Safeguard
Developer Tools•

How do GitLab CI jobs fetch secrets from HashiCorp Vault?

A GitLab job defines an ID token, then the secrets keyword uses it to log in to Vault and read a value. Steps, variables, and the file versus value choice.

Safeguard Security Team
4 min read

A GitLab CI job fetches Vault secrets in two moves. It defines an ID token with the id_tokens keyword, then the secrets keyword uses that token to authenticate to Vault and read the value. No Vault token is stored in GitLab. By default the secret lands in a temporary file.

What happens, step by step

GitLab's Vault integration page describes the flow. Once a job defines at least one ID token, the secrets keyword automatically uses that token to authenticate with Vault. Vault checks the token against a role you configured, and if the claims match, it returns the requested secret to the job.

In plain words, the example from the documentation does this: the job creates a token named VAULT_ID_TOKEN with the Vault URL as audience. A secrets block then defines a variable, such as DATABASE_PASSWORD, which points at a field in a path on a mount, and names the token to authenticate with.

The variables

VariablePurpose
VAULT_SERVER_URLProject CI/CD variable with your Vault server address
VAULT_AUTH_ROLEOptional. Names the Vault role; if unset, Vault falls back to the default role on the auth method

The default secrets engine is KV version 2 unless you set another with the engine name option.

File or value

By default, GitLab writes the secret to a temporary file and puts the file's path in the variable. Setting file to false puts the value directly in the variable instead, so it is not written to a file.

Which is safer depends on the consumer. A file keeps the value out of the process environment, and out of any debug dump of environment variables. A direct value is convenient for tools that only read environment variables. OWASP's secrets guidance notes that environment variables are generally accessible to all processes and may be included in logs or system dumps, which is a good reason to prefer the file where the tool allows it.

Lock down the role

The key security control is on the Vault side. GitLab says bound claims limit access by user, project, or Git reference, and all bound claims must match. It also advises that roles should always be limited to a project or namespace, since otherwise any JWT from the GitLab instance might authenticate.

Steps to a safe setup:

  1. Create a Vault role per project or per purpose, not one shared role.
  2. Bind it to project and namespace identifiers, and to protected refs for production paths.
  3. Give the role a policy that reads only the paths the job needs.
  4. Set a narrow audience on the ID token.
  5. Prefer the file form of the secret unless the tool needs a variable.
  6. Test with a job on an unprotected branch and confirm Vault refuses it.

What this does not solve

The secret still appears on the runner while the job runs. Anything that can run code in the job can read it. Short job timeouts, pinned dependencies, and narrow scopes reduce the exposure. Rotating the underlying secret on a schedule still makes sense, and dynamic secrets, where the backing system issues a fresh credential per request, reduce reuse further.

Quick check

Do I need to store a Vault token in GitLab variables?

No. The job authenticates with its ID token. You still store the Vault server URL, and optionally the role name, as variables.

What happens if I leave out the role?

Vault uses the default role configured on the auth method, so make sure that default is tightly bound or not set.

Safeguard policies and gates can review pull requests that edit CI files, and compliance and evidence automation helps keep proof of access reviews. A free scan is at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.