Published: June 2024
Severity: Medium/High
Affected Products: GitLab CE/EE
Vulnerable Versions:
Summary
In late 2022, a significant vulnerability, CVE-2022-3726, was disclosed in GitLab Community Edition (CE) and Enterprise Edition (EE). The issue? A lack of sandboxing on OpenAPI documents, specifically how GitLab rendered the Swagger OpenAPI viewer. This allowed attackers to craft malicious OpenAPI files which, if viewed by someone in the GitLab web interface, could leverage their authentication to send requests to GitLab or other endpoints — potentially changing settings, modifying account data, or even escalating privileges.
Let’s break down how this happened, what made it risky, and how an attacker could exploit this.
Background: What is OpenAPI and Swagger?
OpenAPI is a standard for describing REST APIs. The most popular UI implementation for OpenAPI documents is called Swagger UI. This tool lets users visually inspect, explore, and try API endpoints directly from their browser.
GitLab, trying to help devs and users, had a feature to display Swagger UI automatically for OpenAPI .yaml files in repos. Nice, right? Except that feature loaded those YAML files untrusted and un-sandboxed inside the authenticated browser session.
The Core Problem
Swagger UI is a JavaScript app. When you load an OpenAPI document, it builds an interface to help you send API requests — often, using the currently logged-in user's credentials.
But: GitLab loaded the Swagger UI for *any* OpenAPI YAML file uploaded into a repo, without sandboxing it.
So: Any attacker could upload a malicious OpenAPI spec that references dangerous or unexpected endpoints, misleading descriptions, or even trick endpoints.
If a victim (maybe a colleague, maintainer, admin) clicked on the OpenAPI file from the GitLab web interface, trusting the pretty interface, it would open Swagger UI. If the victim *clicked any “Try it out”* buttons, requests would be issued using *their authentication* — not the attacker’s.
The Attack: Step-by-step
Here’s how a real-world exploit of CVE-2022-3726 might go down.
1. Upload Malicious OpenAPI File
The attacker creates and commits an OpenAPI YAML file that describes a dangerous endpoint, for example, POST to the victim’s own settings with a payload to change password, API key, or something else.
openapi: 3..
info:
title: Change Password API
version: '1.'
paths:
/-/profile/password:
post:
summary: "Change your password"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
password:
type: string
password_confirmation:
type: string
responses:
'200':
description: Password changed
The attacker might call the API something like “Check your project integration” — social engineering matters.
2. Trick a Victim Into Clicking
The attacker sends a link or PR/Merge Request to a maintainer or dev:
> “Hey, can you check our new API integration? Just click the .yaml and try it out in the browser!”
3. Victim Loads Swagger UI
The victim, while logged in, clicks the OpenAPI YAML. GitLab’s Swagger viewer loads, parses the YAML, and presents the “Try it out” interface, using *the victim’s authentication* (cookie, API token), unless CSRF and other protections block it.
4. Victim Clicks “Try It Out”
If the victim clicks and submits, GitLab’s viewer lets JavaScript send an authenticated API request. Since it’s running in the GitLab domain, and there’s no sandbox — the victim attacks themself.
Exploit PoC
Here’s a minimal “malicious” OpenAPI YAML that, when loaded in GitLab’s Swagger viewer, could send a POST request to the victim’s profile settings (assuming CSRF is not enforced):
openapi: 3..
info:
title: "Update Profile"
version: "1."
paths:
/-/profile:
post:
summary: "Update your profile with dangerous data"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
responses:
'200':
description: "Profile Updated"
Attacker’s instructions to the victim might be:
> “Try updating your integration test user profile via our new API viewer!”
Notes on CSRF and Security Boundaries
Some actions in GitLab require a CSRF token, but many API endpoints do not, and a clever attacker could also use the UI to trick a user into multiple unsafe clicks.
No Sandboxing: The Swagger UI code executed in the same security context as the rest of GitLab.
2. Trust Assumption: GitLab assumed uploaded OpenAPI files would describe *external* APIs, not *GitLab*’s own endpoints.
3. User Trust in UI: Users trusted Swagger UI because it looked official, didn’t realize it used their session cookies/tokens.
4. No Content Security Policy: Mitigations like sandbox iframe restrictions or strong CSPs were not in place.
Patch and Mitigations
GitLab published a security advisory resolving CVE-2022-3726 by:
Rendering OpenAPI documents in a sandboxed iframe
- Disabling dangerous preview and “Try it out” features in Swagger viewer, unless explicitly enabled
Adding warnings if the target endpoints are the GitLab instance itself
Upgrade immediately if you’re using a vulnerable version.
See: GitLab Security Release
Resources and References
- CVE-2022-3726 at NVD
- Original GitLab Advisory
- Swagger UI project
- OpenAPI specification
Final Thoughts
This vulnerability is a great reminder: never trust user-supplied files inside your authenticated app context, especially when using powerful tools like Swagger UI that can submit requests using users’ credentials.
If your platform renders “preview” of user content — especially things describing APIs — always sandbox, validate, and sanitize before letting it loose inside your webapp.
Patch your GitLab now, and if you run any similar code browsing or preview features, check your own sandboxes.
*This article is original content, based on public advisories and analysis. If you learned something, check your own systems for similar features you might be exposing!*
Timeline
Published on: 11/10/2022 00:15:00 UTC
Last modified on: 11/11/2022 01:42:00 UTC