Skip to content

Nested $variable inside a =~ regex pattern produces an invalid regex and crashes rule evaluation #1893

Description

@abhisekmazumdar

gitlab-ci-local crashes evaluating any rule whose =~ pattern contains a nested $variable reference, for example /^\$TARGET$/. This happens regardless of &&/|| or any other operand in the rule. I first suspected a short-circuit bug (the crash showed up inside an && expression), but a minimal repro shows the && is irrelevant, the =~ match alone is enough.

Minimal reproduction

.gitlab-ci.yml:

variables:
  TARGET: '8.3'
  VERSION: '8.3'

test-job:
  stage: test
  script:
    - echo "hello"
  rules:
    - if: $VERSION =~ '/^\$TARGET$/'
      when: never
    - when: on_success

Run gitlab-ci-local in that directory:

Error attempting to evaluate the following rules:
  rules:
    - if: '"8.3" =~ '/^\"8.3"$/''
as
"8.3".matchRE2JS(RE2JS.compile("^\"8.3"$", 0)) != null

Root cause (from the error output)

$TARGET gets substituted into the regex source as a quoted string literal ($TARGET becomes "8.3"), leaving the pattern text as ^\"8.3"$. The \" sequence isn't a valid escape for RE2 (used via re2js), so RE2JS.compile throws and the whole pipeline evaluation aborts instead of just failing that one rule.

Expected behavior

Some resolution of the regex, either a match/no-match result or a rule-level error, without crashing the whole run. Note this exact YAML pattern (nested variable inside a =~ pattern) is used in production GitLab CI templates today, so real GitLab CI must be handling this substitution differently than gitlab-ci-local does.

Actual behavior

Hard crash. Pipeline evaluation stops entirely.

Environment

gitlab-ci-local 4.73.0, Homebrew, macOS arm64

Real-world impact

This exact pattern is in Drupal.org's shared gitlab_templates project, included by every Drupal contrib module's .gitlab-ci.yml (include.drupalci.main.yml#L495-497):

.check-max-php-version-rule: &check-max-php-version-rule
  if: $CORE_PHP_MIN == $CORE_PHP_MAX && ($PHP_VERSION =~ '/^\$_TARGET_PHP$/' || $PHP_VERSION =~ '/^\$CORE_PHP_MAX$/')
  when: never

This is a shared anchor evaluated during pipeline parsing, so it blocks gitlab-ci-local on any job in any Drupal contrib pipeline that includes these templates, not just the job the anchor was written for.

Possibly related to the regex-handling issues in #932, though that one doesn't show this exact error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions