Every CVE Search/ Get API key

CVE-2026-57133

PraisonAI utility shell safe-command wrapper allowlist bypass via shell chaining

8.8 HighFix available

PraisonAI is a multi-agent teams system. From 1.5.1 until 1.7.2, the shell() helper exported from src/praisonai-ts/src/tools/utility-tools.ts checks only the first whitespace-delimited token against safeCommands and then passes the complete original string to child_process.exec(). A string that starts with an allowed read-only command can append a second non-allowlisted command through shell syntax, allowing arbitrary command execution with the PraisonAI process privileges. This issue is fixed in version 1.7.2.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.80%Up 0.3 points since Sep 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.8

PraisonAI utility shell safe-command wrapper allowlist bypass via shell chaining

PraisonAI is a multi-agent teams system. From 1.5.1 until 1.7.2, the shell() helper exported from src/praisonai-ts/src/tools/utility-tools.ts checks only the first whitespace-delimited token against safeCommands and then passes the complete original string to child_process.exec(). A string that starts with an allowed read-only command can append a second non-allowlisted command through shell syntax, allowing arbitrary command execution with the PraisonAI process privileges. This issue is fixed in version 1.7.2.

Record
CVE-2026-57133
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-693, CWE-863
Updated
2026-11-02
EUVDEUVD-2026-78392 8.8

PraisonAI is a multi-agent teams system. From 1.5.1 until 1.7.2, the shell() helper exported from src/praisonai-ts/src/tools/utility-tools.ts checks only the first whitespace-delimited token against safeCommands and then passes the complete original string to child_process.exec(). A string that starts with an allowed read-only command can append a second non-allowlisted command through shell syntax, allowing arbitrary command execution with the PraisonAI process privileges. This issue is fixed in version 1.7.2.

Record
EUVD-2026-78392
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-5jv7-2mjm-h6qj 8.8

npm PraisonAI utility shell safe-command wrapper allowlist bypass via shell chaining

Summary

The published npm package praisonai ships dist/tools/utility-tools.js, which exports a shell(command) helper described in source as:

Execute shell command (safe version - read-only commands)

The helper attempts to enforce a safe read-only command allowlist by checking only the first whitespace-delimited token:

const safeCommands = ['ls', 'cat', 'head', 'tail', 'wc', 'grep', 'find', 'echo', 'date', 'pwd', 'which'];
const firstWord = command.split(/\s+/)[0];

if (!safeCommands.includes(firstWord)) {
    return { success: false, error: `Command not allowed: ${firstWord}` };
}

It then passes the entire original string to Node child_process.exec():

const { stdout, stderr } = await execAsync(command, { timeout: 5000 });

Because exec() runs the command through a shell, a command string that starts with an allowed command can append a second non-allowlisted command with shell metacharacters. For example, direct printf <marker> is rejected, but echo ok; printf <marker> is accepted and executes printf.

This bypasses the helper's safe-command policy and allows arbitrary shell commands to run with the PraisonAI process privileges when an application, agent, or integration exposes this helper to lower-trust users, prompts, model output, or plugin/tool input.

The PoV is deterministic and local-only. It installs only the npm package, runs harmless marker commands, and does not contact any live service after installation.

Technical Details

utility-tools.shell() authorizes one token but executes the full shell string.

Source-head implementation:

export async function shell(command: string): Promise<ToolResult<string>> {
    // Only allow safe read-only commands
    const safeCommands = ['ls', 'cat', 'head', 'tail', 'wc', 'grep', 'find', 'echo', 'date', 'pwd', 'which'];
    const firstWord = command.split(/\s+/)[0];

    if (!safeCommands.includes(firstWord)) {
        return { success: false, error: `Command not allowed: ${firstWord}` };
    }

    try {
        const { exec } = await import('child_process');
        const { promisify } = await import('util');
        const execAsync = promisify(exec);

        const { stdout, stderr } = await execAsync(command, { timeout: 5000 });
        return { success: true, data: stdout || stderr };
    } catch (error: any) {
        return { success: false, error: error.message ?? String(error) };
    }
}

The published npm:[email protected] dist file preserves the same behavior:

  • exports.shell = shell
  • const firstWord = command.split(/\s+/)[0]
  • if (!safeCommands.includes(firstWord)) ...
  • const { stdout, stderr } = await execAsync(command, { timeout: 5000 })

This creates a policy/parser differential: PraisonAI checks only the first token, while the shell parses the full string as a script.

Why This Is Not Intended Behavior

The helper is explicitly documented in code as a "safe version" for read-only commands and contains an allowlist of specific safe commands. The control test proves that non-allowlisted commands are intended to be blocked: direct printf <marker> returns Command not allowed: printf.

The same helper accepting echo ok; printf <marker> is therefore a bypass of the intended safe-command boundary, not merely a permissive command runner.

This is also consistent with Node's own guidance for shell execution: child_process.exec() runs through a shell, and shell metacharacters can change which commands execute. The fix should make PraisonAI's authorization boundary match what is actually executed.

PoV

Run from a local reproduction checkout:

node poc/pov_poc.js 1.7.1

Observed output summary from evidence/pov-npm-1.7.1.json:

{
  "package": "npm:praisonai",
  "version": "1.7.1",
  "installedPackageVersion": "1.7.1",
  "commands": {
    "directDisallowedCommand": "printf poc.7.1",
    "benignAllowedCommand": "echo poc",
    "chainedBypassCommand": "echo…
Record
GHSA-5jv7-2mjm-h6qj
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-693, CWE-863
Updated
2026-11-02
NVD 8.8

PraisonAI is a multi-agent teams system. From 1.5.1 until 1.7.2, the shell() helper exported from src/praisonai-ts/src/tools/utility-tools.ts checks only the first whitespace-delimited token against safeCommands and then passes the complete original string to child_process.exec(). A string that starts with an allowed read-only command can append a second non-allowlisted command through shell syntax, allowing arbitrary command execution with the PraisonAI process privileges. This issue is fixed in version 1.7.2.

Record
CVE-2026-57133
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-78, CWE-693, CWE-863
Updated
2026-11-02
OSV 8.8

PraisonAI utility shell safe-command wrapper allowlist bypass via shell chaining

PraisonAI is a multi-agent teams system. From 1.5.1 until 1.7.2, the shell() helper exported from src/praisonai-ts/src/tools/utility-tools.ts checks only the first whitespace-delimited token against safeCommands and then passes the complete original string to child_process.exec(). A string that starts with an allowed read-only command can append a second non-allowlisted command through shell syntax, allowing arbitrary command execution with the PraisonAI process privileges. This issue is fixed in version 1.7.2.

Record
CVE-2026-57133
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-693, CWE-78, CWE-863
Updated
2026-11-02
OSVGHSA-5jv7-2mjm-h6qj 8.8

npm PraisonAI utility shell safe-command wrapper allowlist bypass via shell chaining

Summary

The published npm package praisonai ships dist/tools/utility-tools.js, which exports a shell(command) helper described in source as:

Execute shell command (safe version - read-only commands)

The helper attempts to enforce a safe read-only command allowlist by checking only the first whitespace-delimited token:

const safeCommands = ['ls', 'cat', 'head', 'tail', 'wc', 'grep', 'find', 'echo', 'date', 'pwd', 'which'];
const firstWord = command.split(/\s+/)[0];

if (!safeCommands.includes(firstWord)) {
    return { success: false, error: `Command not allowed: ${firstWord}` };
}

It then passes the entire original string to Node child_process.exec():

const { stdout, stderr } = await execAsync(command, { timeout: 5000 });

Because exec() runs the command through a shell, a command string that starts with an allowed command can append a second non-allowlisted command with shell metacharacters. For example, direct printf <marker> is rejected, but echo ok; printf <marker> is accepted and executes printf.

This bypasses the helper's safe-command policy and allows arbitrary shell commands to run with the PraisonAI process privileges when an application, agent, or integration exposes this helper to lower-trust users, prompts, model output, or plugin/tool input.

The PoV is deterministic and local-only. It installs only the npm package, runs harmless marker commands, and does not contact any live service after installation.

Technical Details

utility-tools.shell() authorizes one token but executes the full shell string.

Source-head implementation:

export async function shell(command: string): Promise<ToolResult<string>> {
    // Only allow safe read-only commands
    const safeCommands = ['ls', 'cat', 'head', 'tail', 'wc', 'grep', 'find', 'echo', 'date', 'pwd', 'which'];
    const firstWord = command.split(/\s+/)[0];

    if (!safeCommands.includes(firstWord)) {
        return { success: false, error: `Command not allowed: ${firstWord}` };
    }

    try {
        const { exec } = await import('child_process');
        const { promisify } = await import('util');
        const execAsync = promisify(exec);

        const { stdout, stderr } = await execAsync(command, { timeout: 5000 });
        return { success: true, data: stdout || stderr };
    } catch (error: any) {
        return { success: false, error: error.message ?? String(error) };
    }
}

The published npm:[email protected] dist file preserves the same behavior:

  • exports.shell = shell
  • const firstWord = command.split(/\s+/)[0]
  • if (!safeCommands.includes(firstWord)) ...
  • const { stdout, stderr } = await execAsync(command, { timeout: 5000 })

This creates a policy/parser differential: PraisonAI checks only the first token, while the shell parses the full string as a script.

Why This Is Not Intended Behavior

The helper is explicitly documented in code as a "safe version" for read-only commands and contains an allowlist of specific safe commands. The control test proves that non-allowlisted commands are intended to be blocked: direct printf <marker> returns Command not allowed: printf.

The same helper accepting echo ok; printf <marker> is therefore a bypass of the intended safe-command boundary, not merely a permissive command runner.

This is also consistent with Node's own guidance for shell execution: child_process.exec() runs through a shell, and shell metacharacters can change which commands execute. The fix should make PraisonAI's authorization boundary match what is actually executed.

PoV

Run from a local reproduction checkout:

node poc/pov_poc.js 1.7.1

Observed output summary from evidence/pov-npm-1.7.1.json:

{
  "package": "npm:praisonai",
  "version": "1.7.1",
  "installedPackageVersion": "1.7.1",
  "commands": {
    "directDisallowedCommand": "printf poc.7.1",
    "benignAllowedCommand": "echo poc",
    "chainedBypassCommand": "echo…
Record
GHSA-5jv7-2mjm-h6qj
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-693, CWE-78, CWE-863
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
praisonai
npm
1.5.1 to 1.7.1
1.7.2
praisonai
npm
1.5.1 up to 1.7.2
1.7.2

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-57133 is a high vulnerability (CVSS 8.8) in Mervinpraison Praisonai, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.80%, the 56th percentile. Fixed in praisonai 1.7.2.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open