Skip to content

[Security] Receive window check rejects only exactly-zero credit — negative window enables unbounded buffering (CWE-400) #1505

Description

@afldl

Summary

The ssh2 package for Node.js (tested: 1.17.0, ref 318d447ce3ac) does not correctly enforce its advertised SSH channel receive window. The inbound CHANNEL_DATA handler rejects data only when the remaining window is exactly zero, then subtracts the payload length regardless — a single oversized payload drives the window negative, after which every subsequent packet passes the guard and is buffered. Post-authentication memory-exhaustion DoS.

Affected version

ssh2 (npm), default branch, ref 318d447ce3ac (latest as of 2026-07).

Root cause

lib/client.js (CHANNEL_DATA handler):

if (channel.incoming.window === 0)   // line 580: only EXACTLY zero
  return;
channel.incoming.window -= data.length;   // line 583: can go negative
if (channel.push(data) === false) {       // line 585: buffered anyway

Client advertises MAX_WINDOW = 2 * 1024 * 1024 (2 MiB). The guard should be data.length > channel.incoming.window; once window goes negative, === 0 never matches again → unbounded buffering.

PoC (end-to-end)

[server] channel open; client advertised window = 2097152 bytes
[driver] child baseline VmRSS=60600 kB
[server] sent 18874368 bytes of CHANNEL_DATA (16777216 beyond advertised window)
[driver] child VmRSS peak=88784 kB (growth=28184 kB = 27.5 MiB)
[driver] VERDICT: CONFIRMED

Client advertised 2 MiB window; RSS grew 27.5 MiB while 16 MiB was pushed beyond window.

Suggested fix

if (data.length > channel.incoming.window)
  return;  // or disconnect
channel.incoming.window -= data.length;

Apply to both CHANNEL_DATA and CHANNEL_EXTENDED_DATA handlers.

CWE

CWE-400 (Uncontrolled Resource Consumption), post-authentication.

Credit

Reported by zhangph (afldl), 2026-07.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions