glsec

Rules / GL043

GL043 Unanchored regex on user-controlled variable in rules condition

Severity: warn
OWASP: CICD-SEC-5 – Insufficient PBAC

Risk

GitLab CI rules:if uses =~ for regex matching. A regex without a trailing $ anchor is a prefix (or substring) match — an attacker who controls the matched variable can bypass the condition by crafting a value that satisfies the unanchored pattern.

For example, /^admin/ matches both admin and adminevil. If a job is gated on $GITLAB_USER_LOGIN =~ /^admin/, any user with a login starting with admin can trigger it.

What is flagged

rules:if conditions at job level and under workflow: that use =~ against one of the following user-controlled variables with an unanchored regex:

Variable Controlled by
$GITLAB_USER_LOGIN The user triggering the pipeline
$CI_COMMIT_BRANCH The pusher (branch name)
$CI_COMMIT_REF_NAME The pusher (branch or tag name)
$CI_PROJECT_NAMESPACE The project namespace

Two cases are flagged:

Trigger examples

deploy-prod:
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release/     # prefix match — "release-evil" also matches
  script:
    - ./deploy.sh

privileged-job:
  rules:
    - if: $GITLAB_USER_LOGIN =~ /^admin/      # prefix match — "adminevil" also matches
  script:
    - ./build.sh

restricted:
  rules:
    - if: $CI_PROJECT_NAMESPACE =~ /myteam/   # no anchors — any namespace containing "myteam" matches
  script:
    - ./build.sh

Safe alternative

Use both ^ and $ anchors to require an exact match:

deploy-prod:
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release$/
  script:
    - ./deploy.sh

privileged-job:
  rules:
    - if: $GITLAB_USER_LOGIN =~ /^deploy-bot$/
  script:
    - ./build.sh

restricted:
  rules:
    - if: $CI_PROJECT_NAMESPACE =~ /^myteam$/
  script:
    - ./build.sh

For patterns that intentionally match a family of values (e.g. all release/x.y branches), make the suffix explicit:

deploy-release:
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^release\/\d+\.\d+$/
  script:
    - ./deploy.sh

Notes

Documentation for glsec 1.23.0. Source of this page · Rule implementation