CI/CD Pipeline Security: 10 Holes Attackers Love
From poisoned dependencies to leaked runner secrets — how to audit and harden your delivery pipeline.

Neeraj Kumar
Cloud & DevOps Engineer
Your pipeline has production credentials, runs arbitrary code from pull requests, and rarely gets a security review. Attackers noticed. After integrating SonarQube and Trivy into enterprise pipelines, here are the ten holes I check first — and how to close them.
The ten holes
- 1. Secrets in code or logs — use AWS Secrets Manager / GitHub OIDC, never env-var dumps. Add secret scanning (gitleaks) to CI.
- 2. pull_request_target abuse — running privileged workflows on untrusted fork code. Never combine it with a checkout of the PR head.
- 3. Unpinned third-party actions — pin to a commit SHA, not a tag someone can move.
- 4. Poisoned dependencies — lock files, OWASP Dependency Check or Snyk on every build, private registry proxy.
- 5. Over-privileged pipeline roles — the deploy job doesn't need AdministratorAccess. Scope IAM to exactly what it deploys.
- 6. Long-lived cloud keys in CI secrets — replace with OIDC federation; tokens live minutes, not years.
- 7. Unscanned container images — Trivy in the pipeline, fail on HIGH/CRITICAL, scan the base image too.
- 8. Shared runners with residue — job A's credentials readable by job B. Use ephemeral runners.
- 9. No branch protection on the pipeline definition itself — Jenkinsfile/workflow changes need review like any code.
- 10. Missing audit trail — you can't investigate what you didn't log. Ship CI logs somewhere immutable.
The minimal hardened GitHub Actions deploy
permissions:
id-token: write # OIDC, no stored AWS keys
contents: read
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/deploy-web
aws-region: ap-south-1Where to start
Don't try to fix all ten at once. The highest ROI order in my experience: OIDC federation first (kills the stolen-key class entirely), then image + dependency scanning, then runner isolation. Each one is a day of work and each one closes a class of incident, not just a single bug.