Syncing secrets into GitLab CI/CD variables stores them inside the pipeline platform for easier setup, but that increases persistence and exposure. Fetching them at runtime with OIDC keeps credentials out of GitLab, uses short-lived authentication, and injects secrets only for the command that needs them. The runtime approach is better when security and auditability matter more than simplicity.
Why This Matters for Security Teams
Syncing secrets into GitLab CI/CD variables is convenient, but it changes the risk profile by making credentials persistent inside the pipeline platform. Runtime fetch with OIDC shifts the model toward short-lived authentication, narrower exposure, and better auditability. That matters because CI/CD runners are high-value targets, and once a secret is copied into pipeline storage, the blast radius includes configuration drift, over-permissioned jobs, and accidental reuse across stages.
The distinction is not just storage versus retrieval. It is static exposure versus ephemeral access. In environments with frequent builds, shared runners, and multiple maintainers, long-lived variables tend to accumulate until no one can confidently say which job can see what. NHI Management Group’s research on secrets sprawl shows why this is a live issue, not a theoretical one: the State of Secrets Sprawl 2026 found that 59% of compromised machines in a major 2025 supply chain attack were CI/CD runners rather than personal workstations.
In practice, many security teams discover the risk only after a runner or pipeline token has already been reused outside the intended job boundary.
How It Works in Practice
GitLab CI/CD variables store a secret inside GitLab so the job can read it during execution. That is simple to implement, but the secret exists before the job starts, may be readable by multiple pipeline contexts depending on configuration, and often survives far longer than the action that needs it. With OIDC, the job presents a signed workload token to an external identity provider or secret service, proves it is the right pipeline at runtime, and receives a short-lived credential only for the current task.
That runtime pattern is closer to workload identity than to traditional secret storage. The pipeline authenticates as an execution context, not as a reusable bag of credentials. This reduces standing exposure and supports tighter policy decisions such as branch restrictions, environment scoping, and audience matching. It also improves revocation because the credential expires naturally instead of depending on manual cleanup.
- Use GitLab variables only for low-risk values or bootstrapping where persistence is acceptable.
- Use OIDC when the downstream system can trust workload identity and issue ephemeral access on demand.
- Bind the token to specific claims such as project, branch, environment, and audience.
- Keep the lifetime as short as the task allows, then revoke or let it expire automatically.
For a deeper pattern view, see the Guide to the Secret Sprawl Challenge and the OWASP Non-Human Identity Top 10. These controls tend to break down when GitLab jobs need broad legacy integrations that cannot validate OIDC claims or issue short-lived credentials.
Common Variations and Edge Cases
Tighter runtime authentication often increases setup overhead, so organisations have to balance developer convenience against exposure reduction. That tradeoff is real when teams support older deploy targets, mixed cloud estates, or third-party tools that still expect a static API key.
There is no universal standard for this yet, but current guidance suggests using GitLab variables for non-sensitive defaults, bootstrap values, and low-impact configuration, while reserving OIDC-backed fetch for secrets that would be damaging if copied, logged, or reused. The harder cases are multi-stage pipelines and cross-account deployments, where one job may need to hand off trust to another system without exposing the underlying secret.
Two edge cases deserve special attention. First, masked variables are not the same as protected, short-lived credentials; masking limits casual exposure, not persistence. Second, fetching at runtime does not remove all risk if the job itself is compromised, because an attacker can still act within the token’s lifetime. That is why runtime fetch should be paired with minimal scopes, tight job isolation, and rapid expiry.
For context on where secrets are still leaking in modern delivery systems, the CI/CD pipeline exploitation case study shows how pipeline trust is frequently the weak link, and the 52 NHI Breaches Analysis reinforces that static credential exposure remains a repeat failure mode.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10, OWASP Agentic AI Top 10 and CSA MAESTRO address the attack and risk surface, while NIST AI RMF and NIST Zero Trust (SP 800-207) set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-03 | Addresses long-lived secret exposure and weak rotation in CI/CD paths. |
| OWASP Agentic AI Top 10 | A-03 | GitLab jobs act as autonomous workloads needing runtime trust, not static keys. |
| CSA MAESTRO | C3 | Covers identity, authorization, and trust for machine-driven automation. |
| NIST AI RMF | GOVERN | Supports governance for automated systems that access sensitive secrets. |
| NIST Zero Trust (SP 800-207) | PDP | Runtime OIDC reflects request-time authorization instead of standing trust. |
Replace static pipeline secrets with short-lived credentials and enforce automatic rotation.
Related resources from NHI Mgmt Group
- What is the difference between code scanning and runtime identity monitoring?
- What is the difference between storing secrets in docker-compose files and injecting them at runtime from a secrets manager?
- What is the difference between keeping secrets in Sealed Secrets and using an external secrets manager with GitOps?
- What is the difference between Kubernetes Secrets and externally managed secrets for workload access?