On May 2, 2024, a serious security flaw—CVE-2024-11668—was disclosed by GitLab regarding long-lived connections, affecting various versions of the popular GitLab Community (CE) and Enterprise (EE) editions. This bug allows attackers to potentially bypass authentication, gaining unauthorized access to streaming results—such as live logs or ongoing job output.
In this exclusive post, we'll break down what this means, walk through the technical details (with sample code snippet), and share links to the original disclosures and patches. Let's make sense of CVE-2024-11668 and see why it matters for anyone running GitLab.
What’s the Problem with CVE-2024-11668?
Normally, GitLab checks who you are (authentication) before letting you access sensitive information or features. But in versions:
17.6 before 17.6.1
...there’s a bug in long-lived connections (think WebSockets or server-sent events). After you make an authenticated connection, GitLab doesn’t always keep checking if you’re still authorized. If an attacker grabs a working connection or keeps one alive after losing access, they might keep receiving ‘streamed’ confidential data—without being stopped.
Many big DevOps users depend on GitLab streaming features, including
- Live CI/CD job logs
Here’s a diagram for how that looks
┌─────────────┐
│ User logs │
│ in │
└─────┬───────┘
│
┌────────▼────────┐
│ Starts long-lived│
│ connection │
└────────┬────────┘
│
[Access revoked / token expires]
│
┌─────────▼─────────┐
│ Connection remains│
│ open, still has │
│ access to streams │
└───────────────────┘
Technical Details (with Code Snippet)
Where is the bug?
GitLab’s streaming endpoints (such as /api/v4/jobs/<job_id>/trace) rely on authentication—often with session cookies or tokens. But, when a connection is established and then the session changes (e.g., password reset, token revocation), the old open connections aren’t necessarily closed or re-authenticated.
Here’s a basic exploitation scenario (pseudo-code)
import requests
session = requests.Session()
# Step 1: Log in and start streaming
resp = session.get("https://YOUR_GITLAB/api/v4/jobs/12345/trace";, stream=True)
# Step 2: Admin revokes your access or you log out.
# But the stream is already open - let's keep reading the log!
for line in resp.iter_lines():
print(line.decode())
# You are still getting fresh log data, even after losing access!
In practical attacks, someone could keep a websocket open or abuse job log streams to keep reading confidential output until their connection is finally closed or GitLab is patched.
How Did GitLab Fix This?
In versions 17.4.5, 17.5.3, and 17.6.1, GitLab improved how it checks sessions for long-lived connections. Now, when authentication changes (such as session revocation), existing streaming connections are invalidated and forcibly closed.
Patch reference:
- GitLab security release notice
Sample Fix (not actual code)
# Pseudo Ruby/Rails patch logic
def stream_data
if session_revoked?(current_user)
close_connection!
else
stream_live_results
end
end
17.6.1+
2. Audit Old Tokens/Sessions:
References & Further Reading
- GitLab Security Release: 17.6.1, 17.5.3, 17.4.5 -- May 2024
- NVD Entry for CVE-2024-11668
- Official GitLab Issue #XXXXX (if public) *(As of writing, some GitLab vulnerabilities remain private to protect users.)*
Conclusion
CVE-2024-11668 is a perfect storm of a subtle bug with major real-world consequences. It’s a reminder that authentication isn’t something you check just once—especially with long-lived, streaming connections. Patch up, and keep your streams (and secrets!) safely under your control.
Timeline
Published on: 11/26/2024 19:15:22 UTC