Apple's Lockdown Mode strips down the attack surface for people who genuinely need it. It turns off JIT in WebKit, blocks most message attachment types, drops FaceTime calls from people you've never been in contact with, and refuses configuration profiles. As a hardening feature, it does its job.
The problem is that any app on your Mac can check whether you've turned it on. It takes one function call, no permissions, and no prompt. The app learns that you're running in a heightened-security mode, and you have no way of knowing it asked.
I reported this to Apple. They closed it as expected behavior. Their position is that Lockdown Mode status isn't private data.
I think that's wrong. Not because the engineering is bad, because it isn't, but because a privacy feature that quietly announces itself to every app on the system isn't fully doing its job.
How it works
There are two ways to read the flag. Both work from inside the App Sandbox with zero entitlements.
flowchart TD
A["Any Sandboxed App\n(zero entitlements)"] -->|Path 1| B["sysctlbyname()\nsecurity.mac.lockdown_mode_state"]
A -->|Path 2| C["LockdownModeManager.shared.enabled\n(LockdownMode.framework)"]
B --> D["AppleLockdownMode.kext\n(kernel)"]
C --> E["LockdownModeXNUC.lockdownModeEnabled"]
E --> D
D --> F["ACM / Secure Enclave\n(boot-time state)"]
D -->|returns| G{"0 = OFF\n1 = ON"}
Path 1: the sysctl
#include <sys/sysctl.h>
#include <stdio.h>
int main(void) {
int enabled = 0;
size_t len = sizeof(enabled);
sysctlbyname("security.mac.lockdown_mode_state",
&enabled, &len, NULL, 0);
printf("Lockdown Mode: %s\n",
enabled ? "ON" : "OFF");
return 0;
}
That's the entire PoC. Compile it, run it, done. security.mac.lockdown_mode_state is a kernel sysctl that AppleLockdownMode.kext sets from the Secure Enclave at boot. It's world-readable, with no entitlement check or TCC prompt in the way and no sandbox exception required.
Path 2: the framework
@import Foundation;
#import <LockdownMode/LockdownMode.h>
int main(void) {
BOOL enabled = [[LockdownModeManager shared] enabled];
NSLog(@"Lockdown Mode: %@",
enabled ? @"ON" : @"OFF");
return 0;
}
Same result through a friendlier API. It wraps the same sysctl and also works from the App Sandbox with nothing granted. The whole check runs in-process against a kernel value. No XPC, no daemon, no network request. So there's nothing for a defender to intercept or audit.
Apple reads it everywhere
I counted 24 system components reading this sysctl, including callservicesd, identityservicesd, and sharingd. The value is world-readable because Apple's own stack needs it all over the place. Third-party apps getting it too is a side effect of that decision.
Why this matters
The thing that actually concerns me is straightforward: any app you install can quietly learn whether you use Lockdown Mode, and report it.
It doesn't take an exploit. An ordinary App Store app, say a weather widget that happens to bundle a third-party analytics SDK — can read the value and send it home, and no permission dialog ever appears.
flowchart LR
subgraph attacker ["Any App"]
M["App Store app\n(or malware)"]
end
subgraph device ["Your Mac"]
S["sysctl read\n(no permission)"]
K["Kernel"]
end
subgraph outcome ["What it learns"]
T["User runs heightened security"]
N["Regular user"]
end
M -->|"1 function call"| S
S --> K
K -->|"returns 1"| T
K -->|"returns 0"| N
For malware, that's a useful signal. Land on a device running Lockdown Mode and you know the user is security-aware and probably worth more careful handling; see it switched off and you're likely dealing with an ordinary user. It's free triage. It's also useful to data brokers and ad-tech building behavioral profiles. "uses extreme security features" is a data point, and the user never agreed to share it.
What bothers me is the principle. You turn Lockdown Mode on precisely because you want more privacy, and the feature then leaks a fact about your security choices to every app on the system. The people who enable it are exactly the people who would object to that leak if they knew about it.
Apple's response
Apple reviewed the report and closed it. Their response:
"We do not consider the Lockdown Mode status itself to be something that we protect or classify as protected private data."
I get the engineering reasoning. Dozens of components check this flag at runtime, and a world-readable kernel value is the simplest, fastest way to hand that state around. FaceTime uses it to decide whether to block unknown callers, WebKit uses it to configure JIT. Adding an entitlement check means touching every one of those consumers and risking new failure modes in security-critical paths.
That's a real tradeoff, and I don't think Apple made it carelessly. But "this needs to be fast" and "this should be readable by Candy Crush" are two different requirements, and right now a single mechanism is serving both.
Fixes that would work
None of these are hard:
- Gate the sysctl behind a private Apple entitlement. Apple already does this for plenty of other sensitive sysctls. The 24 system components that need the value already run with Apple-signed entitlements; third-party apps don't. It's probably a couple of lines in the sysctl handler.
- Return 0 to any caller without that entitlement, regardless of the real state. The kernel already lies to unprivileged callers for other values.
- Move the query behind XPC.
lockdownmodedalready exists and could answer authorized requests with audit logging.
flowchart TD
subgraph current ["Current"]
A1["Any process"] --> B1["sysctl read"]
B1 --> C1["Returns real value"]
end
subgraph fix ["Entitlement Gate"]
A2["Apple-signed process"] --> B2["sysctl read"]
B2 --> C2["Returns real value"]
A3["Third-party app"] --> B3["sysctl read"]
B3 --> C3["Returns 0"]
end
The first option is the obvious one. It's how Apple handles everything else of this kind.
Timeline
| Date | Event |
|---|---|
| March 21, 2026 | Two read paths identified and tested from App Sandbox on macOS 26.4. |
| March 26, 2026 | Submitted to Apple Product Security. |
| March 2026 | Apple closed as expected behavior. |
| May 2026 | Published after Apple confirmed the design decision is final. |
Disclosure
This was reported to Apple through their security researcher portal and closed as expected behavior. Apple doesn't consider it a vulnerability and doesn't intend to change it. No bounty was involved. Publishing it doesn't violate responsible disclosure: there's no unpatched vulnerability, and Apple's position is on the record.
No user data was accessed during this research. The PoC reads only the local device's own state.
This is one of 16 information channels documented in the companion paper, "The Transparent Sandbox: Cataloging macOS App Sandbox Information Disclosure," on farpsec.xyz/research.
Analyst: Maliq Barnard Date: 18 MAY 2026 Platform: macOS 26.5 (build 25F71), Apple Silicon M4
Analyst Notes