Skip to main content
ISSUE-204 Critical Medium CI/CD Variables

Unsafe variable expansion

Control: Pipeline must not use unsafe variable expansion · Config key: pipelineMustNotUseUnsafeVariableExpansion

📋 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 allowedPatterns in .plumber.yaml if the usage is intentional and safe.

✗ Before User-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"
✓ After Variables 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"
# If you have legitimate sh -c usage, allow it in .plumber.yaml:
# pipelineMustNotUseUnsafeVariableExpansion:
# allowedPatterns:
# - "helm.*--set.*\\$CI_"
# - "terraform workspace select.*\\$CI_"

💡 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).

⚙️ Configuration

This control is configured in .plumber.yaml under the key:

controls:
  pipelineMustNotUseUnsafeVariableExpansion:
    enabled: true

See the CLI documentation for the full configuration reference.