CVE-2019-15782
Description
WebTorrent before 0.107.6 is vulnerable to stored XSS via a malicious torrent title or file name when the HTTP server index page is visited.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
WebTorrent before 0.107.6 is vulnerable to stored XSS via a malicious torrent title or file name when the HTTP server index page is visited.
Vulnerability
Overview
CVE-2019-15782 is a cross-site scripting (XSS) vulnerability in the WebTorrent package for Node.js and the browser, affecting versions prior to 0.107.6. The flaw resides in the HTTP server component: when a user starts the server via createServer() and visits the index page that lists torrent contents, the torrent's title or file names are rendered without proper sanitization. An attacker can craft a torrent with a malicious title or file name containing JavaScript, which executes in the context of the victim's browser when the index page is loaded [1][4].
Exploitation
Prerequisites
Exploitation requires the victim to download a torrent with a specially crafted title or file name)Skip and then start the WebTorrent HTTP server and navigate to its index page. The attacker does not need any authentication or special network position beyond being able to supply the malicious torrent to the victim (e.g., via a public tracker or direct download). The WebTorrent HTTP server only serves data pieces from the torrent, so the attacker's script cannot directly control the torrent client, but it can access the page's DOM and exfiltrate information about the downloaded content [1][4].
Impact
Successful exploitation allows the attacker to execute arbitrary JavaScript in the victim's browser within the origin of the WebTorrent server. This can be used to steal the list of files being downloaded, monitor user activity, or exfiltrate data to an external domain. The impact is limited to the context of the torrent index page; however, it could be combined with other attacks if the victim has other sensitive data accessible from that origin [1][4].
Mitigation
The vulnerability was fixed in WebTorrent version 0.107.6. The fix includes two complementary defenses: HTML-escaping of untrusted torrent metadata (name, path, file names) and adding a strict Content Security Policy (CSP) that denies all scripts, styles, plugins, and frames. Users should upgrade to version 0.107.6 or later. No workarounds are documented, but avoiding the use of the HTTP server index page with untrusted torrents reduces risk [3][4].
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
webtorrentnpm | < 0.107.6 | 0.107.6 |
Affected products
2- WebTorrent/WebTorrentdescription
Patches
17e829b5d52c3Merge pull request #1714 from webtorrent/fix-server-xss
2 files changed · +48 −10
lib/server.js+47 −10 modified@@ -1,4 +1,5 @@ const arrayRemove = require('unordered-array-remove') +const escapeHtml = require('escape-html') const http = require('http') const mime = require('mime') const pump = require('pump') @@ -78,10 +79,6 @@ function Server (torrent, opts = {}) { const pathname = new URL(req.url, 'http://example.com').pathname - if (pathname === '/favicon.ico') { - return serve404Page() - } - // Allow cross-origin requests (CORS) if (isOriginAllowed(req)) { res.setHeader('Access-Control-Allow-Origin', req.headers.origin) @@ -90,6 +87,13 @@ function Server (torrent, opts = {}) { // Prevent browser mime-type sniffing res.setHeader('X-Content-Type-Options', 'nosniff') + // Defense-in-depth: Set a strict Content Security Policy to mitigate XSS + res.setHeader('Content-Security-Policy', "base-uri 'none'; default-src 'none'; frame-ancestors 'none'; form-action 'none';") + + if (pathname === '/favicon.ico') { + return serve404Page() + } + // Allow CORS requests to specify arbitrary headers, e.g. 'Range', // by responding to the OPTIONS preflight request with the specified // origin and requested headers. @@ -147,11 +151,26 @@ function Server (torrent, opts = {}) { res.statusCode = 200 res.setHeader('Content-Type', 'text/html') - const listHtml = torrent.files.map((file, i) => `<li><a download="${file.name}" href="/${i}/${file.name}">${file.path}</a> (${file.length} bytes)</li>`).join('<br>') + const listHtml = torrent.files + .map((file, i) => ( + `<li> + <a + download="${escapeHtml(file.name)}" + href="/${escapeHtml(i)}/${escapeHtml(file.name)}" + > + ${escapeHtml(file.path)} + </a> + (${escapeHtml(file.length)} bytes) + </li>` + )) + .join('<br>') const html = getPageHTML( - `${torrent.name} - WebTorrent`, - `<h1>${torrent.name}</h1><ol>${listHtml}</ol>` + `${escapeHtml(torrent.name)} - WebTorrent`, + ` + <h1>${escapeHtml(torrent.name)}</h1> + <ol>${listHtml}</ol> + ` ) res.end(html) } @@ -160,7 +179,10 @@ function Server (torrent, opts = {}) { res.statusCode = 404 res.setHeader('Content-Type', 'text/html') - const html = getPageHTML('404 - Not Found', '<h1>404 - Not Found</h1>') + const html = getPageHTML( + '404 - Not Found', + '<h1>404 - Not Found</h1>' + ) res.end(html) } @@ -214,16 +236,31 @@ function Server (torrent, opts = {}) { function serveMethodNotAllowed () { res.statusCode = 405 res.setHeader('Content-Type', 'text/html') - const html = getPageHTML('405 - Method Not Allowed', '<h1>405 - Method Not Allowed</h1>') + const html = getPageHTML( + '405 - Method Not Allowed', + '<h1>405 - Method Not Allowed</h1>' + ) res.end(html) } } return server } +// NOTE: Arguments must already be HTML-escaped function getPageHTML (title, pageHtml) { - return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>${title}</title></head><body>${pageHtml}</body></html>` + return ` + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="utf-8"> + <title>${title}</title> + </head> + <body> + ${pageHtml} + </body> + </html> + ` } // From https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
package.json+1 −0 modified@@ -42,6 +42,7 @@ "create-torrent": "^4.0.0", "debug": "^4.1.0", "end-of-stream": "^1.1.0", + "escape-html": "^1.0.3", "fs-chunk-store": "^2.0.0", "http-node": "github:feross/http-node#cddd2872f0020ecf5016f326cf5e58c965eef52a", "immediate-chunk-store": "^2.0.0",
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-gjh4-fcv3-whpqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-15782ghsaADVISORY
- github.com/webtorrent/webtorrent/commit/7e829b5d52c32d2e6d8f5fbcf0f8f418fffde083ghsaWEB
- github.com/webtorrent/webtorrent/compare/v0.107.5...v0.107.6ghsax_refsource_MISCWEB
- github.com/webtorrent/webtorrent/pull/1714ghsax_refsource_MISCWEB
- hackerone.com/reports/681617ghsax_refsource_CONFIRMWEB
- snyk.io/vuln/SNYK-JS-WEBTORRENT-460351ghsaWEB
- www.npmjs.com/advisories/1158ghsaWEB
News mentions
0No linked articles in our index yet.