PoC Archive PoC Archive
High CVE-2026-33331 (GHSA-7f6v-3gx7-27q8) patched

oRPC OpenAPI Reference Plugin Stored XSS via Unescaped Spec Embedding (CVE-2026-33331)

by Abhay Kumar (GitHub: abhayclasher) · 2026-07-05

Severity
High
CVE
CVE-2026-33331 (GHSA-7f6v-3gx7-27q8)
Category
web
Affected product
middleapi/orpc — OpenAPI documentation reference plugin (packages/openapi/src/plugins/openapi-reference.ts)
Affected versions
All versions prior to v1.13.9 (fixed in v1.13.9)
Disclosed
2026-07-05
Patch status
patched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherAbhay Kumar (GitHub: abhayclasher)
CVE / AdvisoryCVE-2026-33331 (GHSA-7f6v-3gx7-27q8)
Categoryweb
SeverityHigh
CVSS ScoreNot specified in source
StatusPoC
Tagsxss, stored-xss, orpc, openapi, cwe-79, javascript, nodejs, docs-page
RelatedN/A

Affected Target

FieldValue
Software / Systemmiddleapi/orpc — OpenAPI documentation reference plugin (packages/openapi/src/plugins/openapi-reference.ts)
Versions AffectedAll versions prior to v1.13.9 (fixed in v1.13.9)
Language / PlatformJavaScript/TypeScript (Node.js 18+), browser-rendered docs page
Authentication RequiredNo (any party able to influence the OpenAPI spec, e.g. via router definitions)
Network Access RequiredYes

Summary

oRPC’s OpenAPI reference plugin renders the generated API docs page by embedding the OpenAPI spec directly into an inline <script id="spec" type="application/json"> block using JSON.stringify(spec), with no HTML-context encoding. Because JSON.stringify() does not escape < or >, a value under attacker influence — such as info.description — can contain a literal </script> sequence that closes the block early; anything that follows is then parsed by the browser as a new, executable <script> element. The bundled lab spins up both a vulnerable and a patched (v1.13.9-equivalent) docs server so the stored XSS can be triggered and compared side by side, plus a minimal standalone PoC that reproduces the same bug without the full application context.


Vulnerability Details

Root Cause

openapi-reference.ts serializes the OpenAPI spec object with JSON.stringify() and interpolates it directly into an HTML <script type="application/json"> tag without HTML-encoding characters (<, >, /) that are meaningful to the HTML parser, even though they are legal inside a JSON string.

Attack Vector

  1. Attacker controls (or influences) a field of the served OpenAPI spec, such as info.description, e.g. via router/operation metadata that ends up in the generated spec.
  2. Set that field to a payload containing a literal closing tag: "</script><script>alert('XSS')</script>".
  3. When a victim loads the oRPC-generated /docs page, the server embeds the raw JSON into the <script id="spec"> block.
  4. The browser’s HTML parser treats the embedded </script> as closing the JSON block regardless of surrounding quoting, and executes everything after it as a new inline <script> — running the attacker’s JavaScript in the docs page’s origin.

Impact

Stored cross-site scripting in the context of the API documentation page, enabling session/cookie or token theft, arbitrary API calls performed as the victim viewing the docs, and phishing overlays rendered within the trusted docs domain.


Environment / Lab Setup

Target:   middleapi/orpc OpenAPI reference plugin < v1.13.9 (Node.js 18+ app)
Attacker: Web browser; optionally Docker for the containerized lab

Proof of Concept

PoC Script

See app/server.js (full vulnerable + patched docs renderer) and poc/exploit.js (standalone minimal PoC) in this folder, plus docker-compose.yml for the containerized lab.

1
2
3
4
5
cd app
npm install
node server.js
cd poc
node exploit.js

The server embeds a crafted OpenAPI spec (with a malicious info.description) into the docs HTML using the vulnerable JSON.stringify()-only approach; loading /docs fires a JavaScript alert('XSS'), while /docs/safe renders the same payload safely using the patched escapeJsonForHtml() encoder.


Detection & Indicators of Compromise

Signs of compromise:

  • Unexpected alert()/script execution or unexplained outbound requests when viewing internal API docs pages
  • OpenAPI spec fields (info.description, operation summaries/descriptions) containing raw <script> or </script> sequences
  • Docs pages served without Content-Security-Policy restricting inline script execution

Remediation

ActionDetail
Primary fixUpgrade orpc to v1.13.9 or later, which HTML-encodes the embedded JSON via escapeJsonForHtml() before rendering
Interim mitigationApply a strict Content-Security-Policy (no unsafe-inline script) on docs pages, and/or sanitize/validate free-text OpenAPI spec fields before they are served

References


Notes

Mirrored from https://github.com/abhayclasher/CVE-2026-33331 on 2026-07-05.