Series · 4 partsmacOS Security BoundariesPart 2 · You are here
  1. 1The App Was Sandboxed. The XPC Boundary Still Needed Authorization.
  2. 2The Permission Was Granted. The Data Use Still Needed a Policy.You are here
  3. 3The Helper Was Registered. Its Lifetime Outlived the App.
  4. 4The Event Was Visible. The Detection Still Needed Context.

When a macOS application asks for the camera, microphone, contacts, calendars, automation, screen recording, accessibility, or Full Disk Access, the platform may place a user or administrator decision between the process and the protected resource. This family of privacy controls is commonly described as TCC: Transparency, Consent, and Control.

That decision is important, but its meaning is narrow. It says that a particular responsible code identity may access a class of protected resource under the platform’s current rules. It does not say that every feature in the application may use every returned record, that a plug-in may inherit the same purpose, or that an upload, model prompt, export, or background workflow is authorized.

The testing mistake is to stop at the system prompt:

The person approved resource access. The application must still authorize each data use.

A defensible review therefore follows the complete chain: declared purpose → requesting binary → system decision → resource handle → data transformation → external effect → retention → revocation. The interesting question is not only whether the prompt appears. It is whether the resulting capability remains bound to the feature, account, destination, duration, and explanation the person understood.

Five controls, five different decisions

TCC is easiest to reason about when it is separated from adjacent controls.

ControlDecision it makesDecision it does not make
Code signingWhich code identity is executing?Is this feature allowed to process this data?
App SandboxWhich resources can this executable reach?Is every reachable object valid for the current workflow?
EntitlementsWhich protected capability may the executable request?Did the person grant it, and is the later use appropriate?
TCC and consentDid the person or administrator allow this protected-resource class?May the app retain, combine, transmit, or repurpose the result?
Application policyWhich feature, account, destination, and state may consume the data?Can it bypass the operating system’s privacy enforcement?

Apple’s guidance for requesting access to protected resources requires an accurate purpose string and describes access as denied by default until the person makes a decision. Some capabilities also require a signed entitlement. Those are complementary gates, not interchangeable ones.

For files, App Sandbox adds another vocabulary. A user-selected file or a security-scoped bookmark can extend a sandboxed process’s access to a specific resource. Apple’s sandbox file-access documentation also notes that other access-control layers can still reject the operation. A reachable URL is a capability. It is not proof that a parser, uploader, helper, or account transition will use it safely.

feature intentWHY · WHEN code identityBINARY · SIGNING TCC decisionGRANT · DENY resource capabilityHANDLE · STREAM use policyFEATURE · ACCOUNT bounded effectLOCAL · REMOTE evidenceOUTCOME · EFFECT lifecycleRETAIN · REVOKE CONSENT IS SCOPEDresource access ≠ unrestricted downstream data use
The system grant creates a capability. Application policy still has to bind that capability to a feature, account, destination, and lifecycle.

Build the privacy surface before touching a setting

On a personal or customer Mac, do not begin by dumping privacy databases or resetting decisions. Start with the application artifact and product documentation. The goal is to understand what the product declares without collecting the person’s actual grants.

For every executable in the supplied app bundle, record:

  • the exact code-signing identifier and designated requirement;
  • sandbox and privacy-sensitive entitlements;
  • usage-description keys and their localized purpose strings;
  • linked frameworks and code paths that request protected resources;
  • XPC services, login items, plug-ins, and extensions involved in the workflow;
  • the feature state in which the request should occur;
  • local consumers, remote destinations, retention rules, and deletion behavior.

Read-only artifact inspection can answer many of these questions:

codesign -d --entitlements :- CustomerApp.app
plutil -p CustomerApp.app/Contents/Info.plist
find CustomerApp.app/Contents -maxdepth 4 -type d -name '*.xpc' -print

These examples intentionally point to a customer-supplied test artifact. They do not justify enumerating the user’s installed applications or opening the per-user TCC database. A personal Mac contains sensitive evidence about the owner’s applications, habits, accounts, and prior decisions; that information is not needed to explain this methodology.

Turn the static inventory into a feature matrix:

FeatureResponsible executableProtected classPrompt triggerPurpose shownReturned capabilityDownstream effect
Voice noteexact client identitymicrophoneexplicit record actionrecord this noteaudio streamlocal draft
Importmain appselected filesopen paneluser selectionscoped URLlocal parser
AutomationXPC client and targetApple Eventsexplicit integration setupcontrol named appevent channelbounded command
Support capturesystem extension or appscreen recordingexplicit support sessioncapture visible screenframe streamapproved case upload

The last column prevents a shallow review. Two products can request the same resource and create very different risk: one transforms a local selection into an ephemeral preview; another sends continuous data to a remote processor and retains it after logout.

Test state transitions, not only the happy prompt

A useful privacy test has controlled states. Use a dedicated test account or disposable test Mac with synthetic contacts, calendars, files, audio, and screen content. Never use the assessor’s personal records as convenient fixtures.

At minimum, exercise:

  1. Undetermined: the feature should explain the action before the operating-system prompt and avoid access before a deliberate gesture.
  2. Denied: the feature should fail closed, preserve unrelated functions, and offer a truthful recovery path without repeatedly coercing the person.
  3. Granted: only the responsible component and requested workflow should receive the capability.
  4. Changed while running: revocation should stop or bound active capture and produce an observable state change.
  5. Account transition: logout, tenant switch, and role reduction should invalidate application authorization even if the system-level grant remains.
  6. Feature disabled: local queues, bookmarks, caches, background jobs, and helper state should no longer continue the data use.

Apple documents tccutil reset for development testing, but that is a state-changing operation. Use it only on the named test identity with an agreed recovery plan—not on a personal laptop merely to make a prompt reappear. Record the exact precondition and expected state; a reset is setup, not proof of a vulnerability.

The dangerous gap is after access succeeds

Once an API returns data, platform consent may no longer distinguish the good and bad application paths. The assessment should follow the object into parsers, shared containers, databases, logs, analytics, XPC calls, cloud requests, exports, and model inputs.

Look for broken bindings:

  • data approved for local preview becomes an automatic remote upload;
  • a security-scoped bookmark remains usable after the project or account is removed;
  • a helper with a broader grant accepts a path or operation from a weaker client;
  • an extension places protected data in a shared container with unnecessary consumers;
  • a denied or revoked state changes UI text but does not stop the active stream;
  • a purpose string describes one feature while a background component performs another;
  • diagnostic logs include filenames, contact values, message bodies, screen text, or stable user IDs.

The correct report does not say “TCC bypass” unless platform enforcement was actually bypassed. Usually the finding is an application authorization, minimization, retention, or transparency failure after legitimate access. Naming the failed boundary accurately makes the remediation both smaller and stronger.

synthetic fixtureNO PERSONAL DATA expected contextFEATURE · ACCOUNT allowed useONE EFFECT wrong featureDENY wrong accountDENY wrong destinationDENY consent revokedSTOP · DISCARD PROOF REQUIRES CONTRASTone intended path plus denied and revoked controls
A granted test is incomplete. Change one authorization variable at a time and prove that mismatched or revoked contexts cannot produce the same effect.

Evidence matrix

ClaimPositive evidenceNegative controlWhat remains unproven
The prompt belongs to the intended featureSynthetic fixture, deliberate gesture, matching purpose string, requesting binary identifiedInvoke unrelated feature; no prompt or accessEvery localization and legacy OS version
Denial fails closedProtected API returns denied and no data-dependent effect occursRepeat action and restart helperThird-party SDK behavior not instrumented
Grant is bound to the active accountIntended account produces one expected local or remote effectSwitch account while platform grant remains; effect deniedServer-side retention outside test access
Revocation stops useActive stream or bookmark access ends and UI state changesReopen stale object or restart background componentFuture OS implementation changes
Logs preserve privacySynthetic marker correlates events while content remains redactedSearch approved diagnostic export for raw fixture valueLogs outside the agreed collection window
Cleanup is completeTest records, bookmarks, caches, queues, and helpers are removedRelaunch and confirm fixture is not resumedPersonal-device privacy state, deliberately not collected

The matrix keeps observation and interpretation separate. A visible prompt proves that a request occurred; it does not prove why a framework requested it. A successful API call proves reachability; it does not prove appropriate retention. A missing log line proves neither absence nor denial unless the expected telemetry path was independently validated.

Remediation should preserve the platform boundary

Good fixes rarely involve weakening macOS privacy controls. They make the application use narrower and more explainable:

  • request access at the moment a person starts the named feature;
  • make every purpose string specific, localized, and consistent with actual downstream use;
  • keep protected processing in the least-privileged component that needs it;
  • pass narrow results across XPC instead of raw data or reusable paths;
  • bind operations to trusted account and feature state, not client-supplied identifiers;
  • discard stale security-scoped bookmarks, queues, and caches on logout or revocation;
  • make background capture visible and independently stoppable;
  • log decisions and effect classes while keeping content and personal identifiers private;
  • document the test state that proves denied and revoked paths remain safe.

TCC is not an application policy engine, and it should not be asked to become one. Its strength is that it places the person and the operating system at the resource boundary. The product’s strength must come from preserving that intent after the resource crosses into application code.

Sources

This is a source-reviewed assessment methodology. It does not claim a TCC bypass, inspect a personal TCC database, or present synthetic controls as findings from a production application.

Sources & freshness

How current is this note?

Sources checkedAugust 30, 2026

The latest source-review, content-update, or publication date is shown.

ReviewPublic sources reviewed

Primary public records were checked. Environment-specific behavior remains outside the claim unless separately reproduced.