Rules / GL026
GL026 git clone/checkout without pinned commit
Severity: warn
OWASP: CICD-SEC-3 – Dependency Chain Abuse
What glsec checks
glsec flags git clone and git checkout invocations in job scripts that use a mutable ref (branch name, tag, or HEAD) instead of a full 40-character commit SHA. Mutable refs can be silently updated between pipeline runs — a compromised upstream repository can inject malicious code into your build without any change to your .gitlab-ci.yml.
Analogous to GL001 (mutable image tag) and GL003 (mutable include: ref), but at the script level. Mirrors ansible-lint's latest rule for VCS module checkouts.
Trigger example
build:
script:
- git clone https://github.com/org/shared-scripts.git # clones HEAD of default branch
- git clone --branch main https://github.com/org/tools.git # mutable branch
- git clone --depth 1 --branch v2.3 https://github.com/org/lib.git # mutable tag
- git checkout develop # mutable branch
Safe alternatives
Clone then pin with SHA checkout:
build:
script:
- git clone https://github.com/org/shared-scripts.git
- git -C shared-scripts checkout a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
Use a Git submodule with a pinned SHA (tracked in .gitmodules + committed HEAD):
build:
script:
- git submodule update --init --recursive
Notes
- A bare
git clone <url>(no--branch) is suppressed when the same job also contains agit checkout <sha>(40-character hex) in any ofbefore_script,script,after_script, or arun:step — that is the intended safe pattern. git checkout -b <name>(local branch creation) does not trigger this rule.git checkout <sha>with a full 40-character SHA does not trigger this rule.- Suppress intentionally mutable checkouts with:
# glsec:ignore GL026 -- upstream repo is trusted and content-addressed by other means.
Documentation for glsec 1.23.0. Source of this page · Rule implementation