Мониторинг Справочная информация
Открытые данные
OSV.DEV

PYSEC-2026-2946

PraisonAI: Coarse-Grained Tool Approval Cache Bypasses Per-Invocation Consent for Shell Commands

Открыть источник ↗

Опубликована: 13.07.2026, 17:36 · Изменена: 03.11.2026, 11:15

## Summary The approval system in PraisonAI Agents caches tool approval decisions by tool name only, not by invocation arguments. Once a user approves `execute_command` for any command (e.g., `ls -la`), all subsequent `execute_command` calls in that execution context bypass the approval prompt entirely. Combined with `os.environ.copy()` passing all process environment variables to subprocesses, this allows an LLM agent (potentially via prompt injection) to silently exfiltrate API keys and credentials without further user consent. ## Details The `require_approval` decorator in `src/praisonai-agents/praisonaiagents/approval/__init__.py:176-178` checks approval status by tool name only: ```python @wraps(func) def wrapper(*args, **kwargs): if is_already_approved(tool_name): # line 177 — checks only tool_name return func(*args, **kwargs) # line 178 — bypasses ALL approval ``` The `mark_approved` function in `registry.py:144-147` stores only the tool name string: ```python def mark_approved(self, tool_name: str) -> None: approved = self._approved_context.get(set()) approved.add(tool_name) # stores "execute_command", not args self._approved_context.set(approved) ``` The approval context is never cleared during agent execution — `clear_approved()` exists (`registry.py:152`) but is never called in the agent's tool execution path (`agent/tool_execution.py`). Meanwhile, the `ConsoleBackend` UI at `backends.py:95-96` misleads the user: ```python return Confirm.ask( f"Do you want to execute this {request.risk_level} risk tool?", # "this" implies per-invocation approval ) ``` The UI displays the specific command arguments (lines 81-85), creating a reasonable expectation that the user is approving only that specific invocation. Additionally, `shell_tools.py:77` passes the full process environment to every subprocess: ```python process_env = os.environ.copy() # includes OPENAI_API_KEY, etc. ``` There is no command filtering, blocklist, or environment variable sanitization in the shell tools module. ## PoC ```python from praisonaiagents import Agent from praisonaiagents.tools.shell_tools import execute_command # Step 1: Create agent with shell tool agent = Agent( name="worker", instructions="You are a helpful assistant.", tools=[execute_command] ) # Step 2: Agent requests benign command — user sees Rich panel: # Function: execute_command # Risk Level: CRITICAL # Arguments: # command: ls -la # "Do you want to execute this critical risk tool?" [y/N] # User approves → mark_approved("execute_command") is called # Step 3: All subsequent execute_command calls bypass approval silently: # execute_command(command="env") # → returns ALL environment variables (OPENAI_API_KEY, AWS_SECRET_ACCESS_KEY, etc.) # → NO approval prompt shown # Step 4: Targeted extraction also bypasses approval: # execute_command(command="printenv OPENAI_API_KEY") # → returns the specific API key # → NO approval prompt shown # Verification: check the approval cache from praisonaiagents.approval import is_already_approved # After approving "ls -la": # is_already_approved("execute_command") → True # Any execute_command call now returns immediately at __init__.py:177-178 ``` ## Impact - **Secret exfiltration**: An LLM agent (or one subjected to prompt injection) can dump all process environment variables after a single benign command approval. Common secrets include `OPENAI_API_KEY`, `AWS_SECRET_ACCESS_KEY`, `DATABASE_URL`, and any other credentials passed via environment. - **Misleading consent UI**: The console prompt displays specific arguments and uses language ("this tool") that implies per-invocation consent, but the system grants session-wide blanket approval. - **No expiration or scope**: The approval cache uses a `ContextVar` that persists for the entire agent execution context with no timeout, no command-count limit, and no clearing between tool calls. - **No environment filtering**: `os.environ.copy()` passes every environment variable to subprocesses without filtering sensitive patterns. ## Recommended Fix 1. **Per-invocation approval for critical tools** — store a hash of `(tool_name, arguments)` instead of just `tool_name`, or require re-approval for each invocation of critical-risk tools: ```python # In registry.py — change mark_approved/is_already_approved: import hashlib, json def mark_approved(self, tool_name: str, arguments: dict = None) -> None: approved = self._approved_context.get(set()) risk = self._risk_levels.get(tool_name) if risk == "critical" and arguments: key = f"{tool_name}:{hashlib.sha256(json.dumps(arguments, sort_keys=True).encode()).hexdigest()}" else: key = tool_name approved.add(key) self._approved_context.set(approved) def is_already_approved(self, tool_name: str, arguments: dict = None) -> bool: approved = self._approved_context.get(set()) risk = self._risk_levels.get(tool_name) if risk == "critical" and arguments: key = f"{tool_name}:{hashlib.sha256(json.dumps(arguments, sort_keys=True).encode()).hexdigest()}" return key in approved return tool_name in approved ``` 2. **Filter environment variables** in `shell_tools.py`: ```python SENSITIVE_PATTERNS = ('_KEY', '_SECRET', '_TOKEN', '_PASSWORD', '_CREDENTIAL') process_env = { k: v for k, v in os.environ.items() if not any(p in k.upper() for p in SENSITIVE_PATTERNS) } if env: process_env.update(env) ```

Связанные идентификаторы

CVE-2026-56074

Альтернативные ID: CVE-2026-56074, GHSA-ffp3-3562-8cv3

Связанные записи: —

Исходные уязвимости: —

Оценки источника

CVSS_V3: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N

Связь с записью и оценка источника сами по себе не подтверждают, что уязвимость затрагивает установленный компонент. Результаты проверки вашего пакета доступны в «Моём стеке».

praisonaiagents

PyPI

pkg:pypi/praisonaiagents

Диапазоны и версии из источника
{
  "ranges": [
    {
      "type": "ECOSYSTEM",
      "events": [
        {
          "introduced": "0"
        },
        {
          "fixed": "4.5.128"
        }
      ]
    }
  ],
  "versions": [
    "0.0.1",
    "0.0.10",
    "0.0.100",
    "0.0.101",
    "0.0.102",
    "0.0.103",
    "0.0.104",
    "0.0.105",
    "0.0.106",
    "0.0.107",
    "0.0.108",
    "0.0.109",
    "0.0.11",
    "0.0.110",
    "0.0.111",
    "0.0.112",
    "0.0.113",
    "0.0.114",
    "0.0.115",
    "0.0.116",
    "0.0.117",
    "0.0.118",
    "0.0.119",
    "0.0.12",
    "0.0.120",
    "0.0.121",
    "0.0.122",
    "0.0.123",
    "0.0.124",
    "0.0.125",
    "0.0.126",
    "0.0.127",
    "0.0.128",
    "0.0.129",
    "0.0.13",
    "0.0.130",
    "0.0.131",
    "0.0.132",
    "0.0.133",
    "0.0.134",
    "0.0.135",
    "0.0.136",
    "0.0.137",
    "0.0.138",
    "0.0.139",
    "0.0.14",
    "0.0.140",
    "0.0.141",
    "0.0.142",
    "0.0.143",
    "0.0.144",
    "0.0.145",
    "0.0.146",
    "0.0.147",
    "0.0.148",
    "0.0.149",
    "0.0.15",
    "0.0.150",
    "0.0.151",
    "0.0.152",
    "0.0.153",
    "0.0.154",
    "0.0.155",
    "0.0.156",
    "0.0.157",
    "0.0.158",
    "0.0.159",
    "0.0.16",
    "0.0.160",
    "0.0.161",
    "0.0.162",
    "0.0.163",
    "0.0.164",
    "0.0.165",
    "0.0.166",
    "0.0.167",
    "0.0.168",
    "0.0.169",
    "0.0.17",
    "0.0.170",
    "0.0.171",
    "0.0.172",
    "0.0.173",
    "0.0.174",
    "0.0.175",
    "0.0.176",
    "0.0.177",
    "0.0.178",
    "0.0.179",
    "0.0.18",
    "0.0.180",
    "0.0.181",
    "0.0.182",
    "0.0.183",
    "0.0.184",
    "0.0.185",
    "0.0.187",
    "0.0.188",
    "0.0.189",
    "0.0.19",
    "0.0.190",
    "0.0.191",
    "0.0.192",
    "0.0.193",
    "0.0.194",
    "0.0.195",
    "0.0.196",
    "0.0.197",
    "0.0.198",
    "0.0.199",
    "0.0.2",
    "0.0.20",
    "0.0.21",
    "0.0.22",
    "0.0.23",
    "0.0.24",
    "0.0.25",
    "0.0.26",
    "0.0.27",
    "0.0.28",
    "0.0.29",
    "0.0.3",
    "0.0.30",
    "0.0.31",
    "0.0.32",
    "0.0.33",
    "0.0.34",
    "0.0.35",
    "0.0.36",
    "0.0.37",
    "0.0.38",
    "0.0.39",
    "0.0.4",
    "0.0.40",
    "0.0.41",
    "0.0.42",
    "0.0.43",
    "0.0.44",
    "0.0.45",
    "0.0.46",
    "0.0.47",
    "0.0.48",
    "0.0.49",
    "0.0.5",
    "0.0.50",
    "0.0.51",
    "0.0.52",
    "0.0.53",
    "0.0.54",
    "0.0.56",
    "0.0.57",
    "0.0.58",
    "0.0.59",
    "0.0.6",
    "0.0.60",
    "0.0.61",
    "0.0.62",
    "0.0.63",
    "0.0.64",
    "0.0.65",
    "0.0.66",
    "0.0.67",
    "0.0.68",
    "0.0.69",
    "0.0.7",
    "0.0.70",
    "0.0.71",
    "0.0.72",
    "0.0.73",
    "0.0.74",
    "0.0.75",
    "0.0.76",
    "0.0.77",
    "0.0.78",
    "0.0.79",
    "0.0.8",
    "0.0.80",
    "0.0.81",
    "0.0.82",
    "0.0.83",
    "0.0.84",
    "0.0.85",
    "0.0.86",
    "0.0.87",
    "0.0.88",
    "0.0.89",
    "0.0.9",
    "0.0.90",
    "0.0.91",
    "0.0.92",
    "0.0.93",
    "0.0.94",
    "0.0.95",
    "0.0.96",
    "0.0.97",
    "0.0.98",
    "0.0.99",
    "0.1.0",
    "0.1.1",
    "0.1.10",
    "0.1.11",
    "0.1.12",
    "0.1.13",
    "0.1.14",
    "0.1.15",
    "0.1.16",
    "0.1.17",
    "0.1.18",
    "0.1.19",
    "0.1.2",
    "0.1.20",
    "0.1.21",
    "0.1.22",
    "0.1.23",
    "0.1.24",
    "0.1.25",
    "0.1.26",
    "0.1.27",
    "0.1.3",
    "0.1.4",
    "0.1.5",
    "0.1.6",
    "0.1.7",
    "0.1.8",
    "0.1.9",
    "0.10.0",
    "0.10.1",
    "0.10.10",
    "0.10.2",
    "0.10.3",
    "0.10.4",
    "0.10.5",
    "0.10.6",
    "0.10.7",
    "0.10.8",
    "0.10.9",
    "0.11.0",
    "0.11.1",
    "0.11.10",
    "0.11.11",
    "0.11.12",
    "0.11.13",
    "0.11.14",
    "0.11.15",
    "0.11.16",
    "0.11.17",
    "0.11.18",
    "0.11.19",
    "0.11.2",
    "0.11.20",
    "0.11.21",
    "0.11.22",
    "0.11.23",
    "0.11.24",
    "0.11.25",
    "0.11.27",
    "0.11.28",
    "0.11.29",
    "0.11.3",
    "0.11.30",
    "0.11.31",
    "0.11.4",
    "0.11.5",
    "0.11.6",
    "0.11.7",
    "0.11.8",
    "0.11.9",
    "0.12.0",
    "0.12.1",
    "0.12.10",
    "0.12.11",
    "0.12.12",
    "0.12.13",
    "0.12.14",
    "0.12.15",
    "0.12.16",
    "0.12.17",
    "0.12.18",
    "0.12.19",
    "0.12.2",
    "0.12.20",
    "0.12.21",
    "0.12.3",
    "0.12.4",
    "0.12.5",
    "0.12.6",
    "0.12.7",
    "0.12.8",
    "0.12.9",
    "0.13.0",
    "0.13.1",
    "0.13.10",
    "0.13.11",
    "0.13.12",
    "0.13.13",
    "0.13.14",
    "0.13.15",
    "0.13.16",
    "0.13.17",
    "0.13.18",
    "0.13.19",
    "0.13.2",
    "0.13.20",
    "0.13.21",
    "0.13.22",
    "0.13.23",
    "0.13.3",
    "0.13.4",
    "0.13.5",
    "0.13.6",
    "0.13.7",
    "0.13.8",
    "0.13.9",
    "0.14.0",
    "0.14.1",
    "0.14.10",
    "0.14.11",
    "0.14.12",
    "0.14.14",
    "0.14.15",
    "0.14.16",
    "0.14.2",
    "0.14.3",
    "0.14.4",
    "0.14.5",
    "0.14.6",
    "0.14.7",
    "0.14.8",
    "0.14.9",
    "0.15.0",
    "0.15.1",
    "0.15.2",
    "0.15.3",
    "0.2.0",
    "0.2.1",
    "0.2.2",
    "0.3.0",
    "0.3.1",
    "0.3.2",
    "0.3.3",
    "0.3.4",
    "0.4.0",
    "0.4.1",
    "0.5.0",
    "0.5.1",
    "0.5.2",
    "0.5.3",
    "0.6.0",
    "0.6.1",
    "0.6.2",
    "0.6.3",
    "0.6.4",
    "0.6.5",
    "0.6.6",
    "0.6.7",
    "0.6.8",
    "0.7.0",
    "0.7.1",
    "0.8.0",
    "0.8.1",
    "0.9.0",
    "0.9.1",
    "1.0.0",
    "1.1.0",
    "1.2.0",
    "1.2.1",
    "1.2.2",
    "1.2.3",
    "1.2.4",
    "1.3.0",
    "1.3.1",
    "1.4.0",
    "1.4.1",
    "1.4.2",
    "1.4.3",
    "1.4.4",
    "1.4.5",
    "1.4.6",
    "1.4.7",
    "1.4.8",
    "1.5.0",
    "1.5.1",
    "1.5.10",
    "1.5.100",
    "1.5.101",
    "1.5.102",
    "1.5.103",
    "1.5.104",
    "1.5.105",
    "1.5.106",
    "1.5.107",
    "1.5.108",
    "1.5.109",
    "1.5.11",
    "1.5.110",
    "1.5.111",
    "1.5.112",
    "1.5.113",
    "1.5.114",
    "1.5.115",
    "1.5.116",
    "1.5.117",
    "1.5.118",
    "1.5.119",
    "1.5.12",
    "1.5.120",
    "1.5.121",
    "1.5.122",
    "1.5.123",
    "1.5.124",
    "1.5.125",
    "1.5.126",
    "1.5.127",
    "1.5.128",
    "1.5.129",
    "1.5.13",
    "1.5.130",
    "1.5.131",
    "1.5.132",
    "1.5.133",
    "1.5.134",
    "1.5.135",
    "1.5.136",
    "1.5.137",
    "1.5.138",
    "1.5.139",
    "1.5.14",
    "1.5.140",
    "1.5.141",
    "1.5.142",
    "1.5.143",
    "1.5.144",
    "1.5.145",
    "1.5.146",
    "1.5.147",
    "1.5.148",
    "1.5.149",
    "1.5.15",
    "1.5.16",
    "1.5.17",
    "1.5.18",
    "1.5.19",
    "1.5.2",
    "1.5.20",
    "1.5.21",
    "1.5.22",
    "1.5.23",
    "1.5.24",
    "1.5.25",
    "1.5.26",
    "1.5.27",
    "1.5.28",
    "1.5.29",
    "1.5.3",
    "1.5.30",
    "1.5.31",
    "1.5.32",
    "1.5.33",
    "1.5.34",
    "1.5.35",
    "1.5.36",
    "1.5.37",
    "1.5.38",
    "1.5.39",
    "1.5.40",
    "1.5.41",
    "1.5.42",
    "1.5.43",
    "1.5.44",
    "1.5.45",
    "1.5.46",
    "1.5.47",
    "1.5.48",
    "1.5.49",
    "1.5.5",
    "1.5.50",
    "1.5.51",
    "1.5.52",
    "1.5.53",
    "1.5.54",
    "1.5.55",
    "1.5.56",
    "1.5.57",
    "1.5.58",
    "1.5.59",
    "1.5.6",
    "1.5.60",
    "1.5.61",
    "1.5.62",
    "1.5.63",
    "1.5.64",
    "1.5.65",
    "1.5.66",
    "1.5.67",
    "1.5.68",
    "1.5.69",
    "1.5.7",
    "1.5.70",
    "1.5.71",
    "1.5.72",
    "1.5.73",
    "1.5.74",
    "1.5.75",
    "1.5.76",
    "1.5.77",
    "1.5.78",
    "1.5.79",
    "1.5.8",
    "1.5.80",
    "1.5.81",
    "1.5.82",
    "1.5.83",
    "1.5.84",
    "1.5.85",
    "1.5.86",
    "1.5.87",
    "1.5.88",
    "1.5.89",
    "1.5.9",
    "1.5.90",
    "1.5.91",
    "1.5.92",
    "1.5.93",
    "1.5.94",
    "1.5.95",
    "1.5.96",
    "1.5.97",
    "1.5.98",
    "1.5.99",
    "1.6.1",
    "1.6.10",
    "1.6.100",
    "1.6.101",
    "1.6.102",
    "1.6.103",
    "1.6.104",
    "1.6.105",
    "1.6.106",
    "1.6.107",
    "1.6.108",
    "1.6.109",
    "1.6.11",
    "1.6.110",
    "1.6.111",
    "1.6.112",
    "1.6.113",
    "1.6.114",
    "1.6.115",
    "1.6.116",
    "1.6.117",
    "1.6.118",
    "1.6.119",
    "1.6.12",
    "1.6.120",
    "1.6.123",
    "1.6.124",
    "1.6.125",
    "1.6.126",
    "1.6.127",
    "1.6.128",
    "1.6.129",
    "1.6.13",
    "1.6.130",
    "1.6.131",
    "1.6.132",
    "1.6.133",
    "1.6.134",
    "1.6.135",
    "1.6.136",
    "1.6.137",
    "1.6.138",
    "1.6.139",
    "1.6.14",
    "1.6.140",
    "1.6.141",
    "1.6.142",
    "1.6.143",
    "1.6.144",
    "1.6.145",
    "1.6.146",
    "1.6.147",
    "1.6.148",
    "1.6.149",
    "1.6.15",
    "1.6.150",
    "1.6.151",
    "1.6.152",
    "1.6.153",
    "1.6.154",
    "1.6.155",
    "1.6.156",
    "1.6.157",
    "1.6.158",
    "1.6.159",
    "1.6.16",
    "1.6.160",
    "1.6.161",
    "1.6.162",
    "1.6.163",
    "1.6.164",
    "1.6.165",
    "1.6.166",
    "1.6.167",
    "1.6.168",
    "1.6.17",
    "1.6.18",
    "1.6.19",
    "1.6.2",
    "1.6.20",
    "1.6.21",
    "1.6.22",
    "1.6.23",
    "1.6.24",
    "1.6.25",
    "1.6.26",
    "1.6.27",
    "1.6.28",
    "1.6.29",
    "1.6.3",
    "1.6.30",
    "1.6.31",
    "1.6.32",
    "1.6.33",
    "1.6.34",
    "1.6.35",
    "1.6.36",
    "1.6.37",
    "1.6.38",
    "1.6.39",
    "1.6.4",
    "1.6.40",
    "1.6.41",
    "1.6.42",
    "1.6.43",
    "1.6.44",
    "1.6.45",
    "1.6.46",
    "1.6.47",
    "1.6.48",
    "1.6.5",
    "1.6.50",
    "1.6.51",
    "1.6.52",
    "1.6.53",
    "1.6.54",
    "1.6.55",
    "1.6.56",
    "1.6.57",
    "1.6.58",
    "1.6.59",
    "1.6.6",
    "1.6.60",
    "1.6.62",
    "1.6.63",
    "1.6.64",
    "1.6.65",
    "1.6.66",
    "1.6.67",
    "1.6.68",
    "1.6.69",
    "1.6.7",
    "1.6.70",
    "1.6.71",
    "1.6.72",
    "1.6.73",
    "1.6.74",
    "1.6.75",
    "1.6.76",
    "1.6.77",
    "1.6.78",
    "1.6.79",
    "1.6.8",
    "1.6.80",
    "1.6.81",
    "1.6.82",
    "1.6.83",
    "1.6.84",
    "1.6.85",
    "1.6.86",
    "1.6.87",
    "1.6.88",
    "1.6.89",
    "1.6.9",
    "1.6.90",
    "1.6.91",
    "1.6.92",
    "1.6.93",
    "1.6.94",
    "1.6.95",
    "1.6.96",
    "1.6.97",
    "1.6.99",
    "1.7.0",
    "1.7.1",
    "1.7.10",
    "1.7.11",
    "1.7.12",
    "1.7.13",
    "1.7.14",
    "1.7.15",
    "1.7.16",
    "1.7.17",
    "1.7.18",
    "1.7.19",
    "1.7.2",
    "1.7.20",
    "1.7.21",
    "1.7.3",
    "1.7.4",
    "1.7.5",
    "1.7.6",
    "1.7.7",
    "1.7.8",
    "1.7.9"
  ]
}

Ссылки источника