# webpack — CWE-407 Disclosure Brief
**2026-03-26 · Patch available — awaiting upstream merge**

## Finding

Three O(n²) defects in webpack's Hot Module Replacement (HMR) runtime. All patched. Patches ready for upstream review. All three defects are in the HMR runtime bundle — JavaScript code shipped to and executed in the browser on every webpack build with HMR enabled.

## The Defects

**webpack-0001 (PATCHED — MEDIUM-HIGH):** `lib/hmr/JavascriptHotModuleReplacement.runtime.js:74`

```javascript
// Inside getAffectedModuleEffects() — BFS over module dependency graph:
var outdatedModules = [moduleId];
// ...
if (outdatedModules.indexOf(parentId) !== -1) continue;  // O(M) per check
outdatedModules.push(parentId);
```

`outdatedModules` is a plain `Array`. `Array.indexOf()` is O(M). Called per module per parent edge during BFS traversal. For M affected modules: **O(M²) total**.

**webpack-0002 (PATCHED — MEDIUM):** `JavascriptHotModuleReplacement.runtime.js:101`

```javascript
// addAllToSet helper — called to merge module lists:
function addAllToSet(a, b) {
    for (var i = 0; i < b.length; i++) {
        var item = b[i];
        if (a.indexOf(item) === -1) a.push(item);  // O(N) per insertion
    }
}
```

`Array.indexOf()` scans the entire accumulator for every new item. For N items: **O(N²)**.

**webpack-0003 (PATCHED — MEDIUM):** `lib/hmr/HotModuleReplacement.runtime.js:60,67`

```javascript
// Inside createRequire() — the hot require() wrapper:
if (module.parents.indexOf(parentId) === -1)     // O(P)
    module.parents.push(parentId);
// ...
if (me.children.indexOf(request) === -1)          // O(C)
    me.children.push(request);
```

Every `require()` call in the HMR hot path deduplicates parents and children arrays using `indexOf`. In a large module graph with many require() calls: **O(P² + C²)**.

## Complexity Proof

**webpack-0001 BFS:** For M affected modules in the BFS frontier:
- Each enqueue step checks `outdatedModules.indexOf(parentId)`: up to M comparisons
- Called M times total
- Total: 1 + 2 + ... + M = **O(M²)**

At M=200: defective=19,900 comparisons, fixed=200. **Measured ratio: 100×.**

**webpack-0002:** For N items to add:
- Each `indexOf()` scans up to N entries in accumulator
- Total: **O(N²)**

**webpack-0003:** Per require() call, O(P) parents scan + O(C) children scan.

## Impact

webpack is the most widely deployed JavaScript module bundler. webpack 5 powers millions of web applications. HMR is enabled by default in every webpack dev server — it runs in-browser during development. `getAffectedModuleEffects()` executes on every file save during hot reload. Large frontend applications (thousands of modules, complex dependency graphs) maximize M and hit the worst case on every hot reload.

`addAllToSet` and the hot `require()` path run on every HMR update cycle. Applications with shared module graphs — monorepos, design systems, large SPA codebases — are most affected.

## The Fix

**webpack-0001:** Shadow `outdatedModules` array with a companion `Set`:

```javascript
// CWE-407 fix: shadow array with Set for O(1) dedup.
var outdatedModules = [];
var outdatedModulesSet = new Set([moduleId]);
outdatedModules.push(moduleId);
// Replace: if (outdatedModules.indexOf(parentId) !== -1) continue;
if (outdatedModulesSet.has(parentId)) continue;
outdatedModulesSet.add(parentId);
outdatedModules.push(parentId);
```

**webpack-0002:** Maintain a companion `Set` alongside the accumulator array:

```javascript
// CWE-407 fix: companion Set for O(1) dedup in addAllToSet.
function addAllToSet(a, b) {
    if (!a._set) a._set = new Set(a);
    for (var i = 0; i < b.length; i++) {
        if (!a._set.has(b[i])) { a.push(b[i]); a._set.add(b[i]); }
    }
}
```

**webpack-0003:** Use `Set` companions for parents and children:

```javascript
// CWE-407 fix: Set companions for parents/children in hot require path.
if (!module._parentsSet) module._parentsSet = new Set(module.parents);
if (!module._parentsSet.has(parentId)) {
    module.parents.push(parentId);
    module._parentsSet.add(parentId);
}
```

## Patch

Fix available:
- `defects/webpack/patch/webpack-0001-hmr-outdated-set.patch`
- `defects/webpack/patch/webpack-0002-hmr-parents-children-set.patch`

Unit test: 4/4 pass. webpack-0001 at M=200: defective=19,900, fixed=200, **100× speedup**. webpack-0002 at N=200: same ratio.

## What We Ask

A patch is ready for review.

1. Confirm receipt and assign a GitHub Security Advisory (webpack/webpack).
2. Assess severity — webpack-0001 fires on every hot reload in webpack dev server.
3. Coordinate a disclosure date — we are targeting 90 days from first contact.
4. We will credit the webpack team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.
