Codex CLI v0.120.0 (Rust) hangs at _dyld_start on macOS 26.4.1 Tahoe — Gatekeeper/AppleSystemPolicy blocks Homebrew Cask binary
Open 💬 11 comments Opened Apr 11, 2026 by g-taki
💡 Likely answer: A maintainer (etraut-openai, contributor)
responded on this thread — see the highlighted reply below.
Update (2026-04-12): Original diagnosis was incorrect — the issue is not about code signing format but about missing Apple notarization + macOS 26's persistent quarantine database. Not version-specific (both v0.119.0 and v0.120.0 work when downloaded directly). See my follow-up comment for revised root cause and fix.
What version of Codex is running?
codex-cli 0.120.0 (Rust rewrite, installed via Homebrew Cask)
What subscription do you have?
Plus
Which model were you using?
N/A — binary never launches
What platform is your computer?
macOS 26.4.1 Tahoe (Build 25E253), Mac mini, Apple Silicon
What issue are you seeing?
The Codex CLI binary installed via brew install --cask codex hangs indefinitely on launch. The process gets stuck at _dyld_start — the dynamic linker never loads a single library. No output, no error, no Gatekeeper dialog (accessed via SSH).
Diagnosis:
sampleshows 100% of samples stuck at_dyld_start (in dyld) + 0DYLD_PRINT_LIBRARIES=1produces zero output — no libraries loadedspctl --assess --type executereturns:rejected (the code is valid but does not seem to be an app)com.apple.provenancexattr is present (SIP-protected, cannot be removed)- The binary is validly signed but macOS AppleSystemPolicy silently kills it before dyld completes
Workaround:
Copying the binary to a new location strips com.apple.provenance, then ad-hoc re-signing makes it work:
cp /opt/homebrew/Caskroom/codex/0.120.0/codex-aarch64-apple-darwin /tmp/codex-clean
codesign --force --sign - /tmp/codex-clean
/tmp/codex-clean --version # works: codex-cli 0.120.0
The original binary at the Caskroom path never works regardless of xattr -d com.apple.quarantine or codesign --force -s - in place.
What steps can reproduce the bug?
brew install --cask codexon macOS 26.4.1 Tahoe (25E253)codex --help— hangs indefinitely, no output- Over SSH, no Gatekeeper dialog appears; the process is silently blocked
What is the expected behavior?
The binary should launch normally after Homebrew installation.
Additional information
- This is the same class of issue as #5787 (quarantine/provenance on older versions) and is related to #17225 / #16767 (AppleSystemPolicy blocking Codex processes).
- #17339 reports a similar
dyld startcrash on the same OS build (25E253) for the Desktop app. - Other tools have hit the same macOS 26 Gatekeeper enforcement: anthropics/claude-code#20407, astral-sh/uv#16726 (fixed via post-build ad-hoc codesigning in CI).
- The
uvproject resolved this by addingcodesign --force -s -to their release pipeline (PR astral-sh/uv#17123). A similar fix in the Codex Rust build CI would resolve this permanently.
11 Comments
Thanks for the bug report. Has this worked for you in previous version? I'm trying to determine if this was a regression in 0.120.0 specifically. If you install 0.119.0, does that work for you?
Thanks for looking into this, @etraut-openai.
I did further testing today and the results change the diagnosis significantly:
Version testing:
brew install --cask codex→ hangsSo this is not a regression between versions. Both work fine when downloaded directly.
Root cause (revised):
The issue is the interaction between Homebrew Cask and macOS 26's Gatekeeper:
com.apple.quarantineon the extracted binaryspctl --assess --type executereturnsrejected— the binary is properly signed (Developer ID) but not notarizeddyldeven startsxattr -d com.apple.quarantinedoes not fix it — macOS 26 persists the quarantine state in a system-level database (not just the xattr)Suggested fix:
Submit the release binaries to Apple's notary service (
xcrun notarytool submit). Once notarized, Gatekeeper will allow execution even with quarantine. This would fix Homebrew Cask installs on macOS 26 permanently.Workaround for users:
Use the official install script instead of Homebrew Cask — it downloads directly to
~/.local/bin/without triggering Homebrew's quarantine:I'll also correct my original issue description — the earlier hypothesis about "obsolete code signature format" was wrong. The signing is fine; the missing piece is notarization.
<img width="372" height="374" alt="Image" src="https://github.com/user-attachments/assets/b7804ace-adca-4b72-8bb0-4a41002818f9" />
Interesting. I re-install it via Homebrew today (the same v0.120.0) and it runs without error. Assuming you haven't silently replaced the binary, it might be a glitch at the Apple side?
BTW: you should warn users NEVER run
xattr -d com.apple.quarantinewhen such issue happens :)Confirming this still reproduces on codex-cli 0.122.0 / macOS 26 Tahoe (Darwin 25.3) / Apple Silicon, installed via
brew install --cask codex.One correction to the workaround:
cpdoes not stripcom.apple.provenanceon my system — the xattr is still present on the copied file at/tmp. What actually fixes the hang is the ad-hoc resign alone:After this,
codex --versionworks at the original Caskroom path even thoughcom.apple.provenanceis still on the inode. So the trigger seems to be the combination of the original signature + provenance, not the xattr's presence.Here comes the the weird part: it's not 100% reproducible, even with the same macOS version + Codex CLI version:
codexbinary installed viabrew install --cask codexhas the same SHA256.Thanks for the detailed write-up. cc @iwinux since this appears to match your report/workaround closely.
I hit what looks like the same failure mode on
codex-cli 0.125.0, installed via Homebrew Cask, on macOS 26.4.1 / Darwin 25.4.0 arm64.Symptoms:
codex exec --json ...process appeared to hang before producing any output./opt/homebrew/bin/codex --versionalso hung.sample <pid> 3showed every sample at_dyld_start; no useful Codex/Rust frames.vmmap -summary <pid>reported:``
text
``Process exists but has not started -- it is launched-suspended
codesign --verify --strict --verbose=2passed for the executable.spctl --assess --type execute -vvreported:``
text
``rejected (the code is valid but does not seem to be an app)
origin=Developer ID Application: OpenAI OpCo, LLC (2DC432GLL2)
Quarantine details:
com.apple.quarantinewithHomebrew Caskin the value.xattr -lr /opt/homebrew/Caskroom/codex/0.125.0then showed quarantine still present on the cask version directory.xattr -dr com.apple.quarantine /opt/homebrew/Caskroom/codex/0.125.0, the original executable still launched suspended.The strongest datapoint: a byte-identical copy of the same executable ran normally.
Replacing the original cask executable inode with the byte-identical working copy fixed the Homebrew path:
So in this case it was not a Codex runtime hang. The process was created but never resumed before dyld completed. Clearing visible
com.apple.quarantinewas insufficient; creating a new inode for the same signed bytes fixed it. This seems consistent with macOS 26.4.1 / AppleSystemPolicy retaining launch-blocking state for the original Homebrew Cask artifact outside the normal visible xattr path.(Previous comment removed — posted prematurely before the full fix was identified. This is the corrected version.)
---
macOS 26.4.1 (25E253), Darwin 25.4.0, ARM64 — Codex v0.128.0 via Homebrew Cask — two separate issues, both triggered by the Cask install path
Following up on https://github.com/openai/codex/issues/17447#issuecomment-4329004287 — the inode-replacement fix alone was not sufficient here. The full fix required both ad-hoc re-signing and moving the binary out of the Caskroom directory tree.
Symptoms (identical to OP)
sample <pid>: every sample at_dyld_startvmmap -summary <pid>:"Process exists but has not started -- it is launched-suspended"spctl --assess --type execute -vv:rejected (the code is valid but does not seem to be an app)What was tried, in order
| # | Attempt | Result | Why |
|---|---|---|---|
| 1 |
xattr -d com.apple.quarantineon the binary | Still hung | Block is not stored in visible xattrs || 2 |
xattr -rd com.apple.quarantineon the entire Caskroom tree | Still hung | Same || 3 |
cpbinary to/tmp(fresh inode, clean path) | Still hung | Block had escalated to CDHash level — all copies of those signed bytes blocked system-wide || 4 |
cp+rm+mvto force new inode at original path | Still hung | Same CDHash = same cached block || 5 |
brew reinstall --cask codex| Still hung | Re-downloads identical signed bytes || 6 |
codesign --remove-signature| Killed with SIGKILL (exit 137) — no output at all, even--version| macOS 26.4.1 kills unsigned arm64 Mach-O binaries outright || 7 |
codesign -s -(ad-hoc sign) + run from/tmp| Works from/tmp✅ | Ad-hoc signature avoids both the Developer ID heuristic AND the unsigned-binary kill || 8 | Copy the ad-hoc signed binary into the Caskroom path | Hangs again ❌ | The Caskroom directory itself had
com.apple.quarantine, and binaries placed inside it inherited the launch-suspended behavior || 9 | Place ad-hoc signed binary directly in
/opt/homebrew/bin/+ symlink | Works ✅ | Bypasses the quarantined directory entirely |What actually fixed it
After this,
codex --versionprintscodex-cli 0.128.0and exits 0 normally.Two distinct mechanisms at play
brew reinstall(downloading the same signed bytes) doesn't help.com.apple.quarantinexattr on the Caskroom directory (/opt/homebrew/Caskroom/codex/0.128.0/) propagates to any executable placed inside it, re-triggering the launch-suspension even for binaries that work fine from/tmpor/opt/homebrew/bin/.The earlier inode-replacement workaround likely worked because (a) the block hadn't yet escalated to CDHash-level on that machine and (b) the directory quarantine was cleared first. By the time a machine hits exit-137-on-unsigned behavior, both issues need to be addressed.
Reproduces on Codex 0.130.0 — and the SSH/remote case makes it much worse than a typical Gatekeeper prompt
Adding a data point that highlights why this is more severe than a one-time consent dialog:
codex-cli 0.130.0viabrew install --cask codex— same_dyld_starthang,Process exists but has not started -- it is launched-suspended, signed byOpenAI OpCo, LLC (2DC432GLL2)but not notarization-stapled (xcrun stapler validate→ "does not have a ticket stapled to it").brew upgrade, not a fresh install. Every Cask update re-appliescom.apple.quarantineand re-arms the prompt, so this recurs on every release."codex-aarch64-apple-darwin" is an app downloaded from the Internet. Are you sure you want to open it?) is rendered on the local console, where there's no human to dismiss it. From the SSH side,codexsimply hangs forever with no output, no error, and no indication that a UI prompt is the blocker. Diagnosing it requiressample <pid>(everything at_dyld_start) pluslog show --predicate 'process == "syspolicyd"'to even realize Gatekeeper is involved.This effectively bricks
codexon every CI runner, build server, and remote-dev box on macOS 26 until someone physically (or via remote desktop) clicks "Open" —sshalone cannot recover the machine.The proposed fix earlier in this thread — notarizing release binaries with
xcrun notarytool submit— would resolve this cleanly: notarized + stapled binaries don't trigger the first-launch consent dialog, so headless installs via Homebrew Cask would just work.First, thanks to @g-taki for the meticulous original diagnosis and the revised root-cause writeup, to @cuber for the cleaner in-place resign variant, to @ashwch for the comprehensive workaround that actually unblocked me, to @cossio for the most recent confirmation on 0.130.0, and to @etraut-openai for engaging on triage. This thread is the single best resource on the bug.
Still reproducing on Codex CLI 0.130.0 / macOS 26.4.1 Tahoe (build 25E253) as of 2026-05-15 — and on this machine the simpler in-place resign workaround was not sufficient.
Posting an additional data point because the workaround selection seems to be machine-dependent, and the OS-level signature here is identical to what @g-taki and @ashwch already reported. Hopefully this helps anyone (or any AI coding assistant) landing on this issue while trying to figure out why
codexhangs with no output on macOS Tahoe.Environment
codex-cli 0.130.0installed viabrew install --cask codexOpenAI OpCo, LLC (2DC432GLL2)(Developer ID),xcrun stapler validatereports no notarization ticketSymptoms (matching the OP exactly)
codexinvocation hung indefinitely.codex --version,codex --help, evencodex completion zshandcodex completion fish(spawned automatically by shell startup) all hung. Six unkillablecodex-aarch64-apple-darwinprocesses had silently accumulated through the day — every new terminal that loaded zsh/fish completions spawned another doomed instance.ps -axo pid,stat,wchan,etime,pcpu,command: stateS,WCHANempty, 0% CPU, 41+ minutes elapsedsample <pid> 2 -mayDie: 100% of samples at_dyld_start (in dyld) + 0, physical footprint stuck at 112K, peak 112K (i.e. dyld never loaded a single library)lsof -p <pid>: zero TCP sockets, only the codex binary mapped + dyld + redirected stdio. No network reached, no config loaded.vmmap -summary <pid>: "Process exists but has not started -- it is launched-suspended" (matches @ashwch's report)spctl --assess --type execute -vvon the binary:rejected (the code is valid but does not seem to be an app)SIGTERMignored.SIGKILLeventually landed but took several seconds — consistent with the process being suspended in a mach-port wait for an AppleSystemPolicy verdict that never came.If you're an LLM-assisted developer searching for
codex hangs,codex no output,codex --version hangs forever,codex stuck at dyld start macOS Tahoe,brew install cask codex broken,AppleSystemPolicy launched-suspended,OpenAI codex SIGKILL macOS 26,homebrew codex notarization, orcodex completion zsh hangs— yes, this is the issue, and the comments below contain the fix.Workaround comparison on this machine
| Approach | Result | Notes |
|---|---|---|
|
xattr -d com.apple.quarantineon the binary | Still hung | Quarantine state is persisted at the system policy DB level, not just the xattr (matches @g-taki's revised finding) || @cuber's in-place fix:
cp→codesign --force -s -→mvback to Caskroom | Still hung | Adhoc signature was confirmed (Signature=adhoc, new Identifiercodex-clean-<sha1>),xattrcleared, butcodex --versionstill timed out at 15s. || @ashwch's full fix: move binary out of Caskroom to
/opt/homebrew/bin/, adhoc-sign there, repoint thecodexsymlink, clear Caskroom dir quarantine | Works.codex --versionreturnscodex-cli 0.130.0in ~1.4s, exit 0. |This is consistent with @ashwch's "CDHash-level deny escalation" theory: once
AppleSystemPolicy/syspolicyd/amfidhas cached enough deny decisions for the Developer-ID-signed bytes, the deny is keyed on the code directory hash and propagates to any path that contains those bytes. Only an ad-hoc resign (which produces a fresh CDHash) AND a path outside any quarantined directory clears both layers.Drop-in script for the full fix
For anyone who needs to recover quickly:
This needs to be re-run on every
brew upgrade codexbecause the upgrade replaces the/opt/homebrew/bin/codexsymlink to point back into Caskroom and re-quarantines the binary. A Homebrew Caskpostflightblock in the cask definition would automate this, but the canonical fix is upstream — addingxcrun notarytool submit && xcrun stapler stapleto the Codex release pipeline as @g-taki suggested, the same approachastral-sh/uvtook in astral-sh/uv#17123.Incidental debris worth scrubbing (not the cause of the hang, but accumulates because of it)
Independent of the AppleSystemPolicy block, two pieces of state pile up on machines that have hit this repeatedly. They made initial diagnosis noisier because one of them looked superficially like a stale lockfile, which is a classic Rust-CLI hang pattern:
~/.codex/tmp/arg0/codex-arg0*/and~/.codex/tmp/path/codex-arg0*/— codex's per-invocationcodex-execve-wrapperandapply_patchshim directories. Codex appears to create them at startup as part of its sandbox setup, but they don't get cleaned up when the process is killed in launch-suspended state. I had six of them, the oldest containing a 2-day-old.lockfile.~/.codex/auth.json.codex-auth.YYYYMMDD-HHMMSS— codex backs up auth on every run but never deletes the backups. 12 files had accumulated over ~4 days of failed launches.To clean up safely (
auth.jsonitself is preserved):To be explicit so future readers don't go down the wrong path: the
.lockfile is not the cause of the hang. The hang is the OS-level AppleSystemPolicy block this issue describes. The lockfile is just an artifact left behind by previously-hung invocations.Thanks again to everyone in this thread — it is genuinely one of the more useful OSS bug investigations I have come across. Happy to share additional diagnostic output (full
sampletraces,log show --predicate 'process == "syspolicyd"'excerpts, etc.) if that would help on the OpenAI side.Adding a current data point from macOS arm64 after the
rust-v0.138.0release.This is notable because
0.138.0includes #26252 (ci: sign macOS release artifacts with Azure Key Vault), but the GitHub release artifact still fails local strict code-signing assessment on this machine.Environment:
26.5.1build25F80,arm6426.602.40724build3593codex-cli 0.137.0-alpha.4rust-v0.138.0 / codex-aarch64-apple-darwin.tar.gzhttps://github.com/openai/codex/releases/download/rust-v0.138.0/codex-aarch64-apple-darwin.tar.gzWhat I tested:
Observed:
completion zshsucceeds and emits completions, but strict signing and Gatekeeper assessment still fail:So at least on this machine, the
0.138.0macOS arm64 release artifact is runnable in a direct terminal smoke test, but is still not accepted by strictcodesign/spctl. This looks like the signing/notarization pipeline fix may not yet be reflected in the published single-binary artifact, or the artifact is still missing something Gatekeeper expects.