GitLab CI/CD Specialist study materials
GitLab CI/CD Specialist study resources

GitLab CI/CD Specialist: Variables, secrets, and protected configuration

GitLab CI/CD Specialist · Work through your exam, one topic at a time.

All guide sections

Variables, secrets, and protected configuration

The Variables, secrets, and protected configuration domain tests where values come from, which ones win, and how to keep secrets out of logs and unauthorized refs. Expect questions on precedence, protected and masked variables, file variables, external secrets, OIDC, and job tokens.

Variable sources and precedence

Highest to lowest: pipeline-run variables (manual, scheduled, trigger/API); project variables; group variables; instance variables; job-level YAML variables; global YAML variables; deployment variables; predefined variables. Job-level YAML overrides global YAML. inherit:variables can exclude or include selected global variables for a job.

Protection and secret handling

Protected variables are exposed only to pipelines running on protected branches or tags; protected environments add deployment-side controls. Masked variables are hidden in job logs when their value meets masking rules, but masking is best-effort and not encryption. File variables write the value to a temporary file and expose the path, which suits kubeconfigs or certificate bundles. External secrets can be pulled with secrets: from supported providers such as HashiCorp Vault; OIDC id_tokens provide short-lived identity tokens. CI_JOB_TOKEN is scoped and short-lived and should not be treated as a general-purpose PAT.

Worked example

variables:
  DEPLOY_ENV: staging
deploy:
  stage: deploy
  variables:
    DEPLOY_ENV: production
  environment:
    name: production
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script: ./deploy.sh "$DEPLOY_ENV"

The job-level DEPLOY_ENV overrides the global value, so the script receives production. If PROD_TOKEN is protected, it exists only because this job runs on the default protected branch; on a feature branch the same job would see an empty or undefined variable, not the secret.

Traps

Putting secrets directly in .gitlab-ci.yml exposes them to anyone who can read the repository. Expecting a masked variable with a newline or whitespace to mask correctly is unsafe. Using $CI_COMMIT_BRANCH in a merge request pipeline can evaluate empty; use the MR-specific variables. Pipeline-run variables outrank project variables, so restrict who can run pipelines on protected refs. Undefined variables in rules:if evaluate as null rather than failing loudly.