A pull-request workflow can execute code supplied by a contributor. Its artifacts are output from that trust level, even if a later privileged workflow downloads them. A file named like a package or test report does not become a trusted release merely by crossing into a protected job. Archive extraction, generated scripts, metadata fields, and path names can each carry hostile input.
Untrusted CI artifacts: separate a pull-request test from promotion
Operational decision
A claims-service repository accepts external pull requests. Run their tests with a read-only token, no deployment secrets, and an isolated runner. A protected workflow may read a structured test result, but must validate its schema, size, path, and relation to the reviewed commit; it must never execute a script from the artifact or promote its binary directly. After merge to a protected branch, rebuild from the reviewed commit in a separate trusted job and bind the resulting digest to that source and builder identity. The text contract makes the handoff explicit. Inject an artifact containing a shell script named like a test report and confirm the protected job rejects it without executing it. Try a path-traversal archive and a mismatched commit identifier as separate cases. A green test run from a fork supports review; it is not the source of production bytes.
Claims release handoff
Pull-request job: read-only token, no secrets, disposable runner
Allowed transfer: bounded JSON test result for reviewed commit
Rejected transfer: executable, archive with unsafe paths, release binary
Protected branch job: fresh checkout and fresh build
Promotion key: trusted build digest plus reviewed source revisionCost and verification
A fresh protected build consumes more CI time and compute than directly reusing a pull-request artifact. The cost buys a clear trust boundary. Validation of untrusted results also takes maintenance; keep the accepted schema small. Record the source revision, producing workflow, artifact digest, and promotion decision separately so an operator can distinguish test evidence from release provenance. A privileged workflow that checks out the contributor's branch and runs it recreates the original risk.
Common Mistakes
- Do not run a downloaded pull-request script in a privileged workflow.
- Do not treat a file name or green badge as proof of release identity.
- Do not let an untrusted archive choose arbitrary extraction paths.
Connected lessons
- DevOps: delivery, infrastructure, and reliable operations
- GitHub Actions: narrow tokens and cloud trust
- CI runner isolation: treat repository code as untrusted
- Software supply chain: SBOM and provenance at admission
- Immutable artifacts and release provenance
