NewApp Monitoring is liveSign up free
AgentbeamBeta
AI agent vulnerability · Other MCP servers and tools

CVE-2026-75858: CodeWhale: rlm_eval auto-approves arbitrary Python execution, bypassing the user's approval policy (RCE)

highCVSS 4.0 8.5 · 3.1 7.8GHSA-wrj3-vj8c-784f

CodeWhale's `rlm_eval` tool runs model-chosen Python in a real `python3` interpreter and marks itself as never needing approval, so the user's `--approval-policy` is ignored. Prompt injection from content the agent reads can run code on the developer's machine with no prompt. Fixed in 0.8.64.

Published Sep 4, 2026 · Analysis Oct 24, 2026

What an attacker can do

rlm_eval in crates/tui/src/tools/rlm.rs takes a code string from the model and runs it. Its approval_requirement() returns ApprovalRequirement::Auto, which overrides the trait default that would require approval for tools with the ExecutesCode capability. The engine's check, spec.approval_requirement() != ApprovalRequirement::Auto && !registry.context().auto_approve, is then false, so no approval event is raised under on-request, unless-trusted or never. The companion tool rlm_open has the same Auto setting. It can stage content, a file or a URL fetch for the kernel. Both tools are registered by default and cannot be disabled.

An attacker needs the agent to read content they control: a web page, a fetched URL, a repo file or an MCP tool result. A prompt injection there can make the model call rlm_open and rlm_eval. The code runs with no sandbox at the user's UID. It can read SSH keys, cloud credentials and ~/.codewhale/auth.json, write to shell rc files or authorized_keys, and reach the network. The same defect was patched earlier on the run_tests tool (CVE-2026-45311). That fix did not reach these tools.

Who is affected

The package names changed along the way. The advisory lists:

  • codewhale (npm) and codewhale-tui (Rust): 0.8.41 up to but not including 0.8.64.
  • deepseek-tui (npm): 0.8.33 up to but not including 0.8.41.
  • deepseek-tui (Rust crate): 0.8.33 through 0.8.41, with no patched version listed.
npm ls -g codewhale deepseek-tui
codewhale --version

Every default install is affected, since the tools are registered unconditionally.

deepseek-tui

Ecosystem
Rust (crates.io)
Affected
>= 0.8.33, <= 0.8.41
Fixed in
No patched version yet
Check
cargo tree -i deepseek-tui

deepseek-tui

Ecosystem
npm
Affected
>= 0.8.33, < 0.8.41
Fixed in
0.8.41
Check
npm ls deepseek-tui

codewhale-tui

Ecosystem
Rust (crates.io)
Affected
>= 0.8.41, < 0.8.64
Fixed in
0.8.64
Check
cargo tree -i codewhale-tui

codewhale

Ecosystem
npm
Affected
>= 0.8.41, < 0.8.64
Fixed in
0.8.64
Check
npm ls codewhale

How to fix it

Upgrade to codewhale or codewhale-tui 0.8.64 or later. The fix is commit 57f3c89.

npm install -g codewhale@latest

For the old deepseek-tui npm package, the patched version listed is 0.8.41. The advisory lists no patched version for the deepseek-tui Rust crate, so move to codewhale-tui 0.8.64. The sources give no workaround. Avoid running the agent over untrusted content until you upgrade.

How to tell if you were hit

Look for a Python process started by the agent that you did not ask for, and for new files the agent should not write, such as /tmp/pwned_by_rlm_eval from the proof of concept. Check ~/.ssh/authorized_keys and shell rc files for recent edits, and the agent's session log for rlm_open or rlm_eval calls that happened without an approval dialog.

Beam records agent shell commands, file access and MCP tool calls, and its rules can flag risky ones, which helps with reviewing what the agent ran.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

Maintainer resolution

The CodeWhale maintainers validated this report. The affected package ranges are recorded in the advisory metadata. Version 0.8.64 contains the fix in commit 57f3c89471e27ac4032d9791f6885e5d4408c381. Users should upgrade to 0.8.64 or later. The original reporter analysis is preserved below.

Summary

The rlm_eval tool runs an arbitrary Python string chosen by the model in a real python3 interpreter. Its approval_requirement() returns ApprovalRequirement::Auto, which the engine treats as "never prompt," regardless of the user's configured --approval-policy. A single tool call — which prompt injection from any untrusted content the agent reads (a web page, a fetched URL, a repo file, an MCP tool result) can induce — runs code on the user's machine at the user's privilege with no prompt and no audit step. This is the same defect that was already patched on the sibling run_tests tool (CVE-2026-45311); the fix never reached rlm_eval or rlm_open, which expose a broader surface (full Python on the host, not just cargo test).

Details

rlm_eval's execute() reads the LLM-controlled code field and runs it (crates/tui/src/tools/rlm.rs:215-300):

fn capabilities(&self) -> Vec<ToolCapability> {
    vec![ToolCapability::Network, ToolCapability::ExecutesCode]
}

fn approval_requirement(&self) -> ApprovalRequirement {
    ApprovalRequirement::Auto          // overrides the safe default below
}

async fn execute(&self, input: Value, context: &ToolContext) -> Result<ToolResult, ToolError> {
    let name = required_non_empty_str(&input, "name")?;
    let code = required_non_empty_str(&input, "code")?;   // LLM-controlled
    ...
    let round = kernel.run(code, Some(&bridge)).await...   // runs that code in python3

The trait default at crates/tui/src/tools/spec.rs:632-633 would have returned Required for any tool whose capabilities include ExecutesCode. rlm_eval deliberately overrides that to Auto.

The engine's approval gate (crates/tui/src/core/engine.rs:845) is two AND-ed conditions, and a per-tool Auto makes the first one false:

let approval_required = spec.approval_requirement() != ApprovalRequirement::Auto
    && !registry.context().auto_approve;

When approval_requirement() is Auto, approval_required is false, no Event::ApprovalRequired is emitted, and the user's --approval-policy (on-request, unless-trusted, never) is never consulted. The companion tool rlm_open (rlm.rs:142-143, same Auto, capabilities include ExecutesCode + Network) spawns the same Python kernel via PythonRuntime::spawn_with_context (rlm.rs:181) and can stage a content string, a file_path read, or a url fetch into the kernel before rlm_eval runs against it. Both tools are registered unconditionally by the default registry (crates/tui/src/tools/registry.rs:802-803); there is no flag to disable them.

PoC

Source-level reproduction. Point a provider's base_url at a local mock that returns canned tool_calls, then have the agent call rlm_open followed by rlm_eval with a code payload such as:

import os, getpass, socket
open('/tmp/pwned_by_rlm_eval','w').write(getpass.getuser()+'@'+socket.gethostname()+':'+os.getcwd())

Run it through the non-interactive path (codewhale exec --auto) to confirm the tool executes, and through the plain interactive TUI under --approval-policy on-request (no --auto, no --yolo) to confirm no approval dialog appears. The sentinel file is written either way; the interactive run is the one that proves the policy is bypassed rather than waived.

Impact

Unsandboxed code execution on the user's workstation at the user's UID: read SSH keys, cloud credentials, ~/.codewhale/auth.json, and other secrets; write to shell rc files or authorized_keys for persistence; spawn subprocesses; reach the network. No filesystem, network, or process sandbox is applied to the spawned interpreter. Reachable with user interaction (running the agent over attacker-influenced content), no further prompt.

Credit

sai-sh

Credited to sai-sh.

Questions

Does my approval policy protect me?

Not before 0.8.64. rlm_eval returns Auto, so the engine never consults --approval-policy, including on-request and never.

How is this triggered?

The model has to call the tool. Prompt injection in a web page, a fetched URL, a repository file or an MCP tool result can induce the call. The CVSS vector marks user interaction as required, since the user runs the agent over that content.

Is this related to the `run_tests` bug?

Yes. The advisory says it is the same defect as CVE-2026-45311 on run_tests. That fix never reached rlm_eval or rlm_open.

Which version fixes CVE-2026-75858?

0.8.64 for codewhale and codewhale-tui. The old deepseek-tui npm package is listed as fixed in 0.8.41.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More Other MCP servers and tools vulnerabilities

All Other MCP servers and tools entries