Repository navigation
Security: bind deploy approvals to the approved commit and artifact - #21
ndbroadbent wants to merge 1 commit into
Conversation
An approval used to authorize "a build" for the token and app, so a
compromised CI job could ship any tarball or image under it: git-sha was
optional (DocSpring CI never sends one), the build's archive wasn't
compared with the upload, and image patterns were optional and unanchored.
Token builds under an approval now:
- must use the archive uploaded under that same approval, chosen
deterministically (no "most recent approved" lookup);
- take the commit from the approval record, never from the client. A
git-sha, if sent, must equal it, and approvals need a full 40-hex SHA;
- may only reference pre-built images tagged <sha> or <sha>-<suffix>.
Services built from source are rejected;
- require service_image_patterns, so the image repository is pinned
too. Patterns are anchored and the substituted commit is regex-escaped.
Also:
- approved_deploy_commands fails closed: an empty list allows no
commands under an approval. The CLI E2E seed stored it as
{"commands": [...]}, which was silently read as empty and so allowed
anything; it now uses the plain array production uses.
- GitHub verification: "branch" mode requires the commit to be on the
feature branch (compare status behind/identical, not any 200),
"latest" mode compares full SHAs, and URL segments are path-escaped.
- CircleCI auto-approve checks the workflow's pipeline revision and
repository against the approval (and rejects fork pipelines) before
approving the hold job. workflow_id must be a UUID.
- CircleCI and GitHub API tokens are no longer stored in River job
args; workers read them from config. The Jobs API redacts token-,
secret-, password- and key-like arg keys.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| JavaScript | Oct 9, 2026 4:01a.m. | Review ↗ | |
| Go | Oct 9, 2026 4:01a.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
This PR is stacked on #19. It fixes RG-06 (plus TOKENS-4/5/6/8/14 and PROXY-6) from the 2026-10-09 audit.
Before, an approval authorized "a build" for a token and app. A compromised CI job could ship any tarball or image under someone's approval of a different commit.
What changes
git-sha, if sent, must match it.<sha>or<sha>-<suffix>. Services built from source are rejected.service_image_patternsis now required, so the image repository is pinned as well as the tag; otherwiseghcr.io/attacker/x:<sha>would pass.approved_deploy_commandsfails closed: an empty list now allows no commands.behindoridentical).vcs_repo, and refuses fork pipelines.river_job.args, and the Jobs API redacts secret-looking keys.service_image_patternsright AFTER this deploysOnce this is deployed, token builds are refused until each rack's
docspringapp has:{"*": "docker\\.io/docspringcom/app:{{GIT_COMMIT}}-amd64"}This matches what CI already produces:
docker.io/docspringcom/app:${CIRCLE_SHA1}-amd64.Do not set it before deploying. The gateway currently in production (v0.1.1) requires a client
git-shawhenever patterns are configured, and DocSpring CI never sends one, so every CI deploy would fail. Deploy this first, then set the patterns immediately.approved_deploy_commandsis already set on all three racks.Testing
approved_deploy_commandswas in the wrong format. It was silently read as an empty list, which the old code treated as "allow anything"; it's now a plain array.task go:test: all pass