Skip to content

Developer ID sign and notarize the macOS standalone CLI binaries - #1226

Merged
theoephraim merged 4 commits into
mainfrom
sign-macos-cli-binary
Oct 14, 2026
Merged

theoephraim merged 4 commits into
mainfrom
sign-macos-cli-binary

Conversation

@theoephraim

@theoephraim theoephraim commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Replaces #1012, rebuilt against the current release flow.

What

The macOS varlock binaries in the standalone archives (and homebrew) are now Developer ID signed with hardened runtime, a stable identifier (dev.varlock.cli), and notarized. Today they only carry bun's ad-hoc linker signature.

Why

  • Hardened runtime blocks other same-user processes from attaching to varlock and reading resolved secrets out of its memory. Verified with lldb -p against varlock run: ad-hoc attaches, ad-hoc + runtime is refused.
  • Developer ID + stable identifier gives the enclave daemon a designated requirement it can verify and show when it reports the caller chain. An ad-hoc signature's only identity is its cdhash, which changes every build.
  • Notarization only matters for archives downloaded in a browser (brew and install.sh use curl, so no quarantine), but it is cheap once we are signing.

Entitlements

Only com.apple.security.cs.allow-jit is granted. #1012 granted nothing, which runs, but hardened runtime then disables JavaScriptCore's JIT: a CPU-bound loop went from 1.1s to 11.8s. allow-jit restores full speed and still blocks debugger attach (verified). All other exceptions are listed as <false/>, and CI fails if the granted set is anything other than allow-jit.

CI shape

  • New reusable build-cli-binaries-macos.yaml builds the two macOS archives on macos-latest, signs, notarizes, verifies signature/identifier/team/entitlements, checks the archive round-trip (no AppleDouble files, bundled .app signature intact), and smoke tests the arm64 binary.
  • release.yaml and binary-release.yaml build the other five targets on linux with --targets=, download the macOS archives, and append their checksums before cosign signs checksums.txt.
  • binary-release.yaml (re-cuts) now needs a macOS runner and the Apple credentials, since the signed CLI binary can't be recovered from npm. It pulls the darwin helper from @varlock/native-helper-darwin.
  • Preview binaries stay unsigned (cross-compiled on linux, where signing no-ops).

build-binaries.ts

  • --targets= to build a subset, --sign <identity> for Developer ID (ad-hoc otherwise), --no-sign to skip (needed to debug a local build).
  • Local dev builds on macOS are ad-hoc signed with hardened runtime so entitlement regressions show up before a release.
  • Checksums are computed in TS instead of shelling out to sha256sum, which macOS lacks.

Hardened runtime blocks same-user debugger attach to the varlock process.
allow-jit is the only granted exception: without it JavaScriptCore's JIT is
disabled and CPU-bound JS runs ~10x slower. The stable identifier
dev.varlock.cli lets the enclave daemon verify and display the caller.
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

bumpy-frog

The changes in this PR will be included in the next version bump.

patch Patch releases

  • @varlock/native-helper-darwin 1.23.0 → 1.23.1
  • @varlock/native-helper-linux-arm64 1.23.0 → 1.23.1
  • @varlock/native-helper-linux-x64 1.23.0 → 1.23.1
  • @varlock/native-helper-win32-x64 1.23.0 → 1.23.1
  • varlock 1.23.0 → 1.23.1

Bump files in this PR

Click here if you want to add another bump file to this PR


This comment is maintained by bumpy.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
varlock-website 8a22142 Commit Preview URL

Branch Preview URL
Oct 14 2026, 01:28 AM

@pkg-pr-new

pkg-pr-new Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

varlock

npm i https://pkg.pr.new/varlock@1226

@varlock/native-helper-darwin

npm i https://pkg.pr.new/@varlock/native-helper-darwin@1226

@varlock/native-helper-linux-arm64

npm i https://pkg.pr.new/@varlock/native-helper-linux-arm64@1226

@varlock/native-helper-linux-x64

npm i https://pkg.pr.new/@varlock/native-helper-linux-x64@1226

@varlock/native-helper-win32-x64

npm i https://pkg.pr.new/@varlock/native-helper-win32-x64@1226

commit: dea601b

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The macOS release job can publish a CLI binary even when Apple rejects its notarization. Require an Accepted status before uploading the archives.

Reviewed changes: Reviewed the macOS signing workflow, its integration into both release paths, the binary build script, entitlements, and installation documentation.

  • macOS release build: Adds Developer ID signing, hardened runtime, notarization submission, signature and archive verification, and an arm64 smoke test.
  • Release integration: Builds the other five targets on Linux and merges the macOS archives into the cosign-signed checksum manifest for normal releases and manual re-cuts.
  • Build controls: Adds target selection and signing flags, signs local macOS builds ad-hoc by default, and computes checksums in TypeScript.
  • User documentation: Documents standalone macOS signature verification and its distinction from npm installations.

Live signing and notarization were not executed in this Linux review environment; the notarization contract was checked against Apple documentation and existing tooling.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed the notarization acceptance gate added since the previous review.

  • Required Apple acceptance: Changed both architecture submissions to JSON output and blocked archive publication unless each returns Accepted.
  • Added rejection diagnostics: Printed the submission response and attempted to retrieve its notarization log, while retaining a fatal exit if log retrieval fails.

Exercised the actual workflow shell block with mocked notarization responses and real jq. All seven cases passed, covering acceptance, rejection of either architecture, failed diagnostic retrieval, missing fields, malformed JSON, and command failure. Live Apple signing and notarization were not run in this Linux environment.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

The daemon now reads the peer's audit token (LOCAL_PEERTOKEN) and derives
the peer pid from it. A new describe-caller action returns the caller
chain with each process's signing identity: the direct peer resolved by
audit token, ancestors by pid as display-only. Access is still gated by
the binary-name allowlist so npm installs keep working.
@github-actions

Copy link
Copy Markdown
Contributor

📦 Bundle size

⚠️ grows the bundle by 1.1 KB (+0.0%)

Metric main This PR Δ
Total dist 5078.8 KB 5079.8 KB +1.1 KB (+0.0%)
JS 1921.7 KB 1922.1 KB +0.4 KB (+0.0%)
Sourcemaps 3026.4 KB 3027.1 KB +0.7 KB (+0.0%)
Type defs 130.7 KB 130.7 KB —
Other 0.0 KB 0.0 KB —

dist/ only; native binaries are versioned separately and not counted here.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The new caller-identity inspector reports signature validation failures as non-Apple certificate chains instead of invalid signatures.

Reviewed changes: Reviewed the caller-identity functionality added since 942c526.

  • Added caller descriptions: Introduced audit-token inspection of the direct IPC peer and bounded, display-only ancestor traversal.
  • Added signing classification: Reported signature category, signing metadata, hardened runtime, and varlock identity through the new Swift target.
  • Connected IPC and client types: Passed resolved peer information to daemon handlers and added describe-caller with DaemonClient.describeCaller().
  • Added unit coverage: Covered chain traversal, audit-token lookup selection, identity matching, and JSON serialization with fake inspectors.

Swift tests could not run on this Linux runner: swift test --scratch-path /tmp/opencode/varlock-caller-review --filter CallerChainTests failed with no such module 'Darwin'. Checked the relevant Security-framework contracts against Apple's public headers and implementation.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

Parked on the enclave-caller-identity branch.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes: Reviewed the caller-identity rollback in dea601b since the previous review at 96183d3.

  • Removed caller inspection: Removed the Swift signing inspector, caller-chain builder, package targets, and associated tests.
  • Restored session IPC: Restored the optional session-ID handler contract and removed the audit-token peer wrapper.
  • Removed client API: Removed describe-caller, DaemonClient.describeCaller(), and related TypeScript types without leaving source references.

Validated the Swift package manifest with swift package dump-package and checked session-ID propagation through the restored handler. Live macOS runtime, signing, and notarization tests were not run on this Linux runner.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@theoephraim
theoephraim merged commit 6771f0e into main Oct 14, 2026
27 checks passed
theoephraim added a commit that referenced this pull request Oct 19, 2026
* Pin remaining GitHub Actions to commit SHAs and enforce it in CI

#1226 branched before #1229 and reintroduced tag refs in the macOS binary
build plus two download-artifact steps. Pin those, and add a CI check that
fails on any remote action not pinned to a full SHA with a ref comment.

* Drop custom pin check in favor of GitHub's require-SHA-pinning setting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant