Skip to content

Commit 6012034

Browse files
1 parent 1a157e7 commit 6012034

2 files changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-76pc-mqxp-3rq5",
4+
"modified": "2026-08-14T21:43:55Z",
5+
"published": "2026-08-14T21:43:54Z",
6+
"aliases": [
7+
"CVE-2026-55156"
8+
],
9+
"summary": "Token Optimizer MCP: Unauthenticated Path Traversal in Dashboard Session Log API Endpoints",
10+
"details": "# Unauthenticated Path Traversal in Dashboard Session Log API Endpoints\n\n| Field | Value |\n| ---------------- | ----- |\n| Repository | ooples/token-optimizer-mcp |\n| Affected version | 5.0.1 (commit 8137147) |\n| Vulnerability | CWE-22 — Improper Limitation of a Pathname to a Restricted Directory |\n| Severity | Medium |\n| CVSS 3.1 | 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |\n\n\n## Summary\n\nThe dashboard HTTP server in `token-optimizer-mcp` exposes `/api/session-summary` and `/api/session-events` with no authentication middleware — any network-accessible client can reach them without credentials. Both handlers concatenate the caller-supplied `sessionId` query parameter directly into a filesystem path via `path.join`, and Node.js normalizes `..` segments at resolution time, allowing an unauthenticated attacker to read any `.jsonl` file reachable from the server's filesystem. Successful reproduction confirmed exfiltration of a `.jsonl` file located outside the intended `hooksDataPath` directory with a single unauthenticated HTTP GET request.\n\n## Affected Code\n\n`src/server/web-server.ts:73–88` — `/api/session-summary`: unsanitized `sessionId` interpolated into `path.join` then passed to `fs.readFileSync`\n\n```typescript\n const hooksDataPath = getHooksDataPath();\n const jsonlFilePath = path.join(\n hooksDataPath,\n `session-log-${sessionId}.jsonl`\n );\n\n if (!fs.existsSync(jsonlFilePath)) {\n return res.status(404).json({\n success: false,\n error: `JSONL log not found for session ${sessionId}`,\n sessionId,\n });\n }\n\n // Parse JSONL file\n const jsonlContent = fs.readFileSync(jsonlFilePath, 'utf-8');\n```\n\n`src/server/web-server.ts:297–311` — `/api/session-events`: identical unsanitized `path.join` + `fs.readFileSync` pattern\n\n```typescript\n const hooksDataPath = getHooksDataPath();\n const jsonlFilePath = path.join(\n hooksDataPath,\n `session-log-${sessionId}.jsonl`\n );\n\n if (!fs.existsSync(jsonlFilePath)) {\n return res.status(404).json({\n success: false,\n error: `JSONL log not found for session ${sessionId}`,\n });\n }\n\n // Parse JSONL file\n const jsonlContent = fs.readFileSync(jsonlFilePath, 'utf-8');\n```\n\n`req.query.sessionId` flows unsanitized into `path.join(hooksDataPath, \\`session-log-${sessionId}.jsonl\\`)`, which Node.js resolves by normalizing `..` traversal sequences before the `fs.readFileSync` call.\n\n## Proof of Concept\n\nStep 1 — Send traversal payload to `/api/session-events` with no credentials: server returns HTTP 200 with contents of a `.jsonl` file outside `hooksDataPath` — proves unauthenticated out-of-bounds file read.\n\n```bash\ncurl -s \"http://127.0.0.1:3100/api/session-events?sessionId=abc%2F..%2F..%2F..%2F..%2Ftraversal-target\"\n```\n\n```http\nGET /api/session-events?sessionId=abc%2F..%2F..%2F..%2F..%2Ftraversal-target HTTP/1.1\nHost: 127.0.0.1:3100\nUser-Agent: python-requests/2.x\nAccept: */*\n```\n\n```http\nHTTP/1.1 200 OK\nX-Powered-By: Express\nAccess-Control-Allow-Origin: *\nContent-Type: application/json; charset=utf-8\nContent-Length: 186\n\n{\"success\":true,\"sessionId\":\"abc/../../../../traversal-target\",\"total\":1,\"offset\":0,\"limit\":100,\"events\":[{\"type\":\"PATH_TRAVERSAL_EVIDENCE\",\"secret\":\"sensitive-data-outside-hooks-dir\"}]}\n```\n\n## Impact\n\nAn unauthenticated remote attacker can read the contents of any `.jsonl` file accessible to the process running the dashboard server. In a typical deployment this includes all session log files (which contain tool invocations, hook outputs, and token usage data) as well as any other `.jsonl` file reachable via `..` traversal from `hooksDataPath`. The constraint that the resolved path must end in `.jsonl` limits the attack surface to that file extension, but session logs can contain sensitive operational data. The same path traversal is present in both `/api/session-summary` and `/api/session-events`, and neither endpoint requires authentication.\n\n## Remediation\n\n1. **Validate `sessionId` format** before use: reject any value that does not match a strict allowlist such as `/^[a-zA-Z0-9_-]{1,64}$/`. This prevents `/` and `.` characters from entering the path construction entirely.\n\n ```typescript\n const SESSION_ID_RE = /^[a-zA-Z0-9_-]{1,64}$/;\n if (!SESSION_ID_RE.test(sessionId)) {\n return res.status(400).json({ success: false, error: 'Invalid sessionId' });\n }\n ```\n\n2. **Alternatively, apply `path.basename`** to strip all directory components: `path.basename(sessionId)` reduces any traversal sequence to a bare filename before `path.join`.\n\n3. **Add authentication middleware** to all `/api/*` routes so that even if a bypass is found the endpoints are not reachable without a valid session token.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "@ooples/token-optimizer-mcp"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "5.1.0"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/ooples/token-optimizer-mcp/security/advisories/GHSA-76pc-mqxp-3rq5"
42+
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/ooples/token-optimizer-mcp/commit/b4ee96dac799cbfba0a9f9c17844ce9d613cbcc7"
46+
},
47+
{
48+
"type": "PACKAGE",
49+
"url": "https://github.com/ooples/token-optimizer-mcp"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/ooples/token-optimizer-mcp/releases/tag/v5.1.0"
54+
}
55+
],
56+
"database_specific": {
57+
"cwe_ids": [
58+
"CWE-22"
59+
],
60+
"severity": "MODERATE",
61+
"github_reviewed": true,
62+
"github_reviewed_at": "2026-08-14T21:43:54Z",
63+
"nvd_published_at": null
64+
}
65+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-9q54-f358-3fqf",
4+
"modified": "2026-08-14T21:44:19Z",
5+
"published": "2026-08-14T21:44:19Z",
6+
"aliases": [
7+
"CVE-2026-10740"
8+
],
9+
"summary": "s2n-quic has excessive memory allocation",
10+
"details": "s2n-quic is a Rust implementation of the QUIC protocol. An unauthenticated user can attempt to exhaust server memory on an s2n-quic endpoint by sending crafted CRYPTO frames with high offsets. The buffer used for processing CRYPTO frames does not enforce a maximum size. In the worst case, a single 1200-byte packet can cause approximately 9.4 MB of allocation. By repeatedly sending such packets, the resulting memory pressure could cause denial of service. No valid handshake is required.\n\nImpacted versions: <= v1.81.0\n\n### Patches\nThis issue has been addressed in s2n-quic version v1.82.0. We recommend upgrading to the latest version and ensuring any forked or derivative code is patched to incorporate the new fixes. \n\n### Workarounds\nThere is no workaround that fully mitigates this issue. Upgrading to the patched version is the recommended remediation.\n\n### References\nIf there are any questions or comments about this advisory, contact AWS Security via the [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting) or directly via email to [aws-security@amazon.com](mailto:aws-security@amazon.com). Please do not create a public GitHub issue.",
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:L"
15+
},
16+
{
17+
"type": "CVSS_V4",
18+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
19+
}
20+
],
21+
"affected": [
22+
{
23+
"package": {
24+
"ecosystem": "crates.io",
25+
"name": "s2n-quic"
26+
},
27+
"ranges": [
28+
{
29+
"type": "ECOSYSTEM",
30+
"events": [
31+
{
32+
"introduced": "0"
33+
},
34+
{
35+
"fixed": "1.82.0"
36+
}
37+
]
38+
}
39+
],
40+
"database_specific": {
41+
"last_known_affected_version_range": "<= 1.81.0"
42+
}
43+
}
44+
],
45+
"references": [
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/aws/s2n-quic/security/advisories/GHSA-9q54-f358-3fqf"
49+
},
50+
{
51+
"type": "ADVISORY",
52+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-10740"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://aws.amazon.com/security/security-bulletins/2026-042-aws"
57+
},
58+
{
59+
"type": "PACKAGE",
60+
"url": "https://github.com/aws/s2n-quic"
61+
},
62+
{
63+
"type": "WEB",
64+
"url": "https://github.com/aws/s2n-quic/releases/tag/v1.82.0"
65+
}
66+
],
67+
"database_specific": {
68+
"cwe_ids": [
69+
"CWE-770"
70+
],
71+
"severity": "MODERATE",
72+
"github_reviewed": true,
73+
"github_reviewed_at": "2026-08-14T21:44:19Z",
74+
"nvd_published_at": "2026-06-10T19:16:32Z"
75+
}
76+
}

0 commit comments

Comments
 (0)