Notarize the macOS codex CLI binary distributed via npm — un-notarized binary causes syspolicyd / XProtect YARA scanning storm

Open 💬 1 comment Opened May 20, 2026 by majiayu000

Summary

The codex binary shipped via the @openai/codex npm package is signed by OpenAI (TeamIdentifier=2DC432GLL2) but not Apple-notarized. On macOS Sequoia (15+), this causes severe system performance issues when the CLI is invoked frequently (e.g. by schedulers, agent loops, CI runners), because each spawn triggers a full XProtect / YARA scan of the ~193 MB binary.

Evidence

Binary (via fnm-managed Node):

~/.local/share/fnm/node-versions/v25.9.0/installation/lib/node_modules/@openai/codex/node_modules/@openai/codex-darwin-arm64/vendor/aarch64-apple-darwin/codex/codex

codesign -dv shows it is signed:

Identifier=codex
TeamIdentifier=2DC432GLL2
Signed Time=May 19, 2026
Runtime Version=15.5.0

But spctl --assess rejects it (= no Notarization):

$ spctl --assess --type execute /path/to/codex
/path/to/codex: rejected

Symptom

When a scheduler (a custom Go daemon in my case, but applies to cron, launchd, CI, agent loops, etc.) repeatedly spawns short-lived codex exec ... processes, macOS syspolicyd sustains 150-200% CPU continuously, because secassessment cannot cache the result for an un-notarized binary.

Confirmed via sudo sample <syspolicyd-pid>:

DispatchQueue_120: com.apple.security.syspolicy.yara  (concurrent)
DispatchQueue_145: syspolicyd.secassessment.xpc  (concurrent)
DispatchQueue: trust  (serial)

Dominant cost is YARA malware-rule scanning of the 193 MB binary on every fork/exec, plus repeated certificate trust evaluation.

Knock-on effect: trustd runs at 60-70%, systemstatusd and WindowServer get dragged up, system idle drops below 5% even with no user activity. M3 Max chassis becomes uncomfortably hot.

Why this matters

  • Codex CLI is designed to be invoked frequently (agentic loops, scheduled skills, IDE integrations).
  • Every invocation = ~193 MB YARA scan on Sequoia+.
  • This is not a niche edge case — any developer wiring codex into automation hits it.
  • macOS 14+ progressively tightened scan caching for un-notarized binaries; the situation will only get worse on macOS 26.

Workarounds tried (all failed)

  • xattr -dr com.apple.quarantine — no quarantine attributes set (Sequoia uses com.apple.provenance instead)
  • codesign --force --sign - ad-hoc resigning — spctl still rejects
  • sudo spctl --add --label CodexCLI <path> — hangs (deadlock with overloaded syspolicyd); effectively deprecated on macOS 15+
  • sudo launchctl kickstart -k system/com.apple.security.syspolicy — blocked by SIP
  • Adding parent processes to "Developer Tools" privacy whitelist — does not affect YARA scanning of child processes
  • Disabling SIP — works but is a security non-starter

The only real fix is notarization on OpenAI's side.

Requested fix

Submit the macOS-arm64 and macOS-x64 codex binaries shipped inside @openai/codex-darwin-arm64 / @openai/codex-darwin-x64 npm packages for Apple Notarization as part of the release pipeline.

The Codex.app desktop bundle is already notarized, so OpenAI clearly has the signing infrastructure — the CLI build pipeline just needs to add a notarytool submit --wait step after codesigning, then stapler staple the result.

Once notarized, spctl --assess will return accepted: Notarized Developer ID, secassessment will cache the result, and YARA won't re-scan on every spawn. This single change fixes the issue for every developer using codex in automation.

Environment

  • macOS Sequoia 15.5
  • Apple M3 Max
  • Codex CLI: latest from @openai/codex npm
  • Node v25.9.0 (fnm) — same binary triggers the issue regardless of install method

Happy to provide more sampling data, profiling traces, or test pre-release notarized builds.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗