Back to Blog
critical SEVERITY7 min read

How WebSocket Header Parsing Vulnerabilities Happen in Node.js and How to Fix Them

CVE-2026-54466 is a critical vulnerability in the `websocket-driver` npm package (versions prior to 0.7.5) that exposes applications to exploitation through malformed WebSocket protocol input. The fix pins the dependency to `0.7.5` via a pnpm override, closing the attack surface in both `faye-websocket` and any other consumers in the dependency tree. Because WebSocket connections are a common real-time communication channel, leaving this unpatched puts any application that handles untrusted WebS

O
By Orbis AppSec
Published August 26, 2026Reviewed August 26, 2026

Answer Summary

CVE-2026-54466 is a critical vulnerability (CWE-20, Improper Input Validation) in the `websocket-driver` npm package ≤0.7.4, which mishandles malformed HTTP upgrade headers during WebSocket handshake parsing. Attackers can send crafted WebSocket handshake requests to trigger the flaw. The fix is to upgrade `websocket-driver` to 0.7.5, enforced via a pnpm `overrides` entry in `package.json` and a corresponding lockfile update in `pnpm-lock.yaml` so all consumers in the dependency tree receive the patched version.

Vulnerability at a Glance

cweCWE-20
fixPin websocket-driver to 0.7.5 via pnpm overrides in package.json and pnpm-lock.yaml
riskRemote attackers can send crafted WebSocket upgrade requests to exploit the vulnerable parser, potentially causing crashes or arbitrary behavior
languageJavaScript / Node.js
root causewebsocket-driver 0.7.4 fails to properly validate untrusted input during WebSocket protocol negotiation
vulnerabilityImproper Input Validation in WebSocket Handshake Parsing

The Hidden Risk in Your WebSocket Dependency Tree

Real-time web applications depend heavily on WebSocket connections — live dashboards, collaborative editors, hot-module replacement in development servers, and more. The libraries powering these connections are often several layers deep in your node_modules tree, far from the code you write every day. That invisibility is exactly what makes transitive dependency vulnerabilities so dangerous.

CVE-2026-54466 is a critical vulnerability discovered in websocket-driver, a foundational WebSocket protocol handler used across the Node.js ecosystem. Version 0.7.4 and earlier contain a flaw in how the library processes WebSocket handshake input. Because websocket-driver is rarely a direct dependency — it typically arrives via faye-websocket, which itself is pulled in by tools like webpack-dev-server — most developers would never notice it sitting in their lockfile, quietly waiting to be exploited.

This post walks through exactly what the vulnerability is, how it was confirmed in a real project's dependency tree, and the precise changes made to close the attack surface.


The Vulnerability Explained

What websocket-driver Does

websocket-driver is a low-level WebSocket protocol handler. Its job is to parse the HTTP Upgrade request that initiates a WebSocket connection, negotiate protocol extensions, and manage the framing of WebSocket messages. Because it sits at the boundary between raw HTTP and the WebSocket protocol, it processes untrusted, attacker-controlled input by design.

What Goes Wrong in 0.7.4

CVE-2026-54466 is rooted in CWE-20: Improper Input Validation. The 0.7.4 release of websocket-driver does not sufficiently validate the structure of incoming WebSocket handshake headers before processing them. An attacker who can send a crafted HTTP Upgrade request to any endpoint backed by this library can trigger the vulnerable code path.

The vulnerable package version is clearly visible in the lockfile before the fix:

# pnpm-lock.yaml (before fix)
websocket-driver@0.7.4:
  resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
  engines: {node: '>=0.8.0'}

And it appears in two separate places in the dependency snapshot — once as a direct resolution and twice as a transitive dependency consumed by faye-websocket and webpack-dev-server:

# Snapshot entries (before fix)
faye-websocket@0.11.4:
  dependencies:
    websocket-driver: 0.7.4   # ← vulnerable

# ...

webpack-dev-server@...:
  dependencies:
    faye-websocket: 0.11.4
    uuid: 8.3.2
    websocket-driver: 0.7.4   # ← vulnerable again

This dual appearance is significant: even if you tried to patch one consumer, the other would still pull in the vulnerable version without an explicit override.

Attack Scenario

Consider a development environment running webpack-dev-server for hot-module replacement. The dev server opens a WebSocket endpoint so the browser can receive live reload notifications. An attacker on the same network — or a malicious web page exploiting the dev server's lack of origin enforcement — could send a specially crafted WebSocket Upgrade request with malformed header content. Because websocket-driver 0.7.4 does not properly validate this input before parsing, the crafted request reaches the vulnerable code path inside the protocol handler.

Depending on the exact nature of the flaw, this can result in:
- Denial of service — crashing the dev server process
- Memory corruption or unexpected state — depending on the runtime behavior of the parser
- Protocol confusion — forcing the server into an unexpected WebSocket state that downstream logic is not prepared to handle

While the scanner assessment notes the vulnerability is "present in dependency tree, not confirmed reachable" in production, development tooling is not immune to attack — and the same faye-websocket package is used in production WebSocket servers as well.


The Fix

Pinning the Safe Version via pnpm Overrides

The fix is precise and surgical: it adds a pnpm override that forces the entire dependency tree to resolve websocket-driver to 0.7.5, regardless of what individual packages request.

package.json — before:

"pnpm": {
  "overrides": {
    "fast-xml-parser": "4.5.4",
    "shell-quote": "1.8.4"
  }
}

package.json — after:

"pnpm": {
  "overrides": {
    "fast-xml-parser": "4.5.4",
    "shell-quote": "1.8.4",
    "websocket-driver": "0.7.5"
  }
}

This single line addition is the key control. The overrides field in pnpm tells the package manager: no matter who asks for websocket-driver, give them 0.7.5. This is the correct approach when a vulnerability exists in a transitive dependency you do not control directly.

Lockfile Updates

The pnpm-lock.yaml changes reflect the override taking effect across every location where websocket-driver appeared:

# pnpm-lock.yaml — resolution block (after fix)
websocket-driver@0.7.5:
  resolution: {integrity: sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==}
  engines: {node: '>=0.8.0'}
# Snapshot entries (after fix)
faye-websocket@0.11.4:
  dependencies:
    websocket-driver: 0.7.5   # ✅ patched

webpack-dev-server@...:
  dependencies:
    faye-websocket: 0.11.4
    uuid: 8.3.2
    websocket-driver: 0.7.5   # ✅ patched

Notice that the integrity hash also changes — from sha512-b17K... to sha512-ZL2+... — confirming that a genuinely different package artifact is being installed. Committing the updated lockfile ensures that every developer and every CI/CD pipeline gets the exact same patched version, with no room for version drift.

Why Two Files Must Change

Updating only package.json would declare the intent to override, but without regenerating pnpm-lock.yaml, the old lockfile would continue to resolve websocket-driver@0.7.4. Both files must be committed together to make the fix deterministic and reproducible across all environments.


Prevention & Best Practices

1. Use Lockfiles and Commit Them

Always commit pnpm-lock.yaml, package-lock.json, or yarn.lock. Lockfiles are the source of truth for what actually gets installed. Without them, npm install or pnpm install can silently resolve to a vulnerable version.

2. Leverage Package Manager Overrides for Transitive Vulnerabilities

When a vulnerability exists in a package you don't depend on directly, use your package manager's override mechanism:

  • pnpm: "pnpm": { "overrides": { "package-name": "safe-version" } } in package.json
  • npm: "overrides": { "package-name": "safe-version" } in package.json (npm 8.3+)
  • yarn: "resolutions": { "package-name": "safe-version" } in package.json

3. Run SCA Scanners in CI

Tools like Trivy, Snyk, and npm audit can detect known-vulnerable packages in your lockfile — including transitive dependencies — before they reach production. Trivy was the scanner that flagged this exact issue via rule CVE-2026-54466.

# Run Trivy against your project
trivy fs --scanners vuln .

# Run npm audit
npm audit

# Run pnpm audit
pnpm audit

4. Subscribe to Security Advisories

Monitor the GitHub Advisory Database and npm security advisories for packages in your dependency tree. Tools like Dependabot and Renovate can automate this.

5. Apply the Principle of Least Exposure

For development-only tools like webpack-dev-server, ensure they are not accessible from untrusted networks. Bind dev servers to localhost only and never expose them on public interfaces.

Relevant standards:
- OWASP A06:2021 – Vulnerable and Outdated Components
- CWE-20: Improper Input Validation


Key Takeaways

  • websocket-driver 0.7.4 is vulnerable; 0.7.5 is the minimum safe version. Any project with faye-websocket or webpack-dev-server in its dependency tree is potentially exposed without the override.
  • Transitive dependencies in pnpm-lock.yaml are part of your attack surface. The vulnerable package appeared in two separate snapshot entries — faye-websocket@0.11.4 and the webpack-dev-server snapshot — requiring both to be updated.
  • A pnpm overrides entry is the correct fix for transitive dependency vulnerabilities. Upgrading a direct dependency is not sufficient when the vulnerable package is two or more levels deep.
  • Lockfile integrity hashes change when the package changes. The shift from sha512-b17K... to sha512-ZL2+... confirms a real artifact change, not just a version label update.
  • Development tooling vulnerabilities are real vulnerabilities. webpack-dev-server is a common attack surface in developer environments; don't treat dev dependencies as low-risk.

How Orbis AppSec Detected This

  • Source: Untrusted input enters via inbound WebSocket Upgrade HTTP requests processed by websocket-driver
  • Sink: The WebSocket handshake parser inside websocket-driver@0.7.4, consumed transitively through faye-websocket@0.11.4 as declared in pnpm-lock.yaml
  • Missing control: Insufficient validation of malformed WebSocket protocol headers before parsing, present in versions ≤0.7.4 and patched in 0.7.5
  • CWE: CWE-20 — Improper Input Validation
  • Fix: Added "websocket-driver": "0.7.5" to the pnpm.overrides block in package.json and regenerated pnpm-lock.yaml to enforce the patched version across all consumers in the dependency tree

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2026-54466 is a reminder that your application's security posture is only as strong as the weakest link in your entire dependency tree — including packages you've never heard of. websocket-driver is not a package most developers think about, yet it processes raw, attacker-controlled network input in millions of Node.js applications every day.

The fix here is minimal in terms of lines changed — two files, one new line in each — but it closes a critical attack surface across every consumer of websocket-driver in the project. The pattern of using pnpm overrides (or npm/yarn equivalents) to enforce safe versions of transitive dependencies is one every Node.js developer should have in their toolkit.

Keep your lockfiles committed, run SCA scanners in CI, and don't let invisible dependencies become invisible risks.


References

Frequently Asked Questions

What is CVE-2026-54466?

CVE-2026-54466 is a critical vulnerability in the websocket-driver npm package (≤0.7.4) that stems from improper validation of WebSocket handshake headers, allowing attackers to send malformed input that exploits the protocol parser.

How do you prevent WebSocket parsing vulnerabilities in Node.js?

Keep WebSocket library dependencies up to date, use pnpm/npm overrides to enforce minimum safe versions across your entire dependency tree, and monitor your lockfile for transitive dependency exposure.

What CWE is this WebSocket vulnerability?

This vulnerability maps to CWE-20 (Improper Input Validation), where the library fails to adequately validate the structure of incoming WebSocket protocol data before processing it.

Is upgrading the direct dependency enough to prevent CVE-2026-54466?

Not always. Because websocket-driver is often a transitive dependency (pulled in by faye-websocket, which is used by tools like webpack-dev-server), you must use package manager overrides to ensure all consumers receive the patched version.

Can static analysis detect this WebSocket vulnerability?

Yes. Trivy and similar software composition analysis (SCA) scanners can detect known-vulnerable versions of websocket-driver in your lockfile, even when it is a transitive dependency several levels deep.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1001

Related Articles

high

How Denial of Service via Infinite Loop Happens in JavaScript Dependencies and How to Fix It

CVE-2026-67213 is a high-severity denial of service vulnerability in nanoid before version 5.1.6 that triggers an infinite loop during random ID generation when processing specially crafted input. We upgraded nanoid across the entire dependency tree to patch this flaw and prevent attackers from freezing application threads. This fix ensures that ID generation remains resilient even when handling adversarial input patterns.

high

How Sensitive Data Exposure happens in Zotero plugins and how to fix it

A high-severity data exposure vulnerability in `Zotero.ts` automatically transmitted complete document metadata—including private notes, attachment paths, and tags—to external LLM services without user consent. The fix replaces broad `item.toJSON()` serialization with explicit field selection, sending only essential bibliographic data.

high

How missing dependency update cooldowns happen in GitHub Dependabot configurations and how to fix it

A semgrep scan flagged `.github/dependabot.yml` for lacking a cooldown period, meaning Dependabot would immediately propose updates to brand-new package versions across npm, Bundler, and Docker ecosystems. The fix adds a `cooldown: default-days: 7` block to every `package-ecosystem` entry, forcing a one-week waiting period before newly published releases are considered — reducing exposure to malicious or unstable package drops.

high

How dependabot-missing-cooldown happens in GitHub Actions/Node.js and how to fix it

The repository's `.github/dependabot.yml` had no cooldown period configured, meaning Dependabot could immediately propose updates to newly published package versions with zero time for the community to flag malware or instability. The fix adds a `cooldown` block with `default-days: 7` to both the `npm` and `github-actions` ecosystems, forcing a 7-day waiting period before new releases are surfaced as update PRs.

high

How Path Traversal Happens in TensorFlow's Data Service and How to Fix It

TensorFlow's data service dispatcher validated dataset IDs against forward-slash traversal attacks but overlooked backslash characters on non-Windows platforms, allowing attackers to escape the root directory. A targeted fix adds explicit backslash validation across all platforms, closing a high-severity path traversal vulnerability in the snapshot management system.

critical

How Unbounded WebSocket Message Handling Causes Resource Exhaustion in Node.js and How to Fix It

The WebSocketCrossServerAdapter class in a popular Node.js WebSocket library lacked any rate limiting on inbound messages, allowing attackers to flood Redis nodes and WebSocket servers with high-volume traffic. The fix introduces a configurable `rateLimit` option that caps messages per connection per second, preventing resource exhaustion while preserving legitimate functionality.