Skip to content

Commit c2e5e2d

Browse files
1 parent 92a88a9 commit c2e5e2d

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

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-525j-2hrj-m8fp",
4+
"modified": "2026-04-01T21:40:22Z",
5+
"published": "2026-04-01T21:40:22Z",
6+
"aliases": [
7+
"CVE-2026-34523"
8+
],
9+
"summary": "SillyTavern: Path Traversal allows file existence oracle",
10+
"details": "### Summary\n\nA path traversal vulnerability in the static file route handler allows any unauthenticated user to determine whether files exist anywhere on the server's filesystem. By sending percent-encoded `../` sequences (`%2E%2E%2F`) in requests to static file routes, an attacker can check for the existence of files (404 if it doesn't exist, 403 means it exists).\n\n### Details\n\nThe vulnerability is in `createRouteHandler` (`src/users.js:947–963`), which backs all user-data static file routes:\n\n```javascript\nfunction createRouteHandler(directoryFn) {\n return async (req, res) => {\n const directory = directoryFn(req);\n const filePath = decodeURIComponent(req.params[0]);\n const exists = fs.existsSync(path.join(directory, filePath)); // no boundary check here\n if (!exists) {\n return res.sendStatus(404);\n }\n return res.sendFile(filePath, { root: directory });\n };\n}\n```\n\n`req.params[0]` contains the raw (percent-encoded) wildcard from the URL. After `decodeURIComponent`, a request path like `/characters/%2E%2E%2F%2E%2E%2FUsers/kirakira` decodes to `../../Users/kirakira`, and `path.join` resolves it outside the intended directory. `res.sendFile` correctly blocks the file from being served (the `send` module's root check returns 403), but `fs.existsSync` had already run, and the 403/404 distinction reveals the result.\n\nAffected routes (they all use the same handler, so they're all affected):\n\n- `/characters/*`\n- `/user/files/*`\n- `/assets/*`\n- `/user/images/*`\n- `/backgrounds/*`\n- `/User%20Avatars/*`\n\n### PoC\n\n```bash\ncurl -o /dev/null -s -w \"%{http_code}\\n\" \"http://localhost:8000/characters/%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2FUsers/kirakira/something\"\n```\n\n### Impact\n\nWhile file contents cannot be read (the `send` module blocks actual delivery), anyone who can reach the SillyTavern HTTP port can check the existence of files on the host filesystem.\n\n### Resolution\n\nThe issue was addressed in version 1.17.0.",
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": "sillytavern"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.17.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 1.16.0"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/SillyTavern/SillyTavern/security/advisories/GHSA-525j-2hrj-m8fp"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/SillyTavern/SillyTavern"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-22"
54+
],
55+
"severity": "MODERATE",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-04-01T21:40:22Z",
58+
"nvd_published_at": null
59+
}
60+
}
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-vprr-q85p-79mf",
4+
"modified": "2026-04-01T21:41:48Z",
5+
"published": "2026-04-01T21:41:48Z",
6+
"aliases": [
7+
"CVE-2026-34524"
8+
],
9+
"summary": "SillyTavern: Path Traversal in `/api/chats/export` and `/api/chats/delete` allows arbitrary file read/delete within user data root",
10+
"details": "## Summary\nA Path Traversal vulnerability in chat endpoints allows an authenticated attacker to read and delete arbitrary files under their user data root (for example `secrets.json` and `settings.json`) by supplying `avatar_url=\"..\"`.\n\n### Details\nThe input validator used by `avatar_url` blocks only `/` and NUL bytes, but does not block traversal segments like `..`.\n\nEvidence:\n- Weak validator regex (does not reject `..`): \n <https://github.com/SillyTavern/SillyTavern/blob/b7bb8be35a5c779b4db12a4a5b94d7e49096071c/src/middleware/validateFileName.js#L24-L27>\n- Vulnerable delete path construction: \n <https://github.com/SillyTavern/SillyTavern/blob/b7bb8be35a5c779b4db12a4a5b94d7e49096071c/src/endpoints/chats.js#L575-L577>\n- Vulnerable export path construction: \n <https://github.com/SillyTavern/SillyTavern/blob/b7bb8be35a5c779b4db12a4a5b94d7e49096071c/src/endpoints/chats.js#L595-L598>\n- Endpoint auth context (authenticated user access): \n <https://github.com/SillyTavern/SillyTavern/blob/b7bb8be35a5c779b4db12a4a5b94d7e49096071c/src/server-main.js#L239>\n\nBecause `avatar_url=\"..\"` is accepted, `path.join(<user>/chats, \"..\")` resolves to `<user>/`, enabling direct access to files outside the chats directory.\n\n### PoC\nPrerequisites:\n- Valid authenticated session cookie (`cookie.txt`)\n- Valid CSRF token (`$TOKEN`)\n\nRead sensitive file (`secrets.json`):\n\n```bash\ncurl -b cookie.txt -H \"x-csrf-token: $TOKEN\" -H \"content-type: application/json\" \\\n -d '{\"avatar_url\":\"..\",\"is_group\":false,\"file\":\"secrets.json\",\"format\":\"jsonl\",\"exportfilename\":\"x\"}' \\\n http://TARGET:8000/api/chats/export\n```\n\nDelete sensitive file (`settings.json`):\n\n```bash\ncurl -b cookie.txt -H \"x-csrf-token: $TOKEN\" -H \"content-type: application/json\" \\\n -d '{\"avatar_url\":\"..\",\"chatfile\":\"settings.json\"}' \\\n http://TARGET:8000/api/chats/delete\n```\n\n### Impact\n- Confidentiality: exposed per-user secrets and config data.\n- Integrity/Availability: attacker can delete critical per-user files and break account operation.\n- Risk is significant in multi-user or remotely reachable deployments.\n\n### Resolution\n\nThe issue was addressed in version 1.17.0",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "sillytavern"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.17.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 1.16.0"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/SillyTavern/SillyTavern/security/advisories/GHSA-vprr-q85p-79mf"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/SillyTavern/SillyTavern"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-22"
54+
],
55+
"severity": "HIGH",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-04-01T21:41:48Z",
58+
"nvd_published_at": null
59+
}
60+
}

0 commit comments

Comments
 (0)