What are common security best practices for CI/CD pipelines?
Key CI/CD security best practices: secret management, least-privilege OIDC tokens, pinned dependencies, isolated runners, scanning gates, and artifact signing.
Expected Interview Answer
Secure a CI/CD pipeline by protecting secrets, enforcing least-privilege access, pinning and verifying dependencies and actions, isolating build environments, and scanning code, dependencies, and artifacts throughout. The pipeline itself is a high-value target because it holds credentials and can push code straight to production, so it must be hardened like production infrastructure.
Concrete practices include storing secrets in a dedicated manager (not in code or plaintext variables) and injecting them at runtime with short-lived, scoped tokens (ideally OIDC federation instead of long-lived keys). Pin third-party actions and dependencies to immutable versions or hashes to prevent supply-chain tampering, run jobs with minimal permissions in ephemeral isolated runners, and require reviews plus branch protection so no single actor can bypass checks. Add SAST, dependency, secret, and container scanning as gates, sign artifacts for provenance (SLSA), and audit every pipeline change. Never expose secrets to pull requests from untrusted forks.
- Prevents credential leaks through proper secret management
- Limits blast radius via least-privilege and scoped tokens
- Defends against supply-chain attacks by pinning dependencies
- Catches vulnerabilities early with automated scanning gates
- Ensures artifact integrity and provenance through signing
- Provides auditability of who changed the pipeline and when
AI Mentor Explanation
Securing a CI/CD pipeline is like guarding the dressing room and pitch keys during a match. Only named staff get access, keys are handed out per session and returned, and no outsider walks onto the square unchecked. If anyone could grab the keys or tamper with the pitch, the whole game is compromised — pipeline security applies the same locked-down, least-access discipline to secrets and deploy rights.
Step-by-Step Explanation
Step 1
Protect secrets
Store credentials in a secrets manager and inject them at runtime; never commit them or print them to logs.
Step 2
Use short-lived, scoped identity
Prefer OIDC federation and least-privilege tokens over long-lived static keys so exposure is limited and temporary.
Step 3
Pin and verify dependencies
Lock third-party actions and packages to immutable versions or hashes to defend against supply-chain tampering.
Step 4
Isolate build environments
Run jobs in ephemeral, isolated runners with minimal permissions, and never expose secrets to untrusted fork PRs.
Step 5
Add security gates
Run SAST, dependency, secret, and container scans as required checks that block merges or deploys on findings.
Step 6
Sign and audit
Sign artifacts for provenance (SLSA) and audit every pipeline change with branch protection and required reviews.
What Interviewer Expects
- Secret management with runtime injection, not plaintext
- Least-privilege and short-lived scoped tokens (OIDC)
- Supply-chain defenses via dependency and action pinning
- Isolated ephemeral runners and untrusted-fork awareness
- Automated scanning gates and artifact signing/provenance
Common Mistakes
- Hardcoding secrets in config files or logging them
- Using long-lived admin tokens with broad scopes
- Referencing third-party actions by mutable tags like @main
- Running untrusted fork PRs with access to secrets
- Treating security scans as optional non-blocking steps
Best Answer (HR Friendly)
“You secure a CI/CD pipeline by keeping passwords and keys in a safe place instead of the code, giving each job only the minimum access it needs and only for a short time, checking that outside code has not been tampered with, and running automated security scans before anything ships. Because the pipeline can push straight to production, it is protected as carefully as production itself.”
Code Example
permissions:
contents: read # minimal by default
id-token: write # enables OIDC token exchange
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# Pin third-party action to a full commit SHA, not a mutable tag
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
# Exchange a short-lived OIDC token for cloud creds - no stored secret key
- uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722
with:
role-to-assume: arn:aws:iam::123456789012:role/ci-deploy
aws-region: us-east-1Follow-up Questions
- How does OIDC federation remove the need for long-lived cloud keys?
- Why pin GitHub Actions to a commit SHA instead of a tag?
- How do you safely handle pull requests from untrusted forks?
- What is SLSA and how does artifact signing help provenance?
- Which security scans belong in a pipeline and where as gates?
MCQ Practice
1. Why should third-party CI actions be pinned to a commit SHA?
Tags are mutable; pinning to an immutable SHA prevents a supply-chain attacker from silently swapping in malicious code.
2. What is the main benefit of OIDC federation in CI/CD?
OIDC exchanges a short-lived, scoped token at runtime, removing the need to store long-lived cloud credentials.
3. Which practice most reduces the blast radius of a compromised job?
Least-privilege scoping ensures a compromised job can do very little, limiting the damage of a breach.
Flash Cards
Where should CI/CD secrets live? — In a dedicated secrets manager, injected at runtime as short-lived scoped tokens — never committed or logged.
Why pin actions/dependencies? — To prevent supply-chain tampering; immutable SHAs or hashes cannot be silently repointed to malicious code.
What is OIDC federation in CI? — A way to exchange a short-lived, scoped identity token at runtime instead of storing long-lived cloud credentials.
What is SLSA? — A framework for supply-chain integrity; signing artifacts establishes verifiable provenance of what was built.