Jun 15, 2026·6 min read·49 visits
Missing binary integrity verification in esbuild's Deno installer allows unauthenticated remote code execution via a poisoned registry configuration.
An issue was discovered in the Deno integration of the esbuild package. The module fails to verify the integrity of downloaded native binary packages from NPM registries before writing and executing them on the local filesystem. This allows an attacker who controls the NPM_CONFIG_REGISTRY environment variable or intercepts the network connection to execute arbitrary native code on the host machine.
The Deno integration module of the esbuild package downloader exposes an unauthenticated remote code execution vulnerability. When running in a Deno environment, esbuild retrieves platform-specific native binaries from an NPM registry. The vulnerability arises because the installer fails to perform cryptographic signature or integrity verification on the downloaded tarball before writing the binary to the local system and executing it.
An attacker can trigger this vulnerability by manipulating environment variables such as NPM_CONFIG_REGISTRY to point to a malicious server, or by executing a man-in-the-middle attack on the network path. Because Deno applications frequently execute within high-privilege pipelines or developer environments, this lack of validation presents a substantial initial access and execution hijacking vector.
The weakness is classified under CWE-494 (Download of Code Without Integrity Check) and CWE-426 (Untrusted Search Path). It impacts all versions of esbuild starting from 0.17.0 up to, but excluding, version 0.28.1.
The root cause of this security flaw lies in the discrepancy between how the Node.js installer and the Deno installer wrapper verify binary payloads. The Node.js implementation enforces checksum integrity checks using a hardcoded JSON manifest containing SHA-256 hashes for each architecture. In contrast, the Deno installer implemented in lib/deno/mod.ts completely lacks any integrity checks or validation routines.
When a Deno application initializes esbuild, the module executes the installFromNPM helper function to check if the platform-specific native binary is available locally. If the binary is missing, the code queries the environment for the NPM_CONFIG_REGISTRY variable to determine the base download URL. If this variable is defined, the installer uses it to build the request path; otherwise, it defaults to the official npmjs registry.
Once the URL is constructed, the module issues an HTTP request using Deno's global fetch API. It reads the response body as an ArrayBuffer and immediately extracts the target executable using a custom tar-gzip extractor. No validation is conducted against the binary content or the archive structure before writing the executable to disk with read-write-execute permissions (0o755).
To understand the exact breakdown, we examine the vulnerable code path located in lib/deno/mod.ts within the affected version range. The implementation constructs the endpoint and fetches the binary archive using the following sequence:
// Affected Code: lib/deno/mod.ts
async function installFromNPM(name: string, subpath: string): Promise<string> {
const { finalPath, finalDir } = getCachePath(name);
try { await Deno.stat(finalPath); return finalPath } catch (e) {}
// The URL construction relies directly on the environment variable
const npmRegistry = Deno.env.get("NPM_CONFIG_REGISTRY") || "https://registry.npmjs.org";
const url = `${npmRegistry}/${name}/-/${name.replace("@esbuild/", "")}-${version}.tgz`;
// Unchecked remote download occurs here
const buffer = await fetch(url).then(r => r.arrayBuffer());
const executable = extractFileFromTarGzip(new Uint8Array(buffer), subpath);
// Writing the extracted binary with executable permissions
await Deno.mkdir(finalDir, { recursive: true, mode: 0o700 });
await Deno.writeFile(finalPath, executable, { mode: 0o755 });
return finalPath;
}In contrast, the Node.js implementation in lib/npm/node-install.ts enforces validation of the payload bytes using a built-in cryptographic hashing function. This ensures that even if a registry mirror is compromised or spoofed, the target environment refuses to write or execute anomalous binaries:
// Node.js Implementation: lib/npm/node-install.ts
function binaryIntegrityCheck(pkg: string, subpath: string, bytes: Uint8Array): void {
const hash = crypto.createHash('sha256').update(bytes).digest('hex');
const key = `${pkg}/${subpath}`;
const expected = packageJSON['esbuild.binaryHashes'][key];
if (!expected) throw new Error(`Missing hash for "${key}"`);
if (hash !== expected) throw new Error(`Hash mismatch for "${key}"`);
}The fix introduced in version 0.28.1 ports this cryptographic checksum verification to the Deno implementation. It resolves the vulnerability by mapping the downloaded bytes against the same static manifest hashes before the local filesystem write occurs. This ensures parity in security postures across both Node.js and Deno execution environments.
The exploitation of GHSA-GV7W-RQVM-QJHR relies on hijacking the source location of the downloaded package. In an enterprise or automated environment, an attacker can poison the NPM_CONFIG_REGISTRY environment variable to point to a malicious server. Alternatively, in a shared host or developer environment, the attacker can leverage local environment mutation permissions to force this redirection.
The attacker prepares a mock registry that returns a crafted gzip tarball containing a malicious script or binary disguised as the native executable. When installFromNPM is triggered, it requests the package from the malicious endpoint. The victim's application downloads and decompresses the payload, subsequently executing it with the active user permissions.
Below is a flow diagram illustrating the hijack sequence from environment poisoning to remote code execution:
This architecture guarantees that any environment in which Deno runs without strict permissions is susceptible to complete compromise. If Deno is launched with broad system permissions, the executed script can capture secrets, perform network reconnaissance, or establish persistence.
The security impact of this vulnerability is high, carrying a CVSS v3.1 score of 8.1. The attack vector is network-based, but exploitation requires specific conditions relating to environment manipulation or local access, which bounds the complexity. However, successful exploitation yields unauthenticated arbitrary code execution under the context of the running Deno process.
In automated environments such as continuous integration (CI) pipelines or automated deployment servers, Deno commands are often run with high privileges. A compromise in these contexts can lead to supply chain taint, exfiltration of sensitive environment variables, or unauthorized infrastructure control. Because the vulnerability involves the execution of native code, it evades standard Deno runtime limits if those flags are configured loosely.
As of current intelligence, this vulnerability is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog, nor is there active ransomware usage reported. However, due to the ease of constructing a proof-of-concept, development teams should prioritize remediation.
The primary and recommended mitigation is upgrading esbuild to version 0.28.1 or higher. This update introduces mandatory cryptographic verification using a static mapping of binary hashes. If upgrading is not immediately possible, security teams should implement restrictive runtime configurations to isolate the vulnerability.
Developers should avoid using the --allow-all or -A flags when executing untrusted or unverified Deno applications. Specifically, omitting or constraining the --allow-run permission blocks the Deno process from spawning the downloaded executable, neutralizing the remote code execution vector. Similarly, restricting the --allow-env permission prevents the application from reading a poisoned NPM_CONFIG_REGISTRY variable.
Additionally, implementing strict network egress controls ensures that Deno installers can only communicate with trusted, verified artifact repositories. Internal build environments should use read-only configurations for system-wide environment variables to prevent unauthorized modifications to registry pathways.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
esbuild (Deno module) evanw | >= 0.17.0, < 0.28.1 | 0.28.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-494, CWE-426 |
| Attack Vector | Network / Local Environment Manipulation |
| CVSS Score | 8.1 (High) |
| Exploit Status | Proof of Concept (PoC) available |
| CISA KEV Status | Not Listed |
| Impact | Remote Code Execution (RCE) |
The application downloads source code or executable binaries from a remote source but does not verify that the code's integrity matches an expected cryptographic hash.
An SSRF vulnerability exists in Flyto2 Core due to improper validation of intermediate HTTP redirect hops. While the initial request target is validated against an SSRF protection policy, the HTTP client library (aiohttp) transparently follows 30x redirects to local, internal, or cloud metadata endpoints without application-level revalidation.
A logic vulnerability exists in @dynatrace-oss/dynatrace-mcp-server prior to version 1.8.7. The create_dynatrace_notebook tool lacks a human-approval gate, allowing an attacker to exploit indirect prompt injection to force the underlying LLM client to create persistent Dynatrace notebooks without the operator's consent.
A critical authentication and authorization bypass vulnerability in the Quarkus Java framework exists due to a parser differential mismatch between the HTTP security policy layer and downstream handlers. By leveraging encoded reserved characters such as semicolons, slashes, and backslashes, attackers can bypass configured path-based security policies to gain unauthorized access to secure administrative endpoints and static resources.
A critical code injection vulnerability exists in @aws/agentcore CLI (AWS AgentCore CLI) during the Bedrock Agent import lifecycle. An authenticated remote attacker with permissions to configure Bedrock collaborator attributes can inject python code by embedding triple-double-quotes (""") inside the collaborationInstruction metadata field. The CLI formats this metadata directly into a Python docstring in a generated main.py file without adequate escaping, leading to arbitrary code execution when the imported agent is run or deployed.
GHSA-WCHH-9X6H-7F6P documents the critical deprecation of the cryptographic library libolm (Olm) and its Python binding wrapper python-olm, which matrix-commander depended upon via its downstream client library matrix-nio. Multiple cryptographic vulnerabilities (timing leaks, side-channels, signature malleability, and protocol confusion) were disclosed in 2022 and 2024. Because libolm is unmaintained, Python clients using matrix-commander are considered cryptographically unsafe until migrating to vodozemac.
An Excessive Data Exposure vulnerability in Easy!Appointments v1.5.2 allows low-privileged administrative users, such as restricted Providers and Secretaries, to harvest unique, stateless appointment hashes belonging to other providers. These hashes act as capability tokens, granting full authorization to reschedule, take over, or delete appointments via stateless endpoints, resulting in a complete Broken Object Level Authorization (BOLA) scenario.