Hunting secrets in CI/CD pipelines: what we look for

Build logs, cached layers, forgotten workflows. Where credentials really leak in delivery pipelines, and how to close each gap for good.

Your pipeline is the most privileged system most attackers will never be asked about. It can read your source, write your artifacts and deploy to production. So it’s no surprise that credentials collect there.

This post walks through the places we check first when we assess a delivery pipeline, and the fix that closes each one. Everything here is defensive: what to look for in your own environment and how to remediate it.

1. Secrets printed into build logs#

The most common finding is also the simplest. A script echoes its environment, a tool runs in verbose mode, or a failing command dumps its full configuration. The secret ends up in a log that dozens of people can read, often kept for months.

What to check in your own logs:

audit your own CI logs (read-only)

    ci-cli logs export --since 90d --out ./logsexported 1,284 job logsgrep -rIl -E "(AKIA|ghp_|xox[bp]-|-----BEGIN)" ./logs | wc -l3
  

Three matching logs is three incidents to triage: rotate the credential, purge the log, then fix the step that printed it. (ci-cli stands in for your CI provider’s export tool.)

2. Long-lived cloud keys in pipeline variables#

Static access keys stored as pipeline variables are the default in a lot of older setups. They never expire, they’re usually over-privileged, and they’re shared across every job that can read them.

The durable fix is to stop storing them at all. Most CI providers can exchange a short-lived identity token for cloud credentials scoped to a single job:

.github/workflows/deploy.yml
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          role-to-assume: arn:aws:iam::123456789012:role/deploy-prod
          aws-region: us-east-1

After the change, there’s no static key left to leak. Credentials last for the job and nothing else.

3. Secrets baked into container layers#

A secret copied into an image during the build and deleted in a later step is still there. Every layer is kept, and anyone who can pull the image can read the earlier one.

Dockerfile
FROM node:22-slim AS build
WORKDIR /app
RUN --mount=type=secret,id=npm_token NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
COPY . .
RUN npm run build

Build-time secret mounts (line 3) make the value available to a single command without writing it into any layer.

4. Untrusted code running with trusted credentials#

This one is less obvious and usually the most severe. A workflow that runs on pull requests from forks, checks out the contributor’s code, and also has access to deploy secrets lets an outsider’s code read those secrets.

SW-F-0219Critical

Pull-request workflow runs untrusted code with deploy credentials

Asset
.github/workflows/preview.yml
Impact
An outside contributor could read production deploy secrets.
Fix
Split untrusted builds from privileged jobs; scope tokens to read-only.
Validatedexpert reviewIllustrative example, not a client finding

The fix is structural. Build untrusted code in a job with no secrets. If a privileged step must follow, pass it only the artifact, never the checkout.

5. History that remembers#

Removing a secret from the current branch doesn’t remove it from history, forks, caches or old artifacts. Treat any secret that was ever committed as compromised, and rotate it first. Clean up the history afterwards, if at all.

A short checklist#

  • Search the last 90 days of CI logs for credential patterns, and rotate anything you find.
  • Replace static cloud keys with short-lived, job-scoped credentials.
  • Use build secret mounts and never COPY a secret into an image.
  • Never give jobs that run untrusted code access to secrets.
  • Rotate first, clean up second.

Pattern-matching gets you started. The findings that matter most, such as live keys with real blast radius and workflows that hand secrets to strangers, are the ones that need a person to confirm and judge.