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

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:
- Argument Injection discovered in blamer via CVE-2023-26143
- Argument injection discovered in git-promise via CVE-2022-24376
- Liran Tal’s book on Node.js Secure Coding: Defending Against Command Injection Vulnerabilities