A pull request changes a package script. The checking job executes that script as part of the build. If publishing credentials are also available in the job, the code under review has reached an authority boundary before the review is complete.

Review what CI jobs execute

Start with the workflow, then follow package scripts, dependencies, generated commands and checked-out files. A build step can execute more than the application’s own source. Treat that entire execution path according to the trust of the candidate being evaluated.

GitHub’s secure-use guidance covers untrusted workflow inputs, dependency risks, token permissions and dangerous combinations of privileged events with untrusted code. Apply the guidance to the actual events and checkout behavior in the repository. A reassuring workflow name does not establish what authority its steps receive.

Source: GitHub Docs · Secure use reference.

Pass a verified build to publishing

For an illustrative static-site release, the checking job builds and validates output without deployment credentials. A separate trusted publishing procedure accepts a specific successful run and artifact. It verifies the source repository, expected workflow, revision and artifact identity before publishing.

That procedure must not then run a package script from the candidate with a release credential present. Doing so would reopen the boundary it was meant to protect. Any publisher configuration or executable tooling needs a separately controlled source.

Check indirect access to credentials

Artifacts, caches and generated metadata can carry content from one job into another. Decide which inputs the privileged job trusts and validate them accordingly. An artifact containing static files should not become an instruction to execute a bundled shell script.

Branch restrictions, event filters and limited token permissions each cover different parts of the design. Document the assumption behind each one. For example, permitting a release from a particular branch still requires an accurate record of which revision and artifact the operator selected.

Test the separation safely

Use a disposable workflow and synthetic markers to inspect what each stage can access. Never use real secret values as test output. Review the configured permissions and confirm that an untrusted candidate cannot select an arbitrary publishing destination or cause the publisher to execute its code.

  • The checking stage has only the repository permissions it needs.
  • The publishing stage accepts a specific validated candidate.
  • Candidate-controlled text stays data when the publisher handles it.
  • The release record identifies the artifact and destination actually used.
Read more articles