Rules / GL015
GL015 User-controlled variable used as Docker image tag
Severity: warn
OWASP: CICD-SEC-4 – Poisoned Pipeline Execution (PPE)
What glsec checks
glsec flags docker build, docker push, docker tag, and podman commands in scripts that use a user-controlled predefined variable as the image tag (the part after :):
| Variable | Controlled by |
|---|---|
CI_COMMIT_REF_SLUG |
branch / tag name (URL-safe) |
CI_COMMIT_REF_NAME |
branch / tag name |
CI_COMMIT_BRANCH |
branch name |
CI_MERGE_REQUEST_SOURCE_BRANCH_NAME |
MR source branch |
CI_COMMIT_SHA, CI_COMMIT_SHORT_SHA, and CI_PIPELINE_ID are not flagged — they are set by GitLab and are not user-controllable.
Trigger example
build:
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
# A developer can create a branch named "latest" or "main" and
# overwrite the production image tag
Safe alternative
Use the commit SHA as the tag — it is unique, immutable, and not influenced by the branch name:
build:
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
# Optionally also tag as "latest" in a separate step gated to the default branch
Why this matters
Branch names are set by developers with push access. By creating a branch with a strategically chosen name:
- A branch named
latestcauses the job to overwrite thelatestproduction image tag - A branch named
mainormasteroverwrites the tag pulled in production deployments - The resulting image may be pulled by other pipelines or production systems expecting a stable tag
Unlike a SHA-based tag, a branch-name tag is mutable and can be overwritten repeatedly from any branch.
Distinct from GL007
GL007 checks the image: YAML field for variable interpolation. GL015 specifically checks Docker CLI commands in scripts — a job may use a safe image: but still build and push with a dangerous tag.
See also
Enable the ShellCheck integration to surface additional shell issues in these script blocks.
Documentation for glsec 1.23.0. Source of this page · Rule implementation