Skip to content

macOS 26/27 taskgated SIGKILL on jcode launch with "Code Signature Invalid" — com.apple.provenance xattr blocks ad-hoc-signed launchers #1233

Description

@KooshaPari

Symptom

On macOS 26 (Tahoe beta 27.0) every jcode invocation is SIGKILLed by taskgated before any code runs:

zsh: killed     jcode
⚡ 137   # exit 137 = 128 + SIGKILL

Crash report namespace is CODESIGNING, indicator is Taskgated Invalid Signature, termination code 1, codeSigningValidationCategory 0, codeSigningTrustLevel 4294967295 (max unsigned).

The binary passes codesign --verify --deep --strict locally and is adhoc (linker) signed, but carries the com.apple.provenance xattr — likely set by a prior macOS install / upgrade / Spotlight ingestion. macOS 26/27 taskgated rejects the launch even though the signature is locally valid.

Reproduction

$ xattr -l ~/.local/bin/jcode
com.apple.provenance:
$ codesign -dv --verbose=4 ~/.local/bin/jcode
Executable=/Users/<user>/.local/bin/jcode
Identifier=jcode
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20400 size=...
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=0 size=12
$ spctl --assess --verbose=4 ~/.local/bin/jcode
~/.local/bin/jcode: rejected

Reproducible 100% across multiple PIDs in ~/Library/Logs/DiagnosticReports/jcode-*.ips — same SIGKILL + namespace=CODESIGNING indicator=Taskgated Invalid Signature.

Workaround (unblocks locally)

xattr -d com.apple.provenance ~/.local/bin/jcode
xattr -d com.apple.quarantine ~/.local/bin/jcode
codesign --force --deep --sign - ~/.local/bin/jcode

Proposed fix

Reference implementation on our fork:

  • branch fix/opencode-go-responses-api at https://github.com/KooshaPari/jcode
  • 3 files, ~+130 lines:
    1. src/main.rs — self_heal_macos_code_signature() runs at the very top of run_main (before Tokio/CLI startup). On macOS, it strips both com.apple.provenance and com.apple.quarantine, then ad-hoc re-signs the current_exe. Best-effort (any failure swallowed because taskgated has already accepted this exec by the time we get here).
    2. scripts/install.sh — same xattr strip + re-sign applied to the staged dest_version_dir/$bin_name AND to the launcher symlink at install time.
    3. crates/jcode-tui/src/tui/app/remote/reconnect.rs:621 — drops the app.has_newer_binary() gate from must_reload_client so a plain PeerClosed reconnect does not re-exec the client on a newer launcher. The legitimate server-reload path is preserved via state.server_reload_in_progress (set only by ServerEvent::Reloading).

Includes regression test test_handle_post_connect_plain_reconnect_does_not_trigger_client_reload_even_with_newer_binary in crates/jcode-tui/src/tui/app/tests/remote_events_reload_01/part_01.rs.

Verification on our fork

  • cargo build -p jcode-tui clean
  • 5/5 test_handle_post_connect_* pass
  • 19/19 reconnect-pattern tests pass
  • Live-tested: xattr -d + codesign --force --sign - on ~/bin/jcode cleared the taskgated rejection, jcode --version runs cleanly, no new crash report.

Environment

  • macOS 27.0 (Tahoe beta)
  • jcode installed at ~/bin/jcode (JCODE_INSTALL_DIR set)
  • Rust toolchain stable, cargo build artifacts at target/debug/jcode

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    autonomous: noNeeds your brain: a product/design decision is required before anyone acts.bugSomething isn't workingtriage: needs-decisionNeeds maintainer decision/design thought

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions