CI/CD security engineering

A CI/CD job can read source code, use secrets, create artifacts, and sometimes deploy straight to production. That is a lot of trust in a file most people only open when a build breaks. I read the workflow from an attacker's point of view, then remove the shortcuts that could turn one changed step into a compromised release.

01 / Approach

How I approach CI/CD security.

  1. Read every workflow change

    Workflows run code and often hold more access than the application itself. I review changes to them carefully and pin outside actions so their code cannot change without a visible pull request.

  2. Give each job less access

    A test job should not be able to publish a release. I keep tokens, secrets, runners, and deployment access limited to the few steps that need them.

  3. Protect the release job

    I keep publishing in a small, separate workflow with protected environments and short-lived credentials. A normal code change should not be able to quietly become a production release.

02 / Evidence

Things I have built and changed.

03 / Questions

Questions about CI/CD security.

01

What does CI/CD security cover?

CI/CD security protects the systems that test, build, and release software. It asks who can change a workflow, what outside code runs inside it, where the job runs, and which secrets it can use. It also checks that a release came from the source and build you expected.

OWASP DevSecOps Verification Standard
02

Why pin GitHub Actions to a full commit SHA?

A full commit SHA points to one exact version of an action. A tag can move to different code, either by mistake or after an account is compromised. Pinning does not prove the action is safe, but it makes any code change visible in your workflow.

GitHub Actions secure use reference
03

How should CI/CD permissions be scoped?

Start with read-only access. Give each job only the extra permissions it needs, and keep build access separate from deployment access. For cloud deployments, use short-lived credentials through OIDC instead of storing a long-lived key in the repository.

GitHub guidance on least privilege and OIDC
04

Where should security checks run in a delivery pipeline?

Run quick checks on a developer's machine when possible, then run the required checks again in CI so every change gets the same test. Only reliable findings should block a release. Slower checks can run after a merge or on a schedule.

NIST Secure Software Development Framework

04 / Related

05 / Contact

Working on a problem like this?