CI/CD pipeline logs are often stored for months and accessible to every team member, contractor, and sometimes even public viewers on open-source projects. A secret printed to a GitHub Actions log — even for one second before a run is cancelled — is captured and searchable. CWE-532 (Insertion of Sensitive Information into Log File) and OWASP A09 (Security Logging and Monitoring Failures) both classify this as a security failure. Rotating a secret that appeared in a CI log is non-trivial because you cannot know who has read or downloaded the log before you noticed the exposure.
High because CI logs are broadly accessible within an organization and often retained for months, giving a long window for secret exfiltration after accidental exposure.
Reference secrets through your CI platform's native secret store, never through shell variables or hard-coded strings in workflow files. Platform-native references are automatically masked in log output.
GitHub Actions — inject via the secrets context:
jobs:
deploy:
steps:
- name: Deploy
env:
STRIPE_SECRET: ${{ secrets.STRIPE_SECRET_KEY }}
run: npm run deploy
GitLab CI — declare variables as masked in project Settings → CI/CD → Variables. Verify masking worked by checking a completed run: the value should appear as *** in every log line.
ID: environment-security.secrets-management.ci-logs-masked
Severity: high
What to look for: Check CI/CD configuration (.github/workflows, .gitlab-ci.yml, .circleci, etc.) for secret masking settings. In GitHub Actions, this is secrets context and env. In GitLab CI, look for secrets or variable masking. In CircleCI, check for Environment Variables and masking flags.
Pass criteria: Count all CI/CD workflow files and enumerate secret references in each. Report the count of masked vs unmasked secrets even on pass. The CI/CD platform is configured to mask known secrets from logs with at least 100% of secret variables using the platform's masking mechanism (e.g., GitHub Actions using secrets.STRIPE_KEY rather than hardcoding).
Fail criteria: CI/CD pipelines print secrets in logs, or no masking configuration found for secret variables.
Skip (N/A) when: The project does not use CI/CD (local builds only, though this is uncommon in production).
Detail on fail: Specify which CI/CD platform and what's missing. Example: "GitHub Actions workflow uses env secrets but does not configure masking" or "GitLab CI logs show API keys in pipeline output".
Remediation: Configure secret masking in your CI/CD platform:
GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
STRIPE_SECRET: ${{ secrets.STRIPE_SECRET_KEY }}
run: npm run deploy
GitLab CI:
deploy:
script:
- npm run deploy
variables:
STRIPE_SECRET: $CI_JOB_TOKEN # masked by default
Verify masking is working by checking a successful pipeline run — the secret value should show as *** in logs.