Liran Tal
Liran Tal
  • Jun 22, 2025

A Command Injection Vulnerability Class Discovered in Bun JavaScript Runtime

A command injection vulnerability class was discovered in the Bun JavaScript runtime, which could lead to unintended command execution based on user input.

A Command Injection Vulnerability Class Discovered in Bun JavaScript Runtime

This is the third security vulnerability that I am disclosing about the Bun JavaScript runtime and its package manager, Bun.

Context: a previous security vulnerability I discovered in the Bun runtime was CVE-2024-21548 and it was accepted by the Bun team and published on their release notes. However, follow-up reports of a security issue did not receive any acknowledgment from the Bun team, despite multiple attempts to contact them through their GitHub security vulnerability disclosure program and other channels. Hence, I stopped trying.

About Command Injection in Bun JavaScript runtime

The Bun runtime exposes a $ function to perform shell commands in a programmatic way. However, a particular injection attack subclass of command injection, known as argument injection, can be employed by attackers to circumvent the output encoding logic of $ which attempts to protect from command injection.

Example usage of $

In the following Bun code, the program uses the git binary to run a command based on user input of a repository URL. If the userRepository is user controlled and would include shell metacharacters such as ; and others to change the logic of the original command (denoted by the git program), then it would fail.

For example, Bun will safely execute the following without the malicious behavior desginated by user input:

import { $ } from "bun";
const userRepository = 'https://github.com/oven-sh/bun; touch /tmp/pwned.txt';
const refs = await $`git ls-remote ${userRepository} main`.text();

Vulnerability Proof of Concept

In another case, where the user input provided as a variable to the tagged template is using a command-line notation, then attackers may rely on it to change the behavior of the originally intended command.

Consider the following proof-of-concept:

import { $ } from "bun";
const userRepository = `--upload-pack=env>hello;`;
const refs = await $`git ls-remote ${userRepository} main`.text();

In the above, the user input changes from being a URL to a command-line argument that is supposed by the git command and would result in the id>hello command successfully executing, creating an file named hello with the contents of the Unix id command.

Impact

By missing to disregard the -- from user-input it becomes a valid command line argument and may alter the behavior of commands.

Analysis

Should Bun implement further security controls to prevent user input interpreted as command line arguments? could it do it without resulting in side effects and unwanted behavior? should this be a user concern instead of a Bun by-design security protection?

I leave this up to the maintainers to decide and invite them to collaborate on best approach and secure-by-design decisions for the project.

Environment

This was tested with Bun 1.1.38

Affected products

bun <=1.1.39

CWE

CWE-78: Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)

References and Prior work

Existing work on command injection vulnerabilities and argument injection vulnerabilities:

Bun Security Vulnerability Cve