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

CVE-2026-16629: danger-js RCE Vulnerability

CVE-2026-16629 is a remote code execution flaw in danger-js that enables OS command injection through the danger.git.diffForFile function. This article covers the technical details, affected versions, and mitigation steps.

Published:

CVE-2026-16629 Overview

CVE-2026-16629 is an OS command injection vulnerability in the danger-js project, affecting versions up to and including 13.0.7. The flaw resides in the danger.git.diffForFile function implemented in source/platforms/git/localGetFileAtSHA.ts, part of the CLI component. A locally supplied file path is interpolated into a shell command, allowing an attacker who controls the File argument to inject arbitrary operating system commands. The maintainers addressed the issue in version 13.0.8 via commit 087a7290264cc6fb7154ea8c2552a7b2cb8b33a3. The vulnerability is tracked under [CWE-77] (Improper Neutralization of Special Elements used in a Command).

Critical Impact

Local attackers who can influence file path arguments passed to danger.git.diffForFile can execute arbitrary shell commands under the privileges of the process running the Danger CLI, typically within CI pipelines.

Affected Products

  • danger-js versions up to 13.0.7
  • Component: source/platforms/git/localGetFileAtSHA.ts (CLI)
  • Fixed in: danger-js 13.0.8

Discovery Timeline

  • 2026-07-22 - CVE-2026-16629 published to NVD
  • 2026-07-22 - Last updated in NVD database
  • Patch reference - Commit 087a7290264cc6fb7154ea8c2552a7b2cb8b33a3 merged via GitHub Pull Request #1513 and released as danger-js 13.0.8

Technical Details for CVE-2026-16629

Vulnerability Analysis

The localGetFileAtSHA function retrieves the contents of a file at a given Git SHA. In vulnerable versions, it builds the Git command as a single string using template literal interpolation and passes it to Node's child_process.exec. Because exec spawns a shell (/bin/sh -c ...), any shell metacharacters embedded in the file path are interpreted by the shell rather than treated as literal arguments. An attacker who controls a file path processed by Danger during a review or diff operation can break out of the quoted argument and append arbitrary commands. This is a local attack vector because the untrusted input must reach the Danger CLI process, typically through repository content or CI configuration files that Danger evaluates. Successful exploitation results in command execution with the same privileges as the Danger runner.

Root Cause

The root cause is unsafe command construction through string interpolation combined with a shell-invoking API. The original implementation built the command git show ${sha}:"${path}" and passed it to exec, which delegates parsing to a shell. Double quotes alone are insufficient to neutralize shell metacharacters such as backticks, $(...), and " itself, so a crafted path can terminate the quoted string and inject further commands.

Attack Vector

An attacker with the ability to influence file paths consumed by Danger such as filenames within a pull request or diff can supply a value containing shell metacharacters. When Danger invokes danger.git.diffForFile against that filename, the injected payload is executed by the shell. Attack complexity is low and no user interaction is required beyond triggering the Danger workflow.

typescript
 import { debug } from "../../debug"
-import { exec } from "child_process"
+import { execFile } from "child_process"
 
 const d = debug("localGetFileAtSHA")
 
 export const localGetFileAtSHA = (path: string, _repo: string | undefined, sha: string) =>
   new Promise<string>((done) => {
-    const call = `git show ${sha}:"${path}"`
-    d(call)
+    // Use execFile with an argv array (no shell) so that file paths containing
+    // shell metacharacters or quotes cannot break out and inject commands.
+    const args = ["show", `${sha}:${path}`]
+    d(`git ${args.join(" ")}`)
 
-    exec(call, (err, stdout, _stderr) => {
+    execFile("git", args, (err, stdout, _stderr) => {
       if (err) {
         console.error(`Could not get the file ${path} from git at ${sha}`)
         console.error(err)

Source: GitHub commit 087a7290. The patch replaces exec with execFile, passing arguments as an array so no shell is spawned and metacharacters in path cannot be interpreted.

Detection Methods for CVE-2026-16629

Indicators of Compromise

  • Unexpected child processes spawned from node or the danger CLI in CI runners, especially shells such as /bin/sh -c invoking non-Git binaries.
  • Git repository contents containing filenames with shell metacharacters (backticks, $(...), semicolons, pipes) surfaced through pull requests processed by Danger.
  • Outbound network connections from CI build agents shortly after danger ci or danger local execution.

Detection Strategies

  • Inventory dependencies to identify projects using danger-js at versions <= 13.0.7 via package.json and lockfiles.
  • Audit CI logs for invocations of git show where the argument after the SHA contains shell metacharacters.
  • Monitor process trees on CI runners for danger spawning shells that execute anything other than git.

Monitoring Recommendations

  • Enable command-line auditing on CI/CD build agents and forward events to a centralized log store for correlation.
  • Alert on new or anomalous outbound connections originating from build agents during Danger execution.
  • Track filename patterns in incoming pull requests and flag names containing shell metacharacters before Danger runs.

How to Mitigate CVE-2026-16629

Immediate Actions Required

  • Upgrade danger-js to version 13.0.8 or later across all repositories and CI pipelines.
  • Rebuild and republish any container images or CI base images that bundle danger-js.
  • Review CI logs for prior executions with suspicious file paths and rotate credentials exposed to affected build agents.

Patch Information

The fix is available in danger-js 13.0.8, delivered by commit 087a7290264cc6fb7154ea8c2552a7b2cb8b33a3 and tracked in Pull Request #1513. The patch replaces child_process.exec with child_process.execFile, which does not invoke a shell and passes arguments as a discrete argv array. Release details are documented in the danger-js 13.0.8 release notes.

Workarounds

  • If immediate upgrade is not possible, restrict Danger execution to trusted branches and disallow running Danger against untrusted forks or pull requests.
  • Pre-validate filenames in pull requests and reject entries containing shell metacharacters before Danger processes the diff.
  • Run Danger in an ephemeral, minimally privileged container with no persistent secrets and restricted network egress.
bash
# Upgrade danger-js to the patched release
npm install --save-dev danger@13.0.8

# Verify installed version
npx danger --version

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.