Skip to main content
ISSUE-204MediumCI/CD Variables

Unsafe variable expansion

Control:CTRL-204Pipeline must not use unsafe variable expansion

📋 What is this?

A user-controlled CI variable (MR title, commit message, branch name) is expanded in a shell re-interpretation context such as eval, sh -c, bash -c, or source. The expanded value is executed as code, enabling command injection.

⚠️ Impact

An attacker can craft a branch name, MR title, or commit message to inject arbitrary commands into your pipeline. This is a direct path to secret exfiltration, source code theft, and supply chain compromise. Maps to OWASP CICD-SEC-1 (Insufficient Flow Control).

🔧 How to fix

Avoid passing user-controlled variables to commands that re-interpret input as shell code. Use the variable in a safe context (e.g., echo, environment variable assignment) or add the script line to the control's allowedPatterns if the usage is intentional and safe.

✗ BeforeUser-controlled variables are passed to eval, sh -c, and bash -c, enabling command injection.
# .gitlab-ci.yml: ❌ Variables in shell re-interpretation contexts
deploy:
script:
- eval "deploy --branch $CI_COMMIT_BRANCH"
notify:
script:
- sh -c "echo Deploying $CI_MERGE_REQUEST_TITLE"
release:
script:
- bash -c "tag=$CI_COMMIT_REF_NAME; push_release $tag"
✓ AfterVariables are used directly in shell commands without re-interpretation.
# .gitlab-ci.yml: ✅ Variables used in safe contexts
deploy:
script:
- deploy --branch "$CI_COMMIT_BRANCH"
notify:
script:
- echo "Deploying $CI_MERGE_REQUEST_TITLE"
release:
script:
- push_release "$CI_COMMIT_REF_NAME"

💡 Tips

  • Normal shell expansion (echo $CI_COMMIT_BRANCH) is safe. Only re-interpretation contexts (eval, sh -c, bash -c, source) are flagged.
  • Use allowedPatterns (regex) to suppress specific findings for legitimate usages like Helm or Terraform.
  • Escape $ as \\$ and {/} as \\{/\\} in allowedPatterns regex.
  • Indirect aliasing (variables: { B: $CI_COMMIT_BRANCH } then sh -c $B) is not tracked (known limitation).

⚙️ Configure this control

With the CLI alone: set it in your configuration file. Every field and default is in the controls configuration reference, CTRL-204.