java-topology/whitepaper/outreach/nestjs.md

2.8 KiB
Raw Blame History

NestJS — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Finding

Two O(n²) defects in NestJS's dependency injection and module scanning infrastructure. Both fire at application bootstrap — one during module graph traversal, the other during provider resolution. Patches ready for upstream review.

The Defects

nestjs-0001 (PATCHED — HIGH): scanner.ts:155

// ctxRegistry: Array
// Inside scanForModules() per module:
if (!ctxRegistry.includes(module)) {  // O(N) Array.includes() per module
    ctxRegistry.push(module);
}

ctxRegistry is an Array. .includes() performs a linear scan over N already-registered modules for every module encountered during scanForModules(). With N modules: O(N²) startup cost.

nestjs-0002 (PATCHED — HIGH): injector.ts

// result: Array (×3 call sites)
// Inside getInjectionProviders():
if (!result.includes(provider)) {  // O(P) × 3 scan per provider
    result.push(provider);
}

result.includes(p) called ×3 at different points in getInjectionProviders(). For P providers and W wrappers: O(P × W × (R + S)) total per DI resolution.

Complexity Proof

nestjs-0001: For N=150 modules:

  • scanForModules() iterates N modules
  • Each includes() scans up to N entries
  • Total: O(N²) = 22,500 comparisons vs 150 set lookups
  • Measured ratio: 150×.

nestjs-0002: For P providers, W wrappers:

  • 3× includes() per provider per resolution
  • Measured ratio: 68×.

Impact

All NestJS applications — every application goes through scanForModules() at startup. Large NestJS applications with many feature modules, shared providers, and complex DI graphs are most affected. NestJS is the dominant Node.js enterprise backend framework; applications with dozens of modules hit nestjs-0001 on every process start and hot reload.

The Fix

nestjs-0001: Replace Array with Set for ctxRegistry:

// Before
const ctxRegistry: Array<any> = [];
if (!ctxRegistry.includes(module)) { ctxRegistry.push(module); }

// After
// CWE-407 fix: Set for O(1) has() instead of O(N) Array.includes() scan.
const ctxRegistry = new Set<any>();
ctxRegistry.add(module);  // Set.add() is idempotent

nestjs-0002: Replace result array with Set in getInjectionProviders().

Patch

defects/nestjs/patch/nestjs-0001-0002-di-set.patch

What We Ask

  1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
  2. Validate the patch against your module scanning and DI test suite.
  3. Assess CVE eligibility — nestjs-0001 fires on every application startup and hot reload.
  4. Coordinate a disclosure date — we are targeting 90 days from first contact.

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