Leaving the back door open on a house that only exists during construction
webpack-dev-middleware is an Express-style development helper that serves webpack-compiled assets from memory during local development. The getFilenameFromUrl function fails to unescape and normalize URL-encoded sequences (%2e, %2f) before resolving file paths, allowing an attacker to break out of the public directory and read arbitrary files from the developer's filesystem. Affected versions: <5.3.4, >=6.0.0 <6.1.2, >=7.0.0 <7.1.0. The PoC is trivial: curl localhost:8080/public/..%2f..%2f..%2f..%2f../etc/passwd. The writeToDisk: true configuration option must be set for the traversal to return useful content in many setups.
The vendor rates this HIGH 7.4 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N). That score is technically defensible in a vacuum: unauthenticated, low-complexity, high-confidentiality impact. But it completely ignores the deployment context. webpack-dev-middleware is explicitly a development-only tool — the npm README, the webpack docs, and every best-practice guide say *do not run this in production*. The realistic attack surface is a developer's laptop listening on localhost:8080, reachable only via a cross-origin request from a malicious page the developer visits. In an enterprise fleet of 10,000 hosts, the number running an exposed webpack dev server at any given moment is vanishingly small. The vendor HIGH overstates the operational risk for defenders managing production infrastructure.
4 steps from start to impact.
Identify a running webpack-dev-server
0.0.0.0, the port may be reachable on the local network or, in rare misconfigurations, on the internet.- webpack-dev-server or custom Express app using webpack-dev-middleware is running
- Server is listening on a reachable interface (localhost requires browser pivot; 0.0.0.0 allows direct access)
- Dev servers run transiently — they are up only while a developer is actively coding
- Default bind is localhost, unreachable from the network
- Enterprise firewalls and VPNs prevent lateral access to developer workstation ports
Trigger cross-origin request (localhost scenario)
http://localhost:8080/public/..%2f..%2f..%2fetc/passwd. Browser SOP blocks reading the response unless CORS headers are permissive. webpack-dev-server does set Access-Control-Allow-Origin: * by default in some versions, which makes this feasible.- Developer visits attacker-controlled page while dev server is running
- CORS headers on the dev server permit cross-origin reads
- Requires social engineering or watering-hole to get the developer to visit a malicious page at the right time
- Modern email gateways and web proxies may block the lure
- Developer must have the specific project running at that moment
Send path-traversal payload
%2e%2f sequences to escape the public directory. For example: /public/..%2f..%2f..%2f..%2f..%2fetc/passwd or targeting ~/.ssh/id_rsa, ~/.aws/credentials, .env files. The middleware resolves the path without proper normalization and serves the file content.- The
writeToDiskoption is enabled, or the targeted file happens to be within the webpack output filesystem
- Many default webpack configs do NOT set writeToDisk: true
- Without writeToDisk, only files in the in-memory webpack output filesystem are served — not arbitrary disk files
- The attacker must guess file paths blind
%2e%2f or .. in URLs would block this, though dev servers rarely sit behind a WAF.Exfiltrate sensitive files
.env files with API secrets, and application source code. Impact is read-only — no code execution, no persistence, no integrity impact.- Traversal in step 3 succeeded
- Target files are readable by the process user
- Impact limited to a single developer workstation
- No lateral movement or privilege escalation without chaining stolen credentials
- Credential rotation and vault-based secret management limit the value of stolen files
~/.ssh/*, ~/.aws/*) could alert.The supporting signals.
| In-the-wild exploitation | No known in-the-wild exploitation. Not listed on CISA KEV. No campaigns reported. |
|---|---|
| Proof of concept | Public. Trivial curl one-liner: curl localhost:8080/public/..%2f..%2f..%2f..%2f../etc/passwd. Vicarius published a detailed walkthrough. |
| EPSS | 0.00371 — bottom ~30th percentile. Reflects extremely low predicted exploitation probability. |
| KEV status | Not listed. No CISA KEV entry as of 2026-09-03. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N — Network-reachable, no privileges, but requires user interaction (UI:R). Read-only impact (C:H, I:N, A:N). Scope Changed means impact crosses the web origin boundary. |
| Affected versions | webpack-dev-middleware <5.3.4, >=6.0.0 <6.1.2, >=7.0.0 <7.1.0 |
| Fixed versions | 5.3.4, 6.1.2, 7.1.0 and later |
| Scanning / exposure | No Shodan/Censys/GreyNoise signatures for webpack-dev-server. This is a development-only tool; internet-facing exposure is effectively zero in properly managed enterprises. |
| Disclosure date | 2024-03-21 (original GHSA); user-supplied disclosure date 2026-08-24 for CVE-2026-76844 |
| Reporter | Reported via the webpack project's GitHub Security Advisory process (GHSA-wr3j-pwj9-hqq6) |
noisgate verdict.
The single most decisive factor is deployment context: webpack-dev-middleware is an explicitly development-only tool that never runs in production, reducing the reachable population in a managed enterprise fleet to near zero. The read-only impact (no code execution, no persistence) and requirement for user interaction further compress the real-world risk below the vendor's HIGH label.
Why this verdict
- Dev-only tool, not production software. webpack-dev-middleware runs transiently on developer laptops during active coding sessions. In a 10,000-host fleet, the number of hosts running a vulnerable dev server at any given time is likely single digits. This alone compresses the exposure window by 2+ orders of magnitude versus the CVSS assumption of a persistent network service.
- User interaction required (UI:R). The default bind is localhost, meaning the attacker cannot reach the port directly. Exploitation requires the developer to visit a malicious page while the dev server is running — a narrow timing window combined with social engineering.
- Read-only impact, no code execution. The chain ends at file read. There is no RCE, no write primitive, no persistence. Stolen credentials (SSH keys, cloud tokens) could enable follow-on attacks, but that requires chaining and depends on whether the developer stores unprotected secrets on disk.
- writeToDisk prerequisite. Many configurations do not set
writeToDisk: true, limiting traversal to the in-memory webpack output filesystem rather than arbitrary disk files. - Role multiplier: This component occupies a low-value role (developer workstation tooling). It is NOT a domain controller, hypervisor, CI/CD server, identity provider, backup system, or network edge appliance. Even if a developer workstation is compromised via credential theft, the blast radius is host-level (one developer's files), not fleet-scale. In CI/CD pipelines, webpack-dev-middleware is not used —
webpack buildruns instead. The high-value-role floor does not apply.
Why not higher?
The vendor's HIGH (7.4) assumes a persistently reachable network service with high-confidentiality impact. In reality, the tool is development-only, transient, defaults to localhost, and requires victim interaction. No in-the-wild exploitation, no KEV listing, and EPSS in the bottom third all confirm this is not attracting attacker attention. The read-only impact with no RCE caps the blast radius.
Why not lower?
A public PoC exists and the exploit is trivial (single curl command). Developers *do* sometimes bind to 0.0.0.0 for mobile testing or Docker workflows, and webpack-dev-server *does* set permissive CORS headers by default. Stolen SSH keys or cloud credentials from a developer workstation can enable meaningful follow-on attacks. LOW would understate the residual risk for organizations with large JavaScript development teams.
What to do — in priority order.
- Pin webpack-dev-middleware to patched versions in package.json — Set
webpack-dev-middlewareto>=5.3.4(v5),>=6.1.2(v6), or>=7.1.0(v7) in all projectpackage.jsonfiles. Runnpm audit fixoryarn upgradeacross repositories. This is the definitive fix and should be completed within the 365-day noisgate remediation SLA for MEDIUM. - Audit and remove writeToDisk: true from webpack configs — Search codebases for
writeToDisk: truein webpack dev configurations. Remove it unless absolutely necessary, as this setting expands the traversal from in-memory assets to the full filesystem. - Ensure dev servers bind to localhost only — Verify that webpack-dev-server configs use
host: 'localhost'(the default) rather than0.0.0.0. This eliminates direct network access to the dev server. Enforce via linting rules or PR checks. - Block inbound connections to common dev ports at the host firewall — Use host-based firewall rules (iptables, Windows Firewall) to block inbound connections on ports 8080, 3000, 9000 from non-localhost sources. This is defense-in-depth even if a developer overrides the bind address.
- WAF rules — dev servers do not sit behind enterprise WAFs, so URL-pattern blocking is irrelevant for the actual attack surface.
- Network IDS/IPS signatures — the traffic is on localhost or a developer's LAN, not traversing monitored network segments in most architectures.
- Patching the OS — this is an npm package vulnerability, not an OS-level issue. OS patching has no effect.
Crowdsourced verification payload.
Run this on any machine with node and npm installed to check whether project dependencies include a vulnerable version of webpack-dev-middleware. Execute from the project root directory: bash check_webpack_dev_middleware.sh /path/to/project. No special privileges required.
#!/usr/bin/env bash
# check_webpack_dev_middleware.sh — detect vulnerable webpack-dev-middleware
# Usage: bash check_webpack_dev_middleware.sh [project_dir]
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
PROJECT_DIR="${1:-.}"
if [ ! -d "$PROJECT_DIR/node_modules" ]; then
echo "UNKNOWN — no node_modules found in $PROJECT_DIR. Run npm install first."
exit 2
fi
PKG="$PROJECT_DIR/node_modules/webpack-dev-middleware/package.json"
if [ ! -f "$PKG" ]; then
echo "PATCHED — webpack-dev-middleware is not installed in this project."
exit 0
fi
VERSION=$(node -e "console.log(require('$PKG').version)" 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "UNKNOWN — could not read webpack-dev-middleware version."
exit 2
fi
echo "Detected webpack-dev-middleware version: $VERSION"
# Compare versions using node semver logic
RESULT=$(node -e "
const v = '$VERSION';
const [major, minor, patch] = v.split('.').map(Number);
if (major <= 4) {
// v5 branch: anything < 5.3.4 is vulnerable
// v4 and below: all vulnerable
console.log('VULNERABLE');
} else if (major === 5) {
if (minor < 3 || (minor === 3 && patch < 4)) {
console.log('VULNERABLE');
} else {
console.log('PATCHED');
}
} else if (major === 6) {
if (minor < 1 || (minor === 1 && patch < 2)) {
console.log('VULNERABLE');
} else {
console.log('PATCHED');
}
} else if (major === 7) {
if (minor < 1) {
console.log('VULNERABLE');
} else {
console.log('PATCHED');
}
} else {
console.log('PATCHED');
}
" 2>/dev/null)
echo "$RESULT"
if [ "$RESULT" = "VULNERABLE" ]; then
echo "Action: upgrade to 5.3.4, 6.1.2, or 7.1.0+"
exit 1
elif [ "$RESULT" = "PATCHED" ]; then
exit 0
else
exit 2
fiIf you remember one thing.
npm audit or yarn audit checks to CI pipelines to flag vulnerable webpack-dev-middleware versions, and bulk-update package.json files across repositories to pin >=5.3.4 / >=6.1.2 / >=7.1.0. Advise developers to never bind dev servers to 0.0.0.0 and to remove writeToDisk: true unless required. This does not warrant emergency patching or weekend work — fold it into your next quarterly dependency update cycle.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.