From fc48c080682acb56ba12a0ae62b5bac46dc88d17 Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Sat, 9 May 2026 10:01:31 +0800 Subject: [PATCH] fix(node-webpack): CVE-2025-68157, CVE-2025-68458 Fix SSRF vulnerabilities in HttpUriPlugin: - CVE-2025-68157: HTTP(S) resolver enforces allowedUris only for the initial URL, but does not re-validate allowedUris after following HTTP 30x redirects. This allows an import that appears restricted to a trusted allow-list to be redirected to URLs outside the allow-list. - CVE-2025-68458: HTTP(S) resolver can be bypassed to fetch resources from hosts outside allowedUris by using crafted URLs that include userinfo (username:password@host). Upstream: https://github.com/webpack/webpack/commit/2179fdbcb Upstream: https://github.com/webpack/webpack/commit/c51007023 Generated-By: glm-5.1 Co-Authored-By: hudeng --- debian/changelog | 12 +++ debian/patches/CVE-2025-68157-68458.patch | 113 ++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 126 insertions(+) create mode 100644 debian/patches/CVE-2025-68157-68458.patch diff --git a/debian/changelog b/debian/changelog index 67eebb8..ed5d1ef 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +node-webpack (5.76.1+dfsg1+~cs17.16.16-2) unstable; urgency=medium + + * Fix CVE-2025-68157: HTTP(S) resolver enforces allowedUris only for the + initial URL, but does not re-validate allowedUris after following HTTP + 30x redirects. This allows an import that appears restricted to a trusted + allow-list to be redirected to URLs outside the allow-list. + * Fix CVE-2025-68458: HTTP(S) resolver can be bypassed to fetch resources + from hosts outside allowedUris by using crafted URLs that include userinfo + (username:password@host). + + -- deepin-ci-robot Fri, 09 May 2026 09:50:00 +0800 + node-webpack (5.76.1+dfsg1+~cs17.16.16-1) unstable; urgency=medium * Team upload diff --git a/debian/patches/CVE-2025-68157-68458.patch b/debian/patches/CVE-2025-68157-68458.patch new file mode 100644 index 0000000..c8ac6a9 --- /dev/null +++ b/debian/patches/CVE-2025-68157-68458.patch @@ -0,0 +1,113 @@ +Index: node-webpack-cve-2025-68157-68458/lib/schemes/HttpUriPlugin.js +=================================================================== +--- node-webpack-cve-2025-68157-68458.orig/lib/schemes/HttpUriPlugin.js ++++ node-webpack-cve-2025-68157-68458/lib/schemes/HttpUriPlugin.js +@@ -20,6 +20,8 @@ const memoize = require("../util/memoize + + const getHttp = memoize(() => require("http")); + const getHttps = memoize(() => require("https")); ++ ++const MAX_REDIRECTS = 5; + const proxyFetch = (request, proxy) => (url, options, callback) => { + const eventEmitter = new EventEmitter(); + const doRequest = socket => +@@ -147,6 +149,20 @@ const areLockfileEntriesEqual = (a, b) = + ); + }; + ++ ++/** ++ * Sanitize URL for inclusion in error messages ++ * @param {string} href URL string to sanitize ++ * @returns {string} sanitized URL text for logs/errors ++ */ ++const sanitizeUrlForError = href => { ++ try { ++ const u = new URL(href); ++ return `${u.protocol}//${u.host}`; ++ } catch (_err) { ++ return String(href).slice(0, 200).replace(/[\r\n]/g, ""); ++ } ++}; + const entryToString = entry => { + return `resolved: ${entry.resolved}, integrity: ${entry.integrity}, contentType: ${entry.contentType}`; + }; +@@ -511,9 +527,28 @@ class HttpUriPlugin { + const resolveContent = (url, integrity, callback) => { + const handleResult = (err, result) => { + if (err) return callback(err); +- if ("location" in result) { ++ if ("location" in result) { ++ // CVE-2025-68157: Validate redirect URL against allowedUris ++ let nextUrl; ++ try { ++ nextUrl = new URL(result.location, url); ++ } catch (_err) { ++ return callback(new Error( ++ `Invalid redirect URL: ${sanitizeUrlForError(result.location)}` ++ )); ++ } ++ if (nextUrl.protocol !== "http:" && nextUrl.protocol !== "https:") { ++ return callback(new Error( ++ `Redirected URL uses disallowed protocol: ${sanitizeUrlForError(nextUrl.href)}` ++ )); ++ } ++ if (!isAllowed(nextUrl.href)) { ++ return callback(new Error( ++ `${nextUrl.href} doesn't match the allowedUris policy after redirect. These URIs are allowed:\n${allowedUris.map(uri => ` - ${uri}`).join("\n")}` ++ )); ++ } + return resolveContent( +- result.location, ++ nextUrl.href, + integrity, + (err, innerResult) => { + if (err) return callback(err); +@@ -525,7 +560,6 @@ class HttpUriPlugin { + } + ); + } else { +- if ( + !result.fresh && + integrity && + result.entry.integrity !== integrity && +@@ -739,19 +773,34 @@ class HttpUriPlugin { + (url, callback) => fetchContentRaw(url, undefined, callback) + ); + +- const isAllowed = uri => { ++ const isAllowed = uri => { ++ let parsedUri; ++ try { ++ // Parse the URI to prevent userinfo bypass attacks ++ // (e.g., http://allowed@malicious/path where @malicious is the actual host) ++ parsedUri = new URL(uri); ++ } catch (_err) { ++ return false; ++ } + for (const allowed of allowedUris) { + if (typeof allowed === "string") { +- if (uri.startsWith(allowed)) return true; ++ let parsedAllowed; ++ try { ++ parsedAllowed = new URL(allowed); ++ } catch (_err) { ++ continue; ++ } ++ if (parsedUri.href.startsWith(parsedAllowed.href)) { ++ return true; ++ } + } else if (typeof allowed === "function") { +- if (allowed(uri)) return true; ++ if (allowed(parsedUri.href)) return true; + } else { +- if (allowed.test(uri)) return true; ++ if (allowed.test(parsedUri.href)) return true; + } + } + return false; + }; +- + const getInfo = cachedWithKey( + /** + * @param {string} url the url diff --git a/debian/patches/series b/debian/patches/series index 16f26f4..ee0a1a3 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,3 +1,4 @@ +CVE-2025-68157-68458.patch update-importing-eslint-scope.patch dont-require-wast-loader.patch webpack-cli-path.patch