CVE-2021-39885

8.7 HIGH

📋 TL;DR

This is a stored cross-site scripting (XSS) vulnerability in GitLab Enterprise Edition's merge request creation page. Attackers can inject malicious JavaScript into approval rule names, which then executes in victims' browsers when they view affected merge requests. All GitLab EE versions from 13.7 to 14.3.1 are affected unless patched.

💻 Affected Systems

Products:
  • GitLab Enterprise Edition
Versions: 13.7 to 14.1.7 (excluding 14.1.7), 14.2 to 14.2.5 (excluding 14.2.5), 14.3 to 14.3.1 (excluding 14.3.1)
Operating Systems: All
Default Config Vulnerable: ⚠️ Yes
Notes: Only affects GitLab EE, not Community Edition. Requires attacker to have repository access to create merge requests with malicious approval rules.

📦 What is this software?

Gitlab by Gitlab

GitLab is a complete DevOps platform providing source code management, CI/CD pipelines, security scanning, container registry, and collaboration tools used by millions of developers and thousands of enterprises worldwide. As both a cloud-hosted SaaS offering (GitLab.com) and self-managed software, G...

Learn more about Gitlab →

Gitlab by Gitlab

GitLab is a complete DevOps platform providing source code management, CI/CD pipelines, security scanning, container registry, and collaboration tools used by millions of developers and thousands of enterprises worldwide. As both a cloud-hosted SaaS offering (GitLab.com) and self-managed software, G...

Learn more about Gitlab →

Gitlab by Gitlab

GitLab is a complete DevOps platform providing source code management, CI/CD pipelines, security scanning, container registry, and collaboration tools used by millions of developers and thousands of enterprises worldwide. As both a cloud-hosted SaaS offering (GitLab.com) and self-managed software, G...

Learn more about Gitlab →

⚠️ Risk & Real-World Impact

🔴

Worst Case

Attackers could steal session cookies, perform actions as authenticated users, redirect to malicious sites, or compromise user accounts and data.

🟠

Likely Case

Attackers with repository access could target project maintainers to steal credentials, modify code, or exfiltrate sensitive data from merge requests.

🟢

If Mitigated

With proper input validation and output encoding, malicious scripts would be rendered harmless as plain text.

🌐 Internet-Facing: HIGH
🏢 Internal Only: HIGH

🎯 Exploit Status

Public PoC: ⚠️ Yes
Weaponized: LIKELY
Unauthenticated Exploit: ✅ No
Complexity: LOW

Exploit requires authenticated access to create merge requests. Public HackerOne report demonstrates the vulnerability with proof-of-concept.

🛠️ Fix & Mitigation

✅ Official Fix

Patch Version: 14.1.7, 14.2.5, or 14.3.1

Vendor Advisory: https://gitlab.com/gitlab-org/cves/-/blob/master/2021/CVE-2021-39885.json

Restart Required: Yes

Instructions:

1. Backup GitLab instance. 2. Update to GitLab EE 14.1.7, 14.2.5, or 14.3.1 depending on current version. 3. Restart GitLab services. 4. Verify fix by checking version.

🔧 Temporary Workarounds

Disable merge request approval rules

all

Temporarily disable approval rule functionality to prevent exploitation

Not applicable - configure via GitLab admin interface

Implement Content Security Policy

linux

Add CSP headers to restrict script execution

Add to nginx config: add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

🧯 If You Can't Patch

  • Restrict repository access to trusted users only
  • Monitor merge request approval rule names for suspicious content

🔍 How to Verify

Check if Vulnerable:

Check GitLab version against affected ranges: 13.7-14.1.6, 14.2-14.2.4, or 14.3-14.3.0

Check Version:

sudo gitlab-rake gitlab:env:info | grep 'Version:'

Verify Fix Applied:

Confirm version is 14.1.7, 14.2.5, 14.3.1 or later, then test that approval rule names with script tags are properly sanitized

📡 Detection & Monitoring

Log Indicators:

  • Unusual approval rule names containing script tags or JavaScript
  • Multiple merge request creations from single user

Network Indicators:

  • Outbound connections to unknown domains after viewing merge requests

SIEM Query:

source="gitlab" AND (message="*<script>*" OR message="*javascript:*")

🔗 References

📤 Share & Export