What CVE-2026-111497 actually affects

Cybersecurity engineer reviewing a protected Brotli decoder dependency pipeline across servers, containers, and software layers.

CVE-2026-111497 is an out-of-bounds write in the Google Brotli decoder. The defect is reached when a vulnerable application decompresses a malformed Brotli-compressed stream: the decoder handles an invalid block switch as if it only needs more input, then continues appending bytes to an internal eight-byte buffer. That lets input pass beyond the intended memory boundary. In Node.js, the affected code is bundled with the runtime’s zlib module, so an application that uses Brotli decompression can expose the flaw without installing a separate package called brotli.

The Node.js security release describes the consequence directly. An attacker who can supply Brotli data that an application decompresses with node:zlib may corrupt process memory, potentially causing a crash, disclosure of process memory, or remote code execution. The release rates the issue as high severity and identifies Node.js 26.x, 24.x, and 22.x as affected release lines. The relevant question for an owner is therefore not only “Which Node.js version is installed?” but also “Can this running process be made to decompress Brotli data that comes from an attacker or another untrusted system?”

That condition is important because the vulnerability is not equivalent to a compromise of every machine containing a Brotli-capable library. The Red Hat bulletin describes the same issue as a crafted stream that can corrupt memory in an application processing untrusted Brotli input. It lists possible outcomes including information disclosure, denial of service, and arbitrary code execution, while also noting that environments in which no application decompresses Brotli data from untrusted sources are not affected in practice. Exploitation requires a specifically malformed stream; ordinary, well-formed output from a normal encoder does not trigger the issue.

The decoder’s location is what makes the inventory problem easy to underestimate. Brotli is used for HTTP Content-Encoding: br, but it can also appear as a standalone library, as Python bindings, inside browsers and other clients, or as part of a larger product. Red Hat identifies the library as available through packages such as brotli and Python Brotli bindings, while also noting that Node.js bundles it as part of zlib. The same bulletin points to embedded copies in Firefox, Thunderbird, and layered products. A software inventory that records only top-level applications may therefore show an apparently ordinary service while hiding the native decoder that actually parses externally supplied compressed bytes.

This is also why the CVE identifier should be tracked at two levels. The CVE record names the underlying vulnerability, while a runtime or product advisory identifies how that component is packaged, patched, or backported in a particular distribution. A Node.js update can remediate the copy bundled into Node.js, but it says nothing by itself about a separate Brotli library, a Python binding, a browser build, an appliance image, or another product that embeds its own copy. Conversely, finding the CVE in a scanner does not prove that the affected decoding path is reachable from an untrusted source.

The first useful classification is consequently a combination of component and input path. Record where Brotli enters the system, which product or runtime owns the running copy, and whether that copy handles network responses, HTTP requests, uploaded data, remote artifacts, or other content controlled outside the trust boundary. In Node.js, that review should include uses of Brotli decompression APIs and any behavior that automatically decodes br responses. For other products, use the vendor’s component advisory and release notes rather than assuming that a package name or application version maps cleanly to the vulnerable binary.

This approach keeps confirmed behavior separate from exploit speculation. The available advisories establish a memory-safety flaw with potentially serious consequences when vulnerable decoding processes attacker-controlled input. They do not establish that every installation is exposed in the same way or that a broad, confirmed exploitation campaign is underway. The defensible priority is to locate the decoders that are both vulnerable and reachable, then verify the fixed release for the product that actually ships them. That is the foundation for the dependency inventory required in the next stage.

Why a Node.js fix does not close the whole exposure

Updating Node.js is necessary when an application uses an affected release line, but it is not a complete answer to CVE-2026-111497. The vulnerable code is in the Google Brotli C decoder, and Cisco notes that this component is often bundled with or linked to software beyond Node.js. A product can therefore inherit the same defect without presenting itself as a Node.js application in an inventory, and without giving operators a separate Brotli package to update. The relevant question is not only “Which Node.js versions do we run?” It is also “Which products contain a Brotli decoder, and which of them can be made to decompress data supplied by someone else?”

Cisco’s November 5 advisory illustrates why that distinction matters operationally. Cisco is reviewing products individually rather than treating the entire portfolio as uniformly affected. Its priority-product table records different outcomes: Catalyst SD-WAN Software, Identity Services Engine, IOS XE Software, Secure Firewall Management Center, and Secure Firewall Threat Defense are listed as not impacted, while IOS XR Software and Secure Firewall Adaptive Security Appliance Software remain under investigation. NX-OS Software is directed to other impact and fix tables. That variation is evidence that a vendor-level assessment depends on how a particular product incorporates and uses the shared component, not simply on whether the vendor ships software associated with Node.js or Brotli.

The same advisory lists products under active investigation across a wide range of categories, including application observability, network and content security, network management, routing and switching, unified computing, video and collaboration, wireless services, and Cisco-hosted services. This breadth is important for asset owners because the affected execution path may sit inside an appliance, controller, virtual appliance, endpoint utility, or cloud-connected service. The product name that appears in a CMDB may describe the business function—such as a firewall manager, controller, or collaboration platform—while the vulnerable decoder is buried in a runtime, bundled library, or service component. A conventional application inventory can therefore be accurate at the product level and still fail to identify the code that processes compressed input.

Cisco’s fixed-release table also shows why “patched” cannot be treated as a single portfolio-wide state. The advisory identifies different remediation tracks for different products: Duo Network Gateway is associated with release 3.4.2, the Duo Authentication Proxy Local Manager for Windows with 6.8.1, and Catalyst Center with 3.4.1. Other entries have a release number still to be determined or a release target marked as pending. Those distinctions mean that an organization must match the exact product, deployment form, and release branch it operates against the vendor’s status and fixed version. Installing an updated Node.js package on a build host does not prove that an appliance image, embedded service, or separately maintained product has received the corresponding correction.

There is a second inventory trap in the data flow itself. A service may not expose a user-facing Brotli feature, yet still decode Brotli when handling HTTP content or another externally supplied stream. Red Hat describes exposure in terms of the decoder receiving untrusted Brotli data and gives examples that include HTTP exchanges using Content-Encoding: br, Node.js decompression APIs, and applications that call the Brotli library directly. That is a more useful assessment boundary than the presence of a package name alone. Teams should ask whether the component can receive attacker-controlled compressed bytes, through which listener or integration, and whether the running product—not just its source dependency manifest—contains the vulnerable decoder.

This is also why a clean dependency scan can produce false reassurance. A lockfile may show an application dependency but omit a library compiled into a vendor binary. Conversely, a host package inventory may show a system Brotli package even when the exposed service uses a private copy inside its own image. Cisco’s advisory directs administrators to product-specific bug records and fixed software releases, while Red Hat notes that layered products and containers may depend on updated base packages. The practical unit of remediation is therefore the deployed product and its executable decoding path. Node.js updates close the Node.js component where they are installed; they do not automatically close every Cisco product, appliance, container, or service that may carry the same Brotli decoder.

The defensive inventory that matters

The useful question is not simply whether a server has Node.js installed. It is which components can decode Brotli data, where those components are running, and whether the data they receive can be influenced by an untrusted party. The decoder may be part of Node.js, a Brotli library used through Python bindings, an SDK bundled into an application, a container image, or an appliance that presents no obvious package-level view to the operating team. A conventional software inventory can therefore identify the application while missing the library that performs the relevant parsing.

Start with an inventory of execution environments rather than a search for one package name. Record Node.js installations and the applications that embed or depend on them. Check services using Brotli support through Python bindings or other language integrations, and include bundled SDKs whose dependencies are maintained separately from the host operating system. Extend the review to containers, base images, build artifacts, and vendor appliances. For each item, capture the product and release, the image or firmware version, the process that loads the decoder, and the owner responsible for updating it. The goal is to connect an abstract dependency to the binary that will actually process data.

The next distinction is exposure. A decoder present on a system is not automatically an exposed decoder. Map the paths by which each service receives compressed content: public HTTP requests, authenticated but remotely supplied uploads, messages from external systems, proxy traffic, package or artifact feeds, and administrative interfaces. Also record services that decompress data indirectly, such as gateways, brokers, API components, or application workers. This mapping should describe the data flow at a high level; it does not require testing the flaw or sending crafted input. It is enough to establish whether an attacker, an untrusted client, or an upstream system can control content that reaches the Brotli decoding path.

A practical inventory can be organized around four questions for every runtime or product:

  • What decodes Brotli? Identify the runtime, library, binding, SDK, appliance component, container layer, or service implementation involved.
  • Where does it run? Record hosts, containers, images, firmware, deployment environments, and the process or product that loads it.
  • Who can supply the input? Mark whether compressed data comes from the public network, a partner, a user, an internal service, or a controlled source.
  • Which vendor release fixes it? Compare the observed product or component with the applicable fixed release from Node.js, the product vendor, or the distributor that supplies the package.

That last comparison must be made at the level of the product that is deployed. A Node.js update may address the runtime in one service while leaving a separate appliance, SDK, or copied library unchanged. Conversely, a vendor may publish a product update that includes the corrected decoder without changing the way the dependency appears in an application-level package report. The authoritative answer is the vendor’s advisory and fixed release for the affected product, followed by confirmation of what is present in the running environment.

Containers require particular care because updating a lockfile or package manifest does not change an already built image. Check the dependency resolution used during the build, but also inspect the resulting image or its installed runtime and then redeploy it. Images that are rebuilt from an unchanged base layer can reproduce the same vulnerable component even when the application source has not changed. Once a corrected image is available, replace the running workload rather than assuming that a later build will alter existing containers in place. Keep the old image and deployment association clear enough to identify which instances still need attention.

The same principle applies to long-lived processes and appliances. A package update may not affect a process that already loaded the old library, and an appliance update may require a documented restart or firmware activation before the corrected component is used. Treat restart requirements as part of the remediation record: note the update applied, the instance or device restarted, the time at which the new process or firmware became active, and the evidence used to confirm it. If a product has no independently visible package inventory, rely on its vendor release mapping and operational verification rather than inferring safety from an unrelated application version.

This inventory also helps prioritize work without turning every occurrence into an emergency. Give precedence to decoders reachable through internet-facing services or remotely supplied content, then to shared gateways, high-value appliances, and workloads whose outputs are consumed by other systems. For isolated development tools or services that decode only controlled data, the risk assessment may differ, but they should remain recorded until the owning team has compared them with the applicable vendor guidance. The resulting map should be a living remediation list: each entry has a product owner, an exposure assessment, a fixed-release comparison, and a verification step tied to the component that actually runs.

Patch, contain, and verify without guessing

A defensible response starts with triage, not with the assumption that every system using Node.js is equally exposed. Rank decoders by how compressed data reaches them: internet-facing services and gateways first, then applications accepting uploads or partner messages, followed by internal services fed from less trusted networks. The key question is not whether a host contains a vulnerable release somewhere in its inventory. It is whether that release is the component actually decoding attacker-controlled Brotli data in a running process or product.

For each candidate, record the owning team, product and release, runtime or library source, deployment form, and input path that invokes decoding. Include Node.js installations, applications that bundle Node.js, direct Brotli libraries, language bindings such as Python integrations, SDKs, containers, and appliances. A vendor advisory may assign different statuses to different product releases, so check the exact product version rather than inferring exposure from a generic statement about the underlying library. Cisco’s advisory demonstrates why this matters: the same underlying issue can appear across products with different remediation states.

The preferred fix is the documented update from the component or product vendor. If the decoder is supplied through Node.js, use the release identified by the Node.js security guidance. If it is embedded in an appliance, SDK, or application, follow that supplier’s release and deployment instructions. Do not treat replacing a top-level dependency as proof that every bundled copy disappeared. A lockfile describes a build resolution; the deployed image may still contain an older transitive package, vendored source, native module, or separate runtime layer. Closure depends on the artifact that executes.

Temporary containment should be narrow, documented, and reversible. Where operationally possible, reduce or suspend the specific route that accepts untrusted Brotli content, place it behind an approved filtering or gateway control, or take an exposed component out of service while the fix is prepared. These measures are not substitutes for patching, and teams should not invent them from assumptions about a product’s compression behavior. Use only mitigations documented by the responsible vendor or validated through the organization’s change and security processes. Record when the control began, what function it affects, and who must remove it after remediation.

Deployment details are part of remediation. A process that loads its runtime or shared library at startup may continue using the old decoder until it is restarted. A container image may be rebuilt correctly while existing replicas still serve traffic from the previous image. After a rolling update, confirm that old pods, workers, sidecars, and appliance nodes have drained or restarted, and that failover or autoscaling will not reintroduce the superseded artifact. For systems outside the main application pipeline, include service restarts or appliance reboots in the change record, following the product’s documented procedure.

Verification should combine software evidence with exposure evidence. Identify the exact running binary, runtime, image digest, package manifest, or vendor build serving the decoding path, then compare it with the fixed release named by the applicable CVE record, Node.js release, or product advisory. Confirm that the relevant process restarted and that expected instances are running the new artifact; a source repository, package cache, or CI result alone is not proof. Recheck duplicate copies in dormant images, backup configurations, test environments connected to production feeds, and appliances maintained by another team.

The record should state what was and was not observed: affected versions found, fixed versions deployed, routes receiving untrusted compressed input, temporary controls, and relevant monitoring results. The cited sources establish the vulnerability and remediation context, but do not establish confirmed widespread exploitation. That distinction supports a proportionate response: prioritize reachable decoders and verify fixes quickly, without claiming that every Brotli consumer was attacked or that remediation succeeded merely because a dependency file changed. The endpoint is a running, inventoried service whose decoder is tied to a documented fixed release—and whose deployment path will not silently restore the vulnerable component.