Apr 23, 2026·6 min read·4 visits
A command injection flaw in @evomap/evolver prior to version 1.66.5 allows remote code execution via unsafe use of execSync in the _extractLLM() utility.
The @evomap/evolver NPM package contains a critical command injection vulnerability in its _extractLLM utility function. Applications passing unsanitized input to this function are vulnerable to unauthenticated remote code execution, allowing attackers to execute arbitrary system commands with the privileges of the Node.js process.
The @evomap/evolver library is a Node.js package designed to facilitate AI agent evolution and data processing. A critical security flaw exists in how the library handles external inputs during natural language processing tasks. Specifically, the _extractLLM utility function improperly neutralizes special elements within the corpus parameter before passing it to a system shell.
This flaw is classified as Improper Neutralization of Special Elements used in a Command (CWE-78). The vulnerability arises because the library relies on the Node.js child_process.execSync method to invoke external utilities like curl for API interactions. By failing to validate or escape the corpus data, the application exposes a direct command injection vector.
The vulnerability carries an estimated CVSS score of 9.8, reflecting its critical severity. Exploitation requires no authentication, and the attack vector is network-based in scenarios where the library processes external AI responses or user-supplied agent configurations. Successful exploitation yields complete compromise of the underlying host environment.
The root cause of GHSA-J5W5-568X-RQ53 lies in the unsafe usage of the execSync function from the Node.js child_process module. When execSync is called with a single string argument, Node.js implicitly spawns a shell (typically /bin/sh on Unix-like systems or cmd.exe on Windows) to parse and execute the command. This shell interpretation is the exact mechanism that enables the vulnerability.
Within the _extractLLM(corpus) function, the corpus variable is dynamically interpolated directly into a command string. The developers intended this string to serve as the HTTP request body payload for a curl command. However, because the string interpolation happens prior to shell execution, any shell metacharacters present in the corpus variable alter the structure of the executed command.
When the resulting string is passed to execSync, the underlying shell parses the injected metacharacters. Characters such as semicolons (;), pipe symbols (|), and command substitutions (` or $()) instruct the shell to terminate the initial command and begin executing subsequent commands. The application lacks any sanitization or escaping mechanisms to prevent this behavior.
The vulnerable implementation constructs a shell command by embedding the corpus argument within double quotes. The code utilizes template literals to build the command string dynamically.
const { execSync } = require('child_process');
function _extractLLM(corpus) {
try {
// VULNERABLE: Direct string interpolation into a shell command
const command = `curl -X POST https://api.llm-provider.com/v1/extract -d "${corpus}"`;
const result = execSync(command);
return result.toString();
} catch (e) {
return null;
}
}The vulnerability occurs because an attacker can inject a double quote (") to close the intended string literal, followed by a semicolon (;) to terminate the curl command. Any subsequent text is treated as an independent shell command.
The remediation strategy eliminates the shell interpreter entirely. The fixed version (1.66.5) replaces execSync with alternatives like execFileSync or spawnSync. By passing the executable and its arguments as an array rather than a single string, the operating system executes the binary directly without invoking /bin/sh.
Exploiting this vulnerability requires the attacker to supply a crafted payload that traverses the application's data flow until it reaches the _extractLLM function. The payload must be designed to break out of the intended curl syntax and establish a new command context within the shell.
A functional proof-of-concept payload utilizes the string "; touch /tmp/pwned; #. When this string is passed as the corpus argument, the template literal evaluates to a completely different command structure than the developer intended.
The evaluated command becomes: curl -X POST https://api.llm-provider.com/v1/extract -d ""; touch /tmp/pwned; #". The shell interprets this as three distinct components. First, it executes the curl command with an empty data payload. Second, it executes the injected touch /tmp/pwned command. Finally, the octothorpe (#) comments out the remaining trailing quote, preventing syntax errors that might halt execution.
This technique allows arbitrary commands to run synchronously. In a realistic attack scenario, adversaries replace the touch command with instructions to download secondary payloads, establish reverse shells, or exfiltrate environment variables containing sensitive API keys.
The successful exploitation of GHSA-J5W5-568X-RQ53 results in unauthenticated Remote Code Execution (RCE). The attacker gains the ability to execute arbitrary operating system commands with the same privileges as the Node.js process running the @evomap/evolver package.
The impact is categorized as high across all three pillars of the CIA triad (Confidentiality, Integrity, and Availability). Attackers can read sensitive files, modify database records, or terminate the application process entirely. The CVSS 3.1 vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H accurately models this total system compromise.
Furthermore, because the library is utilized in AI agent processing workflows, compromised nodes can be leveraged to pivot laterally into internal networks. The execution environment often holds high-value secrets, such as API keys for LLM providers (e.g., OpenAI, Anthropic), which are subsequently exposed to theft.
The primary and most effective remediation is to update the @evomap/evolver dependency to version 1.66.5 or later. This release fundamentally addresses the vulnerability by removing the reliance on shell execution for external API calls. Package managers like npm or yarn should be used to enforce the updated version constraint across all application environments.
For systems where immediate patching is not feasible, developers must implement strict input validation on all data passed to the Evolver engine. This involves sanitizing the corpus input to reject any string containing shell metacharacters. However, input sanitization is prone to bypasses and should only serve as a temporary mitigation until the library is updated.
Security teams should also review application execution contexts. Implementing principle of least privilege by running the Node.js process under a restricted user account limits the blast radius of a successful exploit. Network-level egress filtering can further disrupt post-exploitation activities, such as reverse shell connections or secondary payload downloads.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@evomap/evolver EvoMap | < 1.66.5 | 1.66.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 |
| Attack Vector | Network |
| CVSS Score | 9.8 |
| Impact | Remote Code Execution |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The application constructs an OS command using externally-influenced input but does not properly neutralize special elements, allowing attackers to modify the intended command.