A pull request needs enough access to run tests. It usually does not need authority to deploy production, publish a package, or change a signing policy. When those permissions share an execution environment, a malicious dependency or workflow change can reach far beyond the test it was supposed to run.
Two workflows are useful; two trust boundaries are essential
Separating CI and deployment workflows can make permissions easier to review. Separate YAML files alone do not create isolation. The relevant boundaries are the code that executes, the credentials it can obtain, the runner it shares, and the artifacts passed to the next stage.
A merge to the main branch is also not proof that code is safe. Review, protected environments, controlled workflow changes, and artifact verification still matter.
Scope authority to the job
Use minimal repository permissions for untrusted test jobs. Keep deployment credentials and signing authority out of those jobs. Avoid reusing a privileged self-hosted runner for untrusted work without an adequate reset and isolation boundary.
Review what a privileged job consumes. An attacker-controlled script or artifact can cross the boundary even if the deployment workflow itself is trusted. See GitHub’s secure-use guidance.
Pin reviewed dependencies
An immutable commit reference prevents a moved tag from silently selecting different action code. It does not establish that the selected commit is safe. Review updates, retain the expected identifiers, and consider the dependencies that the action downloads at runtime.
First-party scripts also need review and controlled inputs. Moving code into your own repository does not remove its dependencies or make it immune to compromise.
Use short-lived credentials with explicit trust conditions
OIDC federation can replace stored cloud credentials with short-lived credentials issued for an eligible workflow. Configure the cloud trust policy for the intended repository, environment, and other supported claims. Merely enabling OIDC does not enforce those restrictions.
A token or resulting cloud credential can still be stolen or misused during its validity. Limit its permissions and lifetime and protect the job that obtains it. Follow the GitHub OIDC reference for the claims your repository actually emits.
Protect the promotion decision
Keep production approval and policy administration outside the authority of the code being evaluated. Verify the exact artifact that will be promoted, not a rebuilt substitute with the same name. Define what happens when required evidence is missing or verification cannot complete.
An actor allowlist in a shell script is not a substitute for protecting the workflow, credentials, environment, and artifact path that lead to deployment.
Add evidence within the observation boundary
CI/lock can capture configured work and produce evidence for later verification. The available observations depend on the release, platform, capture mode, and permissions. A trace is not a promise that every secret access or network action is visible.
Observation also does not undo an action that already occurred. If code exfiltrates a secret during execution, rejecting a later release cannot recover that secret. Preventive isolation and scoped credentials remain necessary.
Review the boundary with negative cases
Try an untrusted producer, a changed artifact, missing test evidence, and a failed result. Confirm that the relevant gate rejects each case before the protected action. Separately test whether untrusted work can obtain deployment authority or reach sensitive services.
Read the CI/lock trust model, the environment support matrix, and the Pushgate architecture. The platform can manage multiple gates; each gate needs a clearly defined decision and trust boundary.

