AIMF Security Research · Report 2 of 2 · Follow-Up

After the Gatekeeper Fail-Open Report: The October 2026 Retest

The original report documented a fail-open that let a revoked-certificate app execute. Re-tested on macOS 26.7.1 and 27.0.1, the app did not execute — in any condition. This report maps what changed, what it means, and what remains unresolved.

Companion page: the original report (August 2026) → · Full paper + evidence: github.com/aimarketingflow/macos-gatekeeper-revocation-bypass · Change discovered incidentally while testing OpenDLP against macOS 27's reworked EndpointSecurity framework — not through targeted follow-up on the original report.

Headline. In every recorded October run, the revoked-certificate ChatGPT artifact was refused — at the DMG-open stage or the app-execution stage, on both tested builds, offline and after cache surgery. The historical fail-open did not reproduce. The most consequential observed change: CRLite, dormant (UseCRLite is disabled) at the time of the original testing, is now active on macOS 27.0.1 (UseCRLite is enabled (via feature flags)).

The Questions the Retest Asked

  1. Does the fail-open still execute? With the revocation responder unreachable, does a revoked-certificate app still run — as it did in July?
  2. Is the verdict stored — and where? If blocked, which local store held the revoked status, and can removing it restore execution?
  3. Does the memory of revocation expire? A cached OCSP response has a nextUpdate deadline. Is it still enforced weeks past that deadline, offline?
  4. Did the dormant layer wake up? The paper documented CRLite present but disabled. Is it still disabled — and does it change the outcome?

Results at a Glance

Historical (July 2026 capture)Pro — 26.7.1 (25G241)Air — 27.0.1 (26A434)
DMG containerOpenedRefused at open (malware-class dialog, reported)Opened in most runs; later runs refused at open
App executionExecuted (fail-open)RefusedRefused
CRLite switchDisabledDisabled (reported)Enabled — enforcement observed
Revocation data on devicePresent, unusedNot foundFilters present
Cause of the block— (no block)source unresolvedcached OCSP verdict

Historical and current tests used differing cache conditions and artifact versions — this is not a matched comparison of builds. "DMG opened" and "app executed" are separate enforcement stages and are reported separately throughout.

Follow-up deck slide: results table — historical executed, Pro and Air refused
The results table from the deck: mounting the installer is not running the application — and in every October condition, the app was refused. Slide 5, follow-up deck (October 2026)

The Machine Remembers the Verdict

The central technical lesson of the retest: "the cache" is not one thing. Revocation verdicts persist in several independent local stores, and — unlike a speed cache — they are enforced offline, without any responder contact. That is precisely why the historical fail-open no longer reproduces: an unreachable responder used to mean "no answer"; now it means "enforce the last answer on file."

App launch request syspolicyd / Gatekeeper assessment trustd trust evaluation ocspcache.sqlite3 per-cert OCSP responses bulk valid list serials / hashes (valid.sqlite3) CRLite filters gated by the feature flag policy + tickets ExecPolicy, notarization REVOKED Revocation6 All four sources are LOCAL — the responder never needs to answer
Follow-up deck slide: the machine remembers the verdict — trust decision engine hub with four stores
The store map from the deck: the trust decision engine consults four independent local memories. Slide 6, follow-up deck (October 2026)
ocspcache.sqlite3Per-certificate OCSP responsesHeld the target's revoked verdict on both machines — enforced far past its own nextUpdate
Bulk validity data (e.g. valid.sqlite3)Bulk serial/hash lists + CRLite metadataRebuilt itself while offline on the Pro; its exact enforcement semantics remain open
TrustStore.sqlite3Trust anchors / policy stateExonerated as the verdict source in the Pro investigation
ExecPolicy + notarization ticketsPrior decisions, stapled stateConsulted by evaluators; not the target's verdict source

Resetting one store is not resetting the machine's memory of the verdict.

Pro Investigation (26.7.1): Clearing the Cache Didn't Restore Execution

Recovery-mode surgery identified and removed the target's revoked OCSP response (ocspcache.sqlite3, certStatus=1) and cleared bulk validity data. On retest with a fresh trustd process, the app was still refused — some other local source held the verdict. Live queries found the certificate's serial and SHA-256 absent from the 73,711-row bulk valid list; whether that absence is itself an enforcement input (an absence-based fail-closed mechanism) remains a hypothesis — absence from one queried table does not establish the lookup path.

Source: reports/2026-10-09_TEST_RESULTS_CONSOLIDATED.md, reports/2026-10-09_FRESH_STATE_VERDICT.md in the evidence repository.

Air Investigation (27.0.1): The Stale Verdict, Enforced

The Air's cached-state test produced the cleanest mechanism evidence of the retest:

OCSPSingleResponse: nextUpdate 65.74 days ago
OCSP status revoked=1 definitive=1 fetchFailed=0 timedOut=0
cert[0]: Revocation =(leaf)[force]> 6
Trust evaluate failure: [leaf Revocation6]

The stored answer was ~66 days past its own freshness date, the responder was unreachable, and the system enforced the last answer on file anyway: the app launch was refused. The October 16 sysdiagnose shows the same cached verdict at 72.96 days past nextUpdate — still enforced, with sibling evaluations showing fetchFailed=1 (responder unreachable at eval time).

Source: evidence/air-2026-10-09_offline-retest-evidence.txt, evidence/air-2026-10-16_dmg-block-evidence.txt.

Follow-up deck slide: Air investigation — cached OCSP response, trust evaluation, execution policy
The Air chain from the deck: cached response → trust evaluation → execution policy. Slide 8, follow-up deck (October 2026)

Two Stages, One Verdict — and an Open Question

STAGE 1 · DMG open XProtect malware analysis Mount volume appears STAGE 2 · App launch signature + trust check Execute process starts Pro 26.7.1 — blocked at STAGE 1 "Malware Blocked and Moved to Trash" (reported) Air 27.0.1 — blocked at STAGE 2 (typical) DMG mounts; app refused (Revocation6) Oct 16 sysdiagnose: the Air ALSO fired the Stage-1 malware block (XProtectMalwareType 10, 4 evaluations) — both paths exist on 27.0.1

The builds refused the target at different stages: the Pro rejected the DMG container itself (malware-class dialog, reported); the Air typically mounted the DMG and refused the app. Sysdiagnose evidence from October 16 shows the Air can also fire the DMG-stage malware block (XProtectMalwareType = 10, four evaluations that day) — so both enforcement paths exist on 27.0.1, and what varies is which stage fires.

Follow-up deck slide: two stages one verdict — Pro malware dialog vs Air installer open, real screenshots
Real captures from the deck: the Pro's DMG-stage malware dialog (left) and the Air's mounted installer (right) — same verdict, different stages. Slide 9, follow-up deck (October 2026)

The October 16 Run, Minute by Minute

The newest Air sysdiagnose captured the exact sequence behind the current screenshots — one evaluation chain, from mount attempt to denial, with the machine offline:

Time (EDT)Event
17:33:53–54Disk image source attached; trustd evaluates the certificate chain
17:33:54.094Cached OCSP response read: nextUpdate 72.96 days ago, revoked=1 definitive=1 — sibling evals show fetchFailed=1 (responder unreachable)
17:33:54.094syspolicyd: Trust evaluate failure: [leaf Revocation6]; SecStaticCode verification fails (trust result 6)
17:33:54.883XProtect completes executable analysis of the DMG: XProtectMalwareType = 10, XProtectShouldTranslocateDMG = 1
17:33:54+Kernel records repeated ES_AUTH_RESULT_DENY events; notarization daemon checks error out (offline)
17:34:29Second DiskImageMounter launch — same revocation verdict, same refusal
17:46:06 / 17:46:45Two more evaluations (-049 DMG from Downloads, then -013 again) — identical outcome

Source: evidence/air-2026-10-16_dmg-block-evidence.txt, extracted from sysdiagnose_2026.10.16_17-46-55-0400_macOS_Mac_26A434.tar.gz. The evidence supports a real denial sequence but does not by itself prove whether every denial was caused by the stale OCSP response, CRLite, XProtect, or an interaction among them — the stale revoked OCSP result is the clearest direct revocation input.

The open question: the Air initially restored and relaunched this same DMG after the revoked verdict was known; after one evaluation it refused it the same way the Pro does. The cache-clear method could not produce a true first-contact state on either machine, so "device history with the certificate" cannot be ruled out as the real variable — state, not version, may explain the stage difference. inconclusive

The Deployment Change: CRLite Is Active on 27.0.1

The paper's §5 documented CRLite as the obvious missing defense: infrastructure present, feature flag off. The retest's runtime captures show the flag state flipped between the two eras:

July 24, 2026 capture:   UseCRLite is disabled (via feature flags)
Oct  9, 2026 capture:    UseCRLite is enabled  (via feature flags)

Apple's published source (Security · SecRevocationServer.c L646–668) shows the gate: when the enforcement predicate is false, the function returns before a CRLite "revoked" verdict is ever applied — the verdict exists but never reaches its consequence. When true, the verdict becomes a formal trust failure and is logged (Enforcing CRLite result).

Claim discipline: the published source contains both branches; this is not a verified 26.7.1→27.0.1 source diff. The before/after evidence is the runtime feature-state messages. CRLite activation is demonstrated on the Air; it has not been proven to be the direct cause of the tested app's denial (the Air's block is traced to the cached OCSP verdict; its ordinary CRLite evaluations returned revoked: 0).
Follow-up deck slide: disabled CRLite result never applied vs enabled CRLite result enforced, with code and runtime log lines
The before/after from the deck: published source with the disabled branch (verdict never applied) vs. the enabled branch (verdict enforced), paired with the real runtime log lines from each era. Slide 12, follow-up deck (October 2026)

What the Evidence Establishes

1 · Stale OCSP enforced offline. A cached revoked verdict, weeks past its own nextUpdate, applied with no network path to the responder.
2 · CRLite active on 27.0.1. The dormant layer now runs — flag enabled, filters present, enforcement messages in the log.
3 · Refocused enforcement. The Pro refused the app even after its identified response cache was removed and trustd was fresh.

What Remains Unresolved

1 · First contact. The only state where execution ever differed — a machine that had never evaluated this certificate — is the one state the retest could not produce. The cache-clear method no longer yields a true fresh verdict history.
2 · The persistent verdict source. The Pro's post-clear block came from an unidentified local store. Absence from one database is not proof of absence.
3 · Causation. The flag flip is fact; whether Apple changed anything because of the report, and whether either release is overall "more secure," remain unproven.

The Apple Exchange

The full ticket thread behind the original report — including Apple's July 28 "intended behavior" response (which confirmed the cached-revoked-response pinning the retest later observed directly) and the August 25 close — is preserved in the public evidence repository: Full ticket thread OE1107167498810 →

Timeline — and Why This Was Published Anyway

WhenWhat
~6 yearsThe fail-open behavior ships; a revoked certificate plus an unreachable responder can end in execution
Summer 2026Reported; closed as intended behavior / not a security boundary. At testing time, the fix already existed on the machine — the CRLite enforcement layer sat disabled
October 2026Same artifact, same test: the flag is enabled; the artifact is refused in every recorded run — at the DMG stage or the app stage, on both tested releases
The close. "We can't prove the report caused the change. We can prove the change is real — and that the record of it now exists. That's why you file the report even when the bounty doesn't come through."
Follow-up deck slide: six years one flag no acknowledgment — timeline from initial shipping to summer 2026 reporting and dismissal to October 2026 observed resolution
The closing timeline from the deck: ~6 years of the behavior, the summer 2026 report and dismissal, the October 2026 observed change. Slide 15, follow-up deck (October 2026)

Evidence Index

ArtifactLocation
Air evidence extracts (Oct 8, 9, 16)evidence/ in the evidence repository
Air sysdiagnose archives (Oct 9, 15, 16) — local only, not committedlocal archive (not published)
Pro test-run reports, recovery guidesreports/ in the evidence repository
Air revocation mechanism handoffhandoff/2026-10-08_AIR_SIDE_REVOCATION_MECHANISM.md
Slide assets + provenance notesslide-assets/ in the evidence repository
Deck slide renders used on this pagerendered from the deck PDFs; images hosted on this site
Original paper + figuresmacos-gatekeeper-revocation-bypass

Claims discipline. No universal-fix claim, no publication-causation claim, no release-ranking claim. Stage separation (DMG open vs. app execution) is maintained throughout. CRLite activation, CRLite lookup, CRLite enforcement, cached OCSP verdicts, notarization, XProtect, and syspolicyd enforcement are treated as separate mechanisms. All claims trace to captured sysdiagnose archives or are labeled reported/hypothesis/open.

AIMF Security Research · Page generated October 27, 2026 · Companion: the original report →