Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-48069

CVE-2026-48069: @grpc/grpc-js DOS Vulnerability

CVE-2026-48069 is a denial of service flaw in @grpc/grpc-js that allows invalid compressed messages to crash client or server processes. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-48069 Overview

CVE-2026-48069 is a denial-of-service vulnerability in @grpc/grpc-js, the pure JavaScript implementation of gRPC used widely across Node.js clients and servers. An invalid incoming compressed message triggers an unhandled error in the decompression pipeline, causing the host process to crash. Because the flaw is reachable over the network without authentication or user interaction, any gRPC endpoint exposed to untrusted peers is at risk. The maintainers addressed the issue in versions 1.9.16, 1.10.12, 1.11.4, 1.12.7, 1.13.5, and 1.14.4. The weakness is tracked under [CWE-248] (Uncaught Exception).

Critical Impact

A single crafted compressed gRPC message can crash a client or server process, enabling remote denial of service against services built on @grpc/grpc-js.

Affected Products

  • @grpc/grpc-js versions prior to 1.9.16 (1.9.x branch)
  • @grpc/grpc-js versions prior to 1.10.12, 1.11.4, and 1.12.7
  • @grpc/grpc-js versions prior to 1.13.5 and 1.14.4

Discovery Timeline

  • 2026-07-14 - CVE-2026-48069 published to NVD
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-48069

Vulnerability Analysis

The vulnerability lives in the decompression path used by both client and server code in @grpc/grpc-js. When a peer sends a gRPC message with a compression flag set, the library instantiates a Node.js zlib stream (for example, zlib.createInflate()) and pipes the incoming payload through it. If the payload is not valid deflate or gzip data, the zlib stream emits an error event. Without an attached error listener, Node.js promotes that event to an uncaught exception and terminates the process. This behavior is characteristic of [CWE-248] Uncaught Exception. The attack requires only the ability to send a single request or response frame to the target endpoint. Any gRPC service or client that supports message compression is affected, regardless of the RPC method invoked.

Root Cause

The root cause is missing error handling on the zlib decompression stream in both compression-filter.ts (client side) and server-interceptors.ts (server side). The code registered a data handler for successful chunks but never registered an error handler for malformed input. When the inflate operation failed, the emitted error had no listener and propagated to the Node.js runtime as an uncaught exception.

Attack Vector

An unauthenticated remote attacker sends a gRPC message with a compression flag set and a payload that fails deflate or gzip decoding. The target process receives the frame, dispatches it to the decompression filter, and crashes. Repeated requests keep the service offline. The attack works against both @grpc/grpc-js servers accepting client calls and clients receiving server responses.

typescript
// Fix in packages/grpc-js/src/compression-filter.ts
// Adds an error listener so malformed deflate payloads no longer
// crash the process; instead they reject with a gRPC INTERNAL status.
      let totalLength = 0;
      const messageParts: Buffer[] = [];
      const decompresser = zlib.createInflate();
+     decompresser.on('error', (error: Error) => {
+       reject({
+         code: Status.INTERNAL,
+         details: 'Failed to decompress deflate-encoded message'
+       });
+     });
      decompresser.on('data', (chunk: Buffer) => {
        messageParts.push(chunk);
        totalLength += chunk.byteLength;

// Source: https://github.com/grpc/grpc-node/commit/2375eadcc52ca2b1ef55288bcd6355168b02706c
typescript
// Fix in packages/grpc-js/src/server-interceptors.ts
// Server-side decompression path receives the same error handler.
      return new Promise((resolve, reject) => {
        let totalLength = 0
        const messageParts: Buffer[] = [];
+       decompresser.on('error', (error: Error) => {
+         reject({
+           code: Status.INTERNAL,
+           details: `Failed to decompress ${encoding}-encoded message`
+         });
+       });
        decompresser.on('data', (chunk: Buffer) => {
          messageParts.push(chunk);
          totalLength += chunk.byteLength;

// Source: https://github.com/grpc/grpc-node/commit/2375eadcc52ca2b1ef55288bcd6355168b02706c

Detection Methods for CVE-2026-48069

Indicators of Compromise

  • Unexpected Node.js process exits with stack traces referencing zlib, Inflate, compression-filter, or server-interceptors.
  • gRPC server logs showing abrupt termination immediately after receiving a request with a non-zero compression flag.
  • Process supervisors (systemd, PM2, Kubernetes) reporting repeated restarts of the same gRPC workload from a small set of source IPs.

Detection Strategies

  • Inventory Node.js applications for @grpc/grpc-js using npm ls @grpc/grpc-js or SBOM scans and flag versions below the patched releases.
  • Correlate container or pod restart events with inbound gRPC traffic patterns to identify crash-loop denial of service.
  • Add synthetic monitoring that sends a malformed compressed payload against a canary endpoint to verify patched behavior returns INTERNAL instead of crashing.

Monitoring Recommendations

  • Alert on Node.js uncaught exception logs containing Error: incorrect header check, Error: invalid stored block lengths, or similar zlib messages.
  • Track gRPC status code distributions and alert when INTERNAL responses tied to decompression spike from single peers.
  • Watch process restart counters in orchestrators and correlate them with source IPs sending compressed gRPC frames.

How to Mitigate CVE-2026-48069

Immediate Actions Required

  • Upgrade @grpc/grpc-js to 1.9.16, 1.10.12, 1.11.4, 1.12.7, 1.13.5, or 1.14.4 on the branch you currently deploy.
  • Rebuild and redeploy all Node.js services and container images that transitively depend on @grpc/grpc-js.
  • Audit third-party libraries that bundle @grpc/grpc-js and confirm they resolve to a patched version.

Patch Information

The fix adds an error listener to the zlib decompression stream in both compression-filter.ts and server-interceptors.ts, converting decompression failures into rejected promises with gRPC status INTERNAL. Patched releases and commits are documented in the GitHub Security Advisory GHSA-99f4-grh7-6pcq and the release notes for v1.14.4, v1.13.5, v1.12.7, v1.11.4, v1.10.12, and v1.9.16.

Workarounds

  • If patching is delayed, disable server-side compression support so incoming compressed frames are rejected before reaching the vulnerable code path.
  • Terminate gRPC traffic at a proxy (Envoy, NGINX) that validates or strips compression before forwarding to @grpc/grpc-js backends.
  • Restrict network exposure of gRPC endpoints to authenticated peers using mTLS or network policies until upgrades complete.
bash
# Upgrade @grpc/grpc-js to the patched release on your branch
npm install @grpc/grpc-js@1.14.4

# Verify no vulnerable versions remain in the dependency tree
npm ls @grpc/grpc-js

# Audit for known advisories including GHSA-99f4-grh7-6pcq
npm audit --production

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.