Skip to content

Put the signing key behind a reviewed, tag-only environment - #8

Merged
las7 merged 1 commit into
mainfrom
hardening/signing-environment
Aug 15, 2026
Merged

Put the signing key behind a reviewed, tag-only environment#8
las7 merged 1 commit into
mainfrom
hardening/signing-environment

Conversation

@las7

@las7 las7 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Security hardening for the signing setup, before any key material exists.

The problem with the plan as written

MACOS_* were going to be repository secrets. A repository secret is readable by any workflow in the repository, on any branch, including one added in a push by anyone with write access. This repository is public, has two admins, and has no branch protection on main — I checked.

For an ordinary token that is a bad day. For an Apple Developer ID key it is somebody signing malware that macOS trusts as us, and rotation does not repair it: every binary ever signed with the leaked key has to be re-signed and re-released, and users who already installed one have no way to know. The damage lands on users, not on our infrastructure.

What changed

Created the release-signing environment on this repo with:

  • deployment from cli-v* tags only — not from any branch
  • required reviewer (las7)

and build now names that environment. So the key is reachable exclusively by a tagged release that a human approved, and never by a workflow pushed to a branch.

This gates the Linux legs too. Deliberate: nothing in a release should ship without the same approval, and one click per release is not worth engineering around.

MACOS-SIGNING.md gained the parts that were missing

  • Where the private key may exist — a machine you control, not a shared devbox and not one running coding agents with shell access. Three legitimate locations: your laptop briefly, an encrypted password-manager backup, and the environment secret.
  • Back up the .p12 before shredding. Apple caps how many Developer ID Application certificates an account may hold, so "just make another" is not free, and revoking one invalidates signatures made with it.
  • Read secrets from files, not arguments. A value on a command line is visible in ps to every other process and lands in shell history. All six gh secret set calls now redirect from files.
  • A revocation runbook — revoke, delete the environment secrets, audit which releases were signed and whether each has an approval in the environment's deployment history (GitHub records who approved), re-sign and re-release, and tell users, because a revoked signature makes existing installs fail Gatekeeper.
  • A check users can run — the expected codesign -dv authority and team ID, which is what makes a stolen-certificate build detectable by someone other than us.

Note on the key I generated earlier

I generated a key and CSR at ~/.reachpad-signing on the devbox to save a step. That box runs coding agents with shell access, so by the standard this document now sets, it is the wrong place. Recommend discarding it and generating on your laptop — it costs thirty seconds. Nothing has been uploaded to Apple yet, so there is nothing to revoke.

The plan had the Developer ID key as a repository secret. A repository
secret is readable by any workflow in the repository on any branch,
including one added by anyone with write access — and this repository is
public, has two admins, and has no branch protection on main.

For a token that is a bad day. For an Apple code-signing key it is
somebody signing malware that macOS trusts as us, which rotation does
not repair: every binary ever signed with it has to be re-signed and
re-released, and users who already installed one cannot tell.

The key now lives in a  environment whose rules allow
deployment from cli-v* TAGS only, with a required human reviewer, so it
is reachable only by a tagged release a person approved. The build job
names that environment; the Linux legs are gated too, which is correct —
nothing in a release should ship without the same approval.

MACOS-SIGNING.md gains the parts that were missing: where the private
key is allowed to exist (not a box that runs agents), backing up the
p12 before shredding because Apple caps Developer ID certificates,
reading secret values from files rather than arguments so they stay out
of ps and shell history, a revocation runbook, and the codesign
incantation that lets a user verify a download came from us.

Greentree-Change-Id: 35e2118c4d30b0d1e70a7cea64a5206f
@las7
las7 merged commit 26b7ee8 into main Aug 15, 2026
2 checks passed
@las7
las7 deleted the hardening/signing-environment branch August 15, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant