CVE-2026-54466: Verified Repro With Script Download
CVE-2026-54466: websocket-driver: message corruption via abuse of draft-WebSocket length headers
CVE-2026-54466 is verified against faye/websocket-driver-node · npm. Affected versions: < 0.7.5. Fixed in 0.7.5. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00292.
What Is CVE-2026-54466?
CVE-2026-54466 (GHSA-xv26-6w52-cph6) is a critical message-integrity flaw in the npm package websocket-driver (faye/websocket-driver-node) before 0.7.5. Its legacy draft-75/draft-76 parser mishandles an overlong variable-width length header, causing WebSocket messages to be misframed, corrupted, or lost. Pruva reproduced it (reproduction REPRO-2026-00292).
CVE-2026-54466 Severity & CVSS Score
CVE-2026-54466 is rated critical severity, with a CVSS base score of 9.2 out of 10.
Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.
Affected faye/websocket-driver-node Versions
faye/websocket-driver-node · npm versions < 0.7.5 are affected.
How to Reproduce CVE-2026-54466
pruva-verify REPRO-2026-00292 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00292/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-54466
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
raw bytes on an established hixie-75 WebSocket TCP connection: 0x80 0xFF 0xFF 0xFF 0x7F overlong length header followed by a valid sentinel text frame
- TCP loopback
- Driver.server()
- Draft75.parse()
- _parseLeadingByte()
- stage-1 base-128 length accumulator (no _maxLength guard)
- stage-2 skip mode consumes/misframes the following sentinel text frame
reproduction_steps.sh The 0.7.5 fix only guards against oversized length headers (_length > _maxLength) in the draft-75 length accumulator. The actual message-corruption mechanism depends on two independent bugs the fix does not address: (A) _parseLeadingByte does not reset _buffer when entering binary frame mode, and (B) stage 2 treats 0x…
How the agent worked
Root Cause and Exploit Chain for CVE-2026-54466
websocket-driver (npm package websocket-driver, repo faye/websocket-driver-node) versions before 0.7.5 mishandle an overlong variable-width length header in the legacy draft-75 / draft-76 (hixie-75 / hixie-76) WebSocket parser. The stage-1 base-128 length accumulator in lib/websocket/driver/draft75.js (this._length = (octet & 0x7F) + 128 * this._length) has no upper bound, so a small, attacker-controlled wire sequence makes the declared _length exceed _maxLength (0x3ffffff = 67108863). The driver stays open and enters stage-2 "skip" mode with a gigantic _length, which then consumes, loses, or misframes a subsequent valid text frame instead of delivering its intended message boundary. The 0.7.5 fix adds a per-octet guard if (this._length > this._maxLength) return this.close(); immediately after accumulation.
- Package/component affected:
websocket-driver, theDraft75/Draft76parser path (lib/websocket/driver/draft75.js), reached viaDriver.server(...)/Server.parse(chunk). - Affected versions:
websocket-driver < 0.7.5(representative vulnerable build0.7.4; fixed control0.7.5). - Risk level and consequences: Critical protocol-level message corruption / message loss on any server that accepts legacy hixie-75/76 framing. An attacker who can write raw bytes to an established connection can cause the parser to drop the framing boundary of the following legitimate frame and emit a stale/misframed application message, defeating message integrity. This is a denial-of-integrity / message-corruption issue, not RCE and not memory exhaustion; the wire allocation stays tiny.
Impact Parity
- Disclosed/claimed maximum impact: Protocol message corruption / message loss (impact class
other), via abuse of the draft-75/76 length header on a negotiated hixie-75/76 connection. - Reproduced impact from this run: On
0.7.4, the driver remained open (readyState=1) after the oversized length header, did not deliver the uniquely-marked sentinel text frame, and instead re-emitted a stale copy of the previous (positive-control) message — i.e. the sentinel was consumed/misframed. On0.7.5, the identical stream closed (readyState=3,closeevent) while accumulating the over-limit length header and emitted no corrupted application message. Positive control delivered in both builds, proving the parser/listener path was operational. - Parity:
full— the reproduced behavior matches the disclosed message-corruption/message-loss impact and the fixed-build negative control exactly. - Not demonstrated: No code execution, no memory exhaustion, no native crash — none claimed.
Root Cause
In Draft75.prototype.parse the per-octet state machine has three relevant stages:
- stage 0 (
_parseLeadingByte): a leading byte with the high bit set ((octet & 0x80) === 0x80) initializes_length = 0and moves to stage 1 (binary/control frame with a variable-width length header). - stage 1 (length accumulator): for every octet,
_length = (octet & 0x7F) + 128 * this._length. An octet whose high bit is clear is the terminator; if_length !== 0the parser transitions to stage 2 with_skipped = 0. - stage 2 (skip mode): while
_lengthis truthy, each incoming octet increments_skippeduntil_skipped === _length; the only early exit isoctet === 0xFF, which emitsBuffer.from(this._buffer)as a message and resets to stage 0. Crucially, in the high-bit-set leading-byte branch_parseLeadingBytedoes not resetthis._buffer, so the stale buffer from a prior text frame is still referenced.
In versions < 0.7.5 there is no bound check on _length during stage 1. The minimal deterministic sequence
0x80 0xFF 0xFF 0xFF 0x7F
drives the accumulator: 0 → 127 → 16383 → 2097151 → 268435455. The terminating 0x7F (high bit clear) produces _length = 268435455, which exceeds _maxLength (0x3ffffff = 67108863), and the parser falls through to stage-2 skip mode. A following valid sentinel text frame (0x00 <utf8 "SENTINEL-VULN-XYZ-12345"> 0xFF) is then consumed byte-by-byte as "skipped" payload; when the sentinel's 0xFF terminator is reached, stage 2 emits Buffer.from(this._buffer) — the stale previous message (POSITIVE-CTRL-OK) — and resets to stage 0. The sentinel text is never delivered; a corrupted/stale message is delivered in its place. The connection stays open, so the corruption is silent and ongoing.
The 0.7.5 patch (lib/websocket/driver/draft75.js, one added line in case 1) inserts the guard immediately after accumulation:
this._length = (octet & 0x7F) + 128 * this._length;
if (this._length > this._maxLength) return this.close(); // <-- added in 0.7.5
so the over-limit header closes the driver (readyState=3, close event) before any sentinel is accepted and before any corrupted message can be emitted.
Fix reference: websocket-driver@0.7.5 release — https://github.com/faye/websocket-driver-node/releases/tag/0.7.5 ; advisory GHSA-xv26-6w52-cph6.
Reproduction Steps
- Reference:
bundle/repro/reproduction_steps.sh(driver script) andbundle/repro/harness.js(Node TCP peer harness). Both are self-contained; the script reuses the prepared project cache (bundle/project_cache_context.json,prepared=true) when available and otherwise falls back tonpm install websocket-driver@0.7.4/@0.7.5. - What the script does:
- Resolves the vulnerable (
0.7.4) and fixed (0.7.5) publishedwebsocket-driverpackages from the durable project cache (or installs them). - Verifies the versions and the presence/absence of the
_maxLengthguard indraft75.jsfor each build. - For each build, runs
harness.js, which starts a real loopback TCP server usingnet.createServer+Driver.server({requireMasking:false}), pipesconnection ↔ driver.io, and a raw TCP client performs a draft-75 handshake (nosec-websocket-*headers, soServer.httpselectsDraft75), waits for the101response, then sends (a) a positive-control text frame0x00 "POSITIVE-CTRL-OK" 0xFF, then (b) the malicious overlong length header0x80 0xFF 0xFF 0xFF 0x7Fimmediately followed by (c) a uniquely-marked sentinel text frame0x00 "SENTINEL-VULN-XYZ-12345" 0xFF. All emittedopen/message/close/errorevents, thereadyState, and the exact wire bytes are recorded to JSON. - Evaluates the oracle: vulnerable build must deliver the positive control, stay open (no
close), not deliver the sentinel, and emit a corrupted/stale message; fixed build must deliver the positive control, emitcloseon the malicious header, and emit no corrupted message. - Writes
bundle/repro/runtime_manifest.json,bundle/repro/validation_verdict.json, and best-effort copies proof artifacts into the project-cache proof-carry directory.
- Resolves the vulnerable (
- Expected evidence of reproduction (see
bundle/logs/oracle_eval.txt,bundle/logs/vuln_result.json,bundle/logs/fixed_result.json):- Vulnerable 0.7.4:
positive_delivered=true,sentinel_delivered=false,close_after_malicious=false,corrupted_message_after_malicious=true,positive_count=2(stale re-emit),readyState_final=1. - Fixed 0.7.5:
positive_delivered=true,sentinel_delivered=false,close_after_malicious=true,corrupted_message_after_malicious=false,positive_count=1,readyState_final=3. - Oracle
CONFIRMED=trueonly when both paths match.
- Vulnerable 0.7.4:
Evidence
bundle/logs/reproduction_steps.log— full driver script transcript.bundle/logs/vuln_result.json— events + wire bytes for0.7.4.bundle/logs/fixed_result.json— events + wire bytes for0.7.5.bundle/logs/vuln_run.log,bundle/logs/fixed_run.log— raw harness stdout per build.bundle/logs/oracle_eval.txt— oracle evaluation summary.bundle/repro/runtime_manifest.json— runtime manifest (entrypoint_kind=tcp_peer,service_started=true,healthcheck_passed=true,target_path_reached=true).bundle/repro/validation_verdict.json— structured verdict (claim_outcome=confirmed).
Key excerpt (vulnerable 0.7.4 events):
[
{"type":"open"},
{"type":"message","data":"POSITIVE-CTRL-OK"},
{"type":"message","data":"POSITIVE-CTRL-OK"} // stale re-emit; sentinel "SENTINEL-VULN-XYZ-12345" never delivered
]
Key excerpt (fixed 0.7.5 events):
[
{"type":"open"},
{"type":"message","data":"POSITIVE-CTRL-OK"},
{"type":"close"} // guard closes on over-limit length header; no corrupted message
]
Wire bytes (hex): malicious header 80ffffff7f → computed _length = 268435455 > maxLength 67108863; sentinel 0053454e54494e454c2d56554c4e2d58595a2d3132333435ff.
Environment: Node.js v24.x on Linux; net loopback TCP; websocket-driver 0.7.4 (vulnerable) and 0.7.5 (fixed) from the published npm package; no sanitizers (production path, sanitizer_used=false).
Recommendations / Next Steps
- Upgrade: Pin
websocket-driverto>= 0.7.5(the guardif (this._length > this._maxLength) return this.close();is the canonical fix). - Defense in depth: Where legacy hixie-75/76 framing is not required, disable draft-75/76 negotiation at the HTTP upgrade layer so
Server.httpnever selectsDraft75/Draft76. - Testing: Add a regression test that feeds
0x80 0xFF 0xFF 0xFF 0x7F+ a sentinel text frame throughDriver.server()over a real socket and asserts (1) acloseevent fires and (2) nomessageevent carries stale/sentinel content. Also assert the positive-control text frame still delivers. - Variant exploration (next stage): Confirm the same accumulator path is reachable through
Draft76(hixie-76) once the 8-byte challenge body is satisfied, and check whether intermediate_lengthvalues just under_maxLengthcan still cause partial misframing without tripping the guard.
Additional Notes
- Idempotency: The script was run twice consecutively with identical results (oracle
CONFIRMED=trueboth times, identical event shapes and wire bytes); the only nondeterministic field is the event timestampt. - Minimal deterministic octet sequence derived from shipped source:
0x80 0xFF 0xFF 0xFF 0x7F(5 bytes) drives_lengthto268435455, the smallest terminator-using sequence that exceeds_maxLength(67108863) using all-high-bit continuation octets. The physical wire input (header + sentinel) is under 40 bytes — no resource exhaustion. - Real package, real socket: The proof exercises the published
websocket-driverpackage throughDriver.server(...).parse(chunk)over a real loopback TCP socket (not a copied parser or reimplementation), satisfying thenetwork_protocol/tcp_peerentrypoint requirement. - Limitations: The oracle uses an in-process
netloopback peer; no external network is involved. The driver'sclose()in the fixed build ends the connection before the sentinel, sosentinel_delivered=falsein both builds — the discriminator is thecloseevent plus the absence of a corrupted/stale message in the fixed build versus the stale re-emit + open state in the vulnerable build.
Variant Analysis & Alternative Triggers for CVE-2026-54466
The 0.7.5 fix for CVE-2026-54466 adds a single guard in the draft-75 length accumulator (case 1): if (this._length > this._maxLength) return this.close(). This prevents oversized length headers but does not address the two independent root-cause bugs that actually produce the message corruption: (A) _parseLeadingByte does not reset this._buffer when entering binary frame mode, leaving a stale reference to the previous text frame's content; and (B) in stage 2, the if (octet === 0xFF) frame-terminator check fires before the skip-mode branch, so 0xFF is treated as a frame terminator even during binary-frame payload consumption. By sending a binary frame with a valid length (within _maxLength) that is >= the next frame's wire size, an attacker can cause the parser to consume a subsequent valid sentinel text frame as skip data; when the sentinel's 0xFF terminator is encountered in skip mode, the stale _buffer is emitted as a message, and the sentinel is lost. This bypass is confirmed on the fixed 0.7.5 build — the _maxLength guard never fires because the length is well within bounds.
Fix Coverage / Assumptions
- Invariant the fix relies on: "If
_length <= _maxLength, the parser state is safe." The fix assumes that message corruption requires an oversized_lengthto function. - Code paths explicitly covered:
case 1(the base-128 length accumulator inDraft75.prototype.parse). The guard fires after every continuation octet, closing the driver if the accumulated_lengthexceeds_maxLength. This covers bothDraft75andDraft76(which inheritsparsefromDraft75). - What the fix does NOT cover:
_parseLeadingBytedoes not resetthis._bufferwhen the high bit is set (binary frame path). The stale buffer from a prior text frame persists.- Stage 2's
if (octet === 0xFF)check fires unconditionally — before the skip-mode branch (if (this._length)) — so0xFFis treated as a frame terminator even in skip mode, emitting the stale buffer. - These two gaps combine to allow the same message corruption with a valid, bounded
_length.
Variant / Alternate Trigger
Bypass path: binary frame with valid (within _maxLength) length header
Entry point:
Driver.server(...).parse(chunk)/Server.parse(chunk)→Draft75.parse()— the same public runtime path as the original CVE, selected via a draft-75 handshake (noSec-WebSocket-*headers).Wire sequence:
- Positive control text frame:
0x00 "POSITIVE-CTRL-OK" 0xFF→ populates_bufferwith"POSITIVE-CTRL-OK" - Variant binary frame header:
0x80 0x1E→_parseLeadingByte: high bit set →_length=0,_stage=1. Thencase 1:_length = (0x1E & 0x7F) + 128*0 = 30. Fix guard:30 > 67108863→ false, does NOT fire. High bit clear →_length != 0→_skipped=0,_stage=2(skip mode)._bufferstill holds stale"POSITIVE-CTRL-OK". - Sentinel text frame:
0x00 "SENTINEL-VULN-XYZ-12345" 0xFF(25 bytes) → consumed byte-by-byte in skip mode. Bytes 0–23: not0xFF,_skippedincrements to 24 (< 30, stay in stage 2). Byte 24:0xFF→if (octet === 0xFF)fires → emitsBuffer.from(this._buffer)= stale"POSITIVE-CTRL-OK"as a message →_stage=0.
- Positive control text frame:
Code path:
lib/websocket/driver/draft75.js→parse()→case 0(_parseLeadingByte) →case 1(length accumulator, fix guard passes) →case 2(skip mode,0xFFtriggers stale buffer emission).Result: Sentinel is consumed and lost. A stale duplicate of the previous message is emitted instead. The connection stays open (
readyState=1). This is identical to the original CVE's impact.Package/component affected:
websocket-driver,Draft75/Draft76parser path (lib/websocket/driver/draft75.js), reached viaDriver.server(...)/Server.parse(chunk).Affected versions (as tested):
websocket-driver@0.7.4(vulnerable) andwebsocket-driver@0.7.5(fixed — bypass confirmed). Both are affected by this variant.Risk level and consequences: Critical protocol-level message corruption / message loss. An attacker who can write raw bytes to an established draft-75/76 connection can cause the parser to drop the framing boundary of a legitimate frame and emit a stale/misframed application message, defeating message integrity. The wire allocation is tiny (7 bytes for the variant + sentinel). The connection stays open, so the corruption is silent and ongoing.
Impact Parity
- Disclosed/claimed maximum impact: Protocol message corruption / message loss (impact class
other), via abuse of the draft-75/76 framing on a negotiated hixie-75/76 connection. - Reproduced impact from this variant run: On both
0.7.4and0.7.5, the driver remained open (readyState=1) after the variant binary frame, did not deliver the uniquely-marked sentinel text frame, and instead re-emitted a stale copy of the previous (positive-control) message. Positive control delivered in both builds, proving the parser/listener path was operational. - Parity:
full— the reproduced behavior matches the disclosed message-corruption/message-loss impact exactly, and the bypass reproduces identically on the fixed build. - Not demonstrated: No code execution, no memory exhaustion, no native crash — none claimed.
Root Cause
The message corruption in the draft-75 parser has two independent root-cause bugs:
Stale
_buffer(Gap A): In_parseLeadingByte, when a leading byte with the high bit set is received (binary frame),_bufferis NOT reset. It retains the content from the previous text frame. The text-frame path (high bit clear) correctly creates a freshthis._buffer = [], but the binary-frame path does not.0xFFas unconditional frame terminator in stage 2 (Gap B): Incase 2, the checkif (octet === 0xFF)is the first branch, before the skip-mode/text-mode split. In skip mode (this._lengthis truthy),0xFFshould be treated as a payload data byte, not a frame terminator. Instead, it emitsBuffer.from(this._buffer)(the stale buffer from Gap A) as a message and resets to stage 0.
The 0.7.5 fix (commit 5b197ca) only adds the _maxLength guard in case 1. It does not address Gap A or Gap B. Because a valid, bounded _length (e.g., 30) is sufficient to trigger the corruption — the attacker just needs _length >= the sentinel frame's wire size so the sentinel's 0xFF terminator is encountered in skip mode before _skipped reaches _length — the fix is bypassable.
Fix reference: commit 5b197ca874dab58e96cacad8a3c256797d804680 → lib/websocket/driver/draft75.js, one added line.
Reproduction Steps
- Reference:
bundle/vuln_variant/reproduction_steps.sh(driver script) andbundle/vuln_variant/variant_harness.js(Node TCP peer harness). Both are self-contained; the script reuses the prepared project cache (bundle/project_cache_context.json,prepared=true) when available and otherwise falls back tonpm install websocket-driver@0.7.4/@0.7.5. - What the script does:
- Resolves the vulnerable (
0.7.4) and fixed (0.7.5) publishedwebsocket-driverpackages from the durable project cache (or installs them). - Verifies the versions and the presence of the
_maxLengthguard indraft75.jsfor the fixed build. - For each build, runs
variant_harness.js, which starts a real loopback TCP server usingnet.createServer+Driver.server({requireMasking:false}), pipesconnection ↔ driver.io, and a raw TCP client performs a draft-75 handshake (noSec-WebSocket-*headers) soServer.httpselectsDraft75. - Sends: (1) a positive-control draft-75 text frame, (2) a variant binary frame header
0x80 0x1E(valid length=30, within_maxLength), immediately followed by (3) a uniquely-marked sentinel text frame — all in a contiguous wire stream. - Records every emitted
open/message/close/errorevent, the driverreadyState, and the exact wire bytes, then writes a JSON result file. - Evaluates the oracle: on both versions,
sentinel_delivered=false,corrupted_message_after_malicious=true(stale re-emit),close_after_malicious=false,readyState_final=1.
- Resolves the vulnerable (
- Expected evidence:
bundle/logs/variant_oracle_eval.txtshowsBYPASS CONFIRMED: true— the variant reproduces on the fixed0.7.5build with exit code 0.
Evidence
Log locations:
bundle/logs/variant_repro.log— driver script outputbundle/logs/vuln_variant_run.log— vulnerable 0.7.4 harness outputbundle/logs/fixed_variant_run.log— fixed 0.7.5 harness outputbundle/logs/vuln_variant_result.json— vulnerable 0.7.4 structured resultbundle/logs/fixed_variant_result.json— fixed 0.7.5 structured resultbundle/logs/variant_oracle_eval.txt— oracle evaluation
Key excerpt (fixed 0.7.5):
Fixed 0.7.5: positive_control_delivered : true sentinel_delivered : false close_after_malicious : false corrupted_message_emitted : true positive_message_count : 2 (2+ => stale re-emit = misframing) readyState_final : 1 (1=open, 3=closed) Oracle verdict: vuln_path_matches : true fixed_path_matches : true BYPASS CONFIRMED : true variant_length : 30 <= maxLength 67108863 (fix guard does NOT fire)Environment: Node.js, loopback TCP,
websocket-driver@0.7.4and@0.7.5from published npm packages (cached in project cache). Fixed build commit:5d6a9aaf5f019007d917bd9ddc7eeb775c86cc1f.
Recommendations / Next Steps
The fix must be extended to close Gap A and Gap B:
Reset
_bufferin_parseLeadingBytewhen entering binary frame mode. Addthis._buffer = [];(ordelete this._buffer) in theif ((octet & 0x80) === 0x80)branch, alongsidethis._length = 0andthis._stage = 1.Restrict the
0xFFframe-terminator check in stage 2 to text mode only. Move theif (octet === 0xFF)check inside theelsebranch (where_lengthis falsy / text mode), or restructure so that in skip mode (this._lengthis truthy),0xFFis treated as a regular skip byte. For example:case 2: if (this._length) { // skip mode: 0xFF is a data byte, not a terminator this._skipped += 1; if (this._skipped === this._length) this._stage = 0; } else { // text mode if (octet === 0xFF) { this._stage = 0; message = Buffer.from(this._buffer).toString('utf8', 0, this._buffer.length); this.emit('message', new Base.MessageEvent(message)); } else { this._buffer.push(octet); if (this._buffer.length > this._maxLength) return this.close(); } } break;
Either fix alone would partially mitigate the issue, but both should be applied for defense in depth.
Additional Notes
- Idempotency: The reproduction script was run twice with identical results (exit code 0 both times). The script is idempotent and deterministic.
- Edge cases: The variant length must be
>=the sentinel frame's wire size (25 bytes in this test) for the sentinel's0xFFterminator to be encountered in skip mode before_skippedreaches_length. A length of 30 provides a safe margin. Any length from 25 to_maxLength(67,108,863) works. - Draft76 coverage:
Draft76inheritsparsefromDraft75and does not override it, so the bypass applies to draft-76 connections as well. The server selectsDraft76whenSec-WebSocket-Key1/Sec-WebSocket-Key2headers are present. - Client-side parser: The client-side driver (
client.js) usesHybi(modern WebSocket protocol), notDraft75, so the client-side parser is not affected by this variant.
CVE-2026-54466 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support · claim contract · reproduction · judge · variant analysis
Full session Replay every step — scrub the timeline or play it back.
cd /data/pruva/project-cache/a075e72d-24e1-4a1d-a5ed-88cbb2e0a266 && ls -la repo vuln fixed 2>/dev/null; echo "---vuln---"; ls -la vuln 2>/dev/null; echo "---fixed---"; ls -la fixed 2>/dev/null{"cwd":"/data/pruva/runs/294686a0-89e7-4ba8-a27d-7fca0e3a9e70","duration_ms":7,"exit_code":0,"stderr":"","stdout":"fixed:\ntotal 8\ndrwxr-xr-x 1 vscode vscode 82 Jul 16 08:11 .\ndrwxr-xr-x 1 vscode vscode 62 Jul 16 08:18 ..\ndrwxr-xr-x 1 vscode vscode 158 Jul 16 08:11 node_modules\n-rw-r--r-- 1 vscode vscode 2085 Jul 16 08:11 package-lock.json\n-rw-r--r-- 1 vscode vscode 299 Jul 16 08:11 package.json\n\nrepo:\ntotal 40\ndrwxr-xr-x 1 vscode vscode 194 Jul 16 08:10 .\ndrwxr-xr-x 1 vscode vscode 62 Jul 16 08:18 ..\ndrwxr-xr-x 1 vscode vscode 122 Jul 16 10:42 .git\ndrwxr-xr-x 1 vscode vscode 18 Jul 16 08:10 .github\n-rw-r--r-- 1 vscode vscode 31 Jul 16 08:10 .gitignore\n-rw-r--r-- 1 vscode vscode 4358 Jul 16 08:10 CHANGELOG.md\n-rw-r--r-- 1 vscode vscode 162 Jul 16 08:10 CODE_OF_CONDUCT.md\n-rw-r--r-- 1 vscode vscode 558 Jul 16 08:10 LICENSE.md\n-rw-r--r-- 1 vscode vscode 12960 Jul 16 08:10 README.md\ndrwxr-xr-x 1 vscode vscode 52 Jul 16 08:10 examples\ndrwxr-xr-x 1 vscode vscode 18 Jul 16 08:10 lib\n-rw-r--r-- 1 vscode vscode 1204 Jul 16 08:10 package.json\ndrwxr-xr-x 1 vscode vscode 36 Jul 16 08:10 spec\n\nvuln:\ntotal 8\ndrwxr-xr-x 1 vscode vscode … [truncated]cd /data/pruva/project-cache/a075e72d-24e1-4a1d-a5ed-88cbb2e0a266 && echo "=== vuln pkg ==="; cat vuln/package.json; echo "=== fixed pkg ==="; cat fixed/package.json; echo "=== vuln node_modules ==="; ls vuln/node_modules; echo "=== fixed node_modules ==="; ls fixed/node_modules=== vuln pkg ===
{
"name": "vuln",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"Artifacts and Evidence for CVE-2026-54466
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-54466
Upgrade faye/websocket-driver-node · npm to 0.7.5 or later.
FAQ: CVE-2026-54466
Does CVE-2026-54466 lead to remote code execution?
How is CVE-2026-54466 fixed?
Which versions of websocket-driver are affected by CVE-2026-54466?
How can I reproduce CVE-2026-54466?
References for CVE-2026-54466
Authoritative sources for CVE-2026-54466 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.