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
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-04 |
| Author / Researcher | Abhay Kumar (GitHub: abhayclasher) |
| CVE / Advisory | CVE-2026-33331 (GHSA-7f6v-3gx7-27q8) |
| Category | web |
| Severity | High |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | xss, stored-xss, orpc, openapi, cwe-79, javascript, nodejs, docs-page |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | middleapi/orpc — OpenAPI documentation reference plugin (packages/openapi/src/plugins/openapi-reference.ts) |
| Versions Affected | All versions prior to v1.13.9 (fixed in v1.13.9) |
| Language / Platform | JavaScript/TypeScript (Node.js 18+), browser-rendered docs page |
| Authentication Required | No (any party able to influence the OpenAPI spec, e.g. via router definitions) |
| Network Access Required | Yes |
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
- 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. - Set that field to a payload containing a literal closing tag:
"</script><script>alert('XSS')</script>". - When a victim loads the oRPC-generated
/docspage, the server embeds the raw JSON into the<script id="spec">block. - 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) andpoc/exploit.js(standalone minimal PoC) in this folder, plusdocker-compose.ymlfor the containerized lab.
| |
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
| Action | Detail |
|---|---|
| Primary fix | Upgrade orpc to v1.13.9 or later, which HTML-encodes the embedded JSON via escapeJsonForHtml() before rendering |
| Interim mitigation | Apply 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.