Join our Newsletter — 33% off our NHI Course
Home› Guides› OWASP CI/CD Top 10 CICD-SEC-6 Insufficient Credential Hygiene…
Guide Software & AI Supply Chain

OWASP CI/CD Top 10 CICD-SEC-6 Insufficient Credential Hygiene Guide: Managing Secrets in Pipelines

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 26 October 2026 14 min read
On this page

CI/CD systems hold more powerful credentials than almost any other part of the estate, and they spread those credentials into code, logs, images and build hosts. OWASP lists this as CICD-SEC-6 Insufficient Credential Hygiene in the Top 10 CI/CD Security Risks. This guide explains what the risk covers, the five flaws OWASP names, how to move pipelines from stored static secrets to scoped, short-lived credentials, how to assess and measure progress, and how the risk maps to NIST, CIS, ISO and MITRE frameworks. It is written for platform engineers, DevSecOps teams and the owners of pipeline service identities, and goes deeper than the Top 10 CI/CD Security Risks overview.

Key takeaways

  • It is a secrets problem with five faces. OWASP names credentials committed to source control, insecure use inside builds, secrets in container image layers, secrets printed to console output, and unrotated credentials.
  • History outlives deletion. A secret removed from a branch still sits in commit history for anyone with read access, so the only real fix for a committed secret is revocation and rotation.
  • Masking is a safety net, not a control. Both GitHub and GitLab state that log redaction is not guaranteed; transformed, encoded or structured values slip through.
  • Federation beats rotation. OWASP prefers temporary credentials over static ones; OIDC federation from the pipeline to the cloud removes the stored secret altogether.
  • Every pipeline credential is a non-human identity. It needs an owner, a scope, an expiry and an inventory entry, exactly like a service account. See the OWASP NHI Top 10 NHI7 Long-Lived Secrets Guide.

What it is and who it applies to

OWASP defines insufficient credential hygiene as an attacker's ability to obtain and use secrets and tokens spread throughout the pipeline, because of flaws in access controls around credentials, insecure secret management and overly permissive credentials. The entry stresses context: application runtime credentials, deployment credentials used by pipelines to reach production, and credentials engineers use in test environments, code and artefacts all live side by side, and each context offers a different way to leak them.

The risk applies to every organisation that builds or deploys software automatically, whether on hosted services (GitHub Actions, GitLab.com, CircleCI) or self-managed platforms (Jenkins, TeamCity, GitLab self-managed). Hosted services encrypt stored secrets, but they cannot stop a workflow from printing a secret, baking it into an image or granting it more scope than it needs. OWASP's own references show the range: thousands of credentials stored as environment variables stolen through the Codecov breach, secure variables injected into fork pull request builds in the Travis CI secrets exposure, and a GitHub token shown on a public Jenkins environment variables page in the Homebrew token exposure.

CICD-SEC-6 overlaps with its neighbours. OWASP CI/CD Top 10 CICD-SEC-5 Insufficient PBAC Guide decides which secrets a running step can reach; CICD-SEC-6 is about the secrets themselves: where they are stored, how long they live, what they can do and where they leak to.

Structure and key requirements

The OWASP entry has a definition, a description of five flaws, an impact statement, eight recommendations and six real-world references. The table pairs each flaw with the recommendation that addresses it and a practical control.

OWASP flawWhat goes wrongOWASP recommendationPractical control
Credentials pushed to SCMSecret exposed to everyone with read access, and stays in commit history after deletionDetect secrets with an IDE plugin, scanning on every push, and periodic scans of the repository and its past commitsPre-commit hooks, server-side push protection, scheduled full-history scans, revoke then rotate on every finding
Insecure use in build and deployPipelines reach credentials they do not need, including from unreviewed codeScope secrets so each pipeline and step reaches only what it requires; avoid sharing one set across contextsEnvironment-scoped secrets with required reviewers, protected variables, per-job vault roles
Credentials in image layersA build-time secret remains in a layer that anyone who pulls the image can readRemove secrets from all artefacts: image layers, binaries, Helm chartsBuildKit secret mounts instead of build arguments, image scanning before push
Credentials printed to consoleClear-text secrets in build logs, then copied to log management platformsPrevent secrets being printed in future builds and clean existing outputsRegister every derived value for masking, delete affected logs, rotate
Unrotated credentialsDeploy keys and tokens stay valid for years, known to a growing group of people and artefactsPrefer temporary credentials; rotate static ones and detect stale ones; limit use to predetermined conditions such as source IP or identityOIDC federation, expiry on every token, network and identity conditions on cloud roles

The first OWASP recommendation sits above all of these: establish procedures to continuously map credentials across the engineering ecosystem, from code to deployment, and confirm each set has exactly the permissions its consumer needs. Without that map, none of the other controls can be shown to be complete.

Platform features that implement the recommendations

  • GitHub Actions: organisation, repository and environment secrets (limits of 1,000, 100 and 100), encrypted client-side with libsodium sealed boxes. Organisation secrets can be limited to selected repositories, and environment secrets can require reviewer approval before a job receives them. Environment secrets are read only when a job referencing the environment starts. GitHub notes that anyone with write access to a repository can read all secrets configured in it.
  • GitLab CI/CD: the Protect variable option limits a variable to pipelines on protected branches or tags. Visibility can be Visible, Masked or Masked and hidden; masked values must be a single line of at least 8 characters, and hidden values cannot be revealed in the UI after saving. By default, pipelines from forks cannot access the parent project's variables.
  • Jenkins: credentials (secret text, username and password, secret file, SSH key, certificate) are stored encrypted on the controller and bound into builds through the Credentials Binding plugin. Use the narrowest scope (Global for pipeline items, System for controller functions) and restrict who holds Credentials > Create through Matrix-based security.
  • Container builds: Docker's documentation warns that build arguments and environment variables persist in the final image. Use docker build --secret with RUN --mount=type=secret, which mounts the secret at /run/secrets/<id> for that instruction only, and --ssh for Git access during builds.

Identity and NHI requirements

Every credential in a pipeline authenticates a machine, a bot or a workflow, which makes CICD-SEC-6 a non-human identity problem as much as a secrets problem. The same lifecycle questions apply: who owns this credential, what can it do, where is it used, when does it expire and who will notice if it is abused.

Credential typeTypical CI/CD usePreferred replacement or control
Static cloud access keysDeploying infrastructure and artefactsOIDC federation to a cloud role; GitHub states the cloud token is valid for a single job and then expires. See the Workload Identity Federation Guide.
Personal access tokensCross-repository checkout, release automation, botsGitHub App or fine-grained token with minimum permissions and expiry; GitHub recommends Apps because they are not tied to a user who may leave
Deploy keysRead or write access to one repositoryRead-only by default, one key per repository and purpose, recorded rotation date
Package registry tokensPublishing npm, PyPI or container imagesTrusted publishing through OIDC where the registry supports it; otherwise scoped, expiring tokens held in a protected environment
Signing keysSigning releases and artefactsHSM or managed signing service, never a general CI variable
Platform job tokensGITHUB_TOKEN, CI_JOB_TOKENSet default permissions to read-only and grant write per job
  • Federation trust policy: the job needs the id-token: write permission to request the OIDC token. The cloud role must then check the subject claim, for example repo:octo-org/octo-repo:environment:prod, so that only the intended repository, branch or environment can assume it. A wildcard subject turns federation into a shared credential.
  • Conditions on static credentials: where a static key must remain, OWASP asks for use to be limited to predetermined conditions such as a source IP range or identity; in AWS that means policy conditions such as aws:SourceIp or aws:SourceVpc.
  • No shared credentials: OWASP warns that sharing one credential across contexts undermines least privilege and accountability. One credential, one pipeline, one environment. See the OWASP NHI Top 10 NHI9 NHI Reuse Guide.
  • Leak response as an identity process: a leaked pipeline secret is handled like any exposed NHI credential: revoke, rotate, review usage logs for the exposure window. See the OWASP NHI Top 10 NHI2 Secret Leakage Guide.

For the wider picture of how pipelines authenticate, see the CI/CD Pipeline Identity Security Guide.

Implementation steps

  1. Inventory every pipeline credential. Export secrets and variables from each CI platform (organisation, repository, environment, group and folder level), list deploy keys, bot accounts and tokens, and record owner, consumer, scope, creation date and last use. This is the continuous mapping OWASP asks for.
  2. Stop new leaks at the source. Turn on push protection or a pre-receive secret scanner for all repositories, add pre-commit scanning for developers, and enable GitLab's Prevent pushing secret files push rule where applicable. Run in audit mode for two weeks to tune false positives before blocking. See the Git Secret Scanning Guide.
  3. Scan history and artefacts once, fully. Scan every repository's full commit history, existing build logs, container images in registries and Helm charts. Treat each live finding as an incident: revoke, rotate, then remove from history if required.
  4. Replace static cloud credentials with federation. Start with production deployment pipelines. Create one role per pipeline and environment with a strict subject condition, run the federated and static paths in parallel for one release, then delete the static key. Roll back by re-enabling the static key from the vault, never by widening the trust policy.
  5. Scope what remains. Move production secrets into environments with required reviewers or protected variables, restrict organisation secrets to named repositories, and remove secrets from jobs that run untrusted code such as fork pull requests and dependency installation.
  6. Fix logging behaviour. Register every derived value (JWTs, Base64 forms, URL-encoded forms) with ::add-mask:: or the platform equivalent, never store structured JSON or YAML blobs as a single secret, disable debug options that print environment data, and delete any log that contained a secret before rotating it.
  7. Harden image builds. Replace ARG and ENV secrets with secret mounts, add an image secret scan as a gate before push, and rebuild any published image found to contain credentials.
  8. Set expiry and rotation for every static credential. Apply a maximum lifetime (for example 90 days for tokens with write scope), automate rotation through the secrets manager, and alert on stale credentials unused for 30 days. See the Secrets Rotation Runbook Template.

Choosing an approach

  • Small teams on a hosted CI service: native secrets plus environment protection, push protection and OIDC to one cloud provider cover most of the risk with no extra infrastructure.
  • Large or multi-platform estates: a central secrets manager or vault issuing dynamic, per-job credentials gives one inventory, one audit trail and consistent rotation across Jenkins, GitLab and GitHub. See the Secrets Management Guide.
  • Third-party targets without federation: keep the static secret, but scope it to one environment, add network conditions on the target side, and rotate on a schedule.

Evidence and assessment

Assessors and internal audit should be able to see, for any pipeline, which credentials it holds, why, and when they last changed. Useful evidence includes the credential inventory export, secret scanning and push protection reports with bypass records, cloud trust policy definitions, and rotation logs from the secrets manager.

MetricHow to measureTarget direction
Share of deployment pipelines using federated or dynamic credentialsPipelines with OIDC or vault dynamic secrets divided by all deploying pipelinesRising towards 100 percent for cloud targets
Static credentials older than policyInventory entries past their maximum lifetimeZero
Mean time to revoke a leaked secretFrom scanner alert to confirmed revocationHours, not days
Push protection bypassesBypass events per month and the share with reason "I'll fix it later" still openFalling, with every open bypass owned
Secrets shared across pipelinesCredentials referenced by more than one pipeline or environmentFalling
Images and logs with secretsFindings from registry and log scans per monthZero after the initial clean-up

Detection: monitor audit events for secret changes (GitHub logs org.update_actions_secret for organisation secrets), cloud authentication events for CI roles from unexpected subjects or networks, use of CI credentials outside pipeline run windows, and new or unusual consumers of package registry and signing credentials. The OWASP CI/CD Top 10 CICD-SEC-10 Insufficient Logging and Visibility Guide covers the logging side in depth.

Mapping to other frameworks

FrameworkReferenceRelevance to CICD-SEC-6
NIST CSF 2.0PR.AA-01, PR.AA-05, PR.DS-01Credentials for services managed; access permissions defined and reviewed; data at rest protected
NIST SP 800-53 Rev. 5IA-5, IA-5(7), SC-12, SC-28, AC-6Authenticator management; no embedded unencrypted static authenticators; key management; protection at rest; least privilege
CIS Controls v8.1Control 3 Data Protection, Control 5 Account Management, Control 6 Access Control Management, Control 16 Application Software SecuritySecret handling, service account lifecycle, least privilege, secure development pipeline
ISO/IEC 27001:2022 Annex A5.17 Authentication information, 8.4 Access to source code, 8.24 Use of cryptography, 8.25 Secure development life cycleManaging secrets, protecting repositories, keys, secure build practice
MITRE ATT&CKT1552.001 Credentials In Files, T1552.004 Private Keys, T1213.003 Code Repositories, T1078.004 Cloud Accounts, T1528 Steal Application Access TokenHow attackers find and use leaked pipeline credentials
MITRE D3FENDD3-CRO Credential Rotation, D3-CR Credential Revocation, D3-CTS Credential Transmission ScopingDefensive techniques that limit the life and reach of a leaked credential
OWASP NHI Top 10NHI2 Secret Leakage, NHI7 Long-Lived Secrets, NHI9 NHI ReuseThe same failure seen from the identity side

Common pitfalls

  • Deleting the commit instead of rotating the secret. OWASP notes the credential remains in history; clones, forks and caches already hold it. Revocation is the fix, history rewriting is housekeeping. The Uber 2016 breach began with an AWS key committed to a private GitHub repository.
  • Trusting masking. GitHub states that the runner only redacts secrets used in the current job and that transformed values may escape; GitLab notes that shell escaping defeats masking. A JWT minted from a private key and never registered for masking will print in clear.
  • Secrets as environment variables for every step. The Codecov breach worked because a coverage uploader ran in jobs that held cloud keys, tokens and signing material as environment variables. Scope secrets to the step that needs them.
  • Secrets reachable by untrusted builds. The Travis CI exposure gave fork pull request builds access to public projects' secrets for about a week. Fork and dependency jobs should run with no secrets at all.
  • CI configuration pages as a leak path. In the Homebrew token exposure, a public Jenkins environment variables page revealed a bot token with push access to core repositories. Check what your CI UI shows to anonymous and read-only users.
  • "If it isn't broken, don't fix it" deploy keys. OWASP highlights deploy keys left unrotated for years. If rotation would break a pipeline, that pipeline is undocumented, which is a finding in itself.

Practitioner checklist

  • Maintain an inventory of every pipeline credential with owner, scope, consumer, creation date and last use.
  • Enable push protection or pre-receive secret scanning on all repositories and review every bypass.
  • Scan full commit history, build logs, container images and Helm charts, and revoke every live finding.
  • Replace static cloud keys in deployment pipelines with OIDC federation and strict subject conditions.
  • Put production secrets behind environments with required reviewers or protected variables.
  • Run fork, pull request and dependency installation jobs with no secrets.
  • Register derived values for masking, avoid structured secrets, and delete any log that exposed a secret.
  • Use BuildKit secret mounts, never build arguments, for credentials needed during image builds.
  • Set maximum lifetimes for static tokens and alert on credentials unused for 30 days.
  • Keep signing keys in an HSM or managed signing service, outside general CI variables.

Standards and references

Related NHI Mgmt Group resources: Top 10 CI/CD Security Risks · OWASP NHI Top 10 NHI2 Secret Leakage Guide · OWASP NHI Top 10 NHI7 Long-Lived Secrets Guide · Secrets Management Guide · OWASP CI/CD Top 10 CICD-SEC-7 Insecure System Configuration Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 26 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.