CI/CD · Ship safely, repeatedly

How do you secure a CI/CD pipeline from untrusted code?

Hardpipeline securityleast privilegeciUpdated Oct 2026
Quiz this track

Short answer

Treat pull request code as untrusted. Run it on isolated runners without production secrets, grant minimal token permissions, pin third-party actions, require review, and separate untrusted validation from trusted deployment.

A pipeline often has the keys to production. If a fork pull request can execute arbitrary code in a job that holds those keys, the attacker does not need to compromise the application. They can use the pipeline directly.

  • Set the workflow token to read-only by default and grant write permissions per job
  • Never expose production secrets to pull requests from forks or untrusted branches
  • Pin third-party actions and plugins to a commit SHA, not a mutable tag
  • Run untrusted builds on ephemeral isolated runners with no shared credentials
  • Require review and protected environments for deployment jobs
  • Audit pipeline configuration changes like production code changes
yaml
permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@<pinned-sha>
      - run: npm ci
      - run: npm test
A common attack is the pwn request: a workflow checks out and runs code from a fork while holding a privileged token. Separate the privileged workflow from the untrusted checkout, or require approval before it runs.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What is the pwn request attack pattern?
  2. 2Why pin an action to a SHA instead of a version tag?
  3. 3How do you allow external contributors without exposing secrets?
  4. 4What should a runner be allowed to access?

Say it in the interview

I treat any pull request code as untrusted because the pipeline holds valuable credentials. The workflow token is read-only by default, secrets are unavailable to fork builds, and deployment jobs live in a separate privileged workflow behind approval. I pin actions to SHAs and use ephemeral runners. The key principle is that untrusted validation and trusted deployment must not share the same credential context.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live CI/CD mock interview and get scored feedback on depth, clarity and confidence.