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