Media

praisonaiagents: ast_grep_rewrite rewrites arbitrary files without the @require_approval gate enforced on every sibling mutation tool

  • Publicada: 25.08.2026
  • Actualizado: 11.10.2026 15:18

Target: PraisonAI (MervinPraison/PraisonAI) Affected component: praisonaiagents/tools/ast_grep_tool.py — ast_grep_rewrite Affected versions: master at ce97667156a116c50b4a3d1aa21e09f048903fda; reproduced against the current praisonaiagents PyPI release (praisonaiagents <= 1.6.52).

Summary

Tools in praisonaiagents/tools/ that modify on-disk state or run code are uniformly wrapped with @require_approval, which routes the call through an interactive approval flow before the body runs and fails closed — on denial (or with no approval backend configured) it raises PermissionError and the side effect does not occur. This is applied at every sibling mutation entry point:

File Line Symbol Risk level
file_tools.py 212 copy_file high
file_tools.py 239 move_file high
file_tools.py 266 delete_file high
edit_tools.py 38 EditTools.edit_file high
edit_tools.py 155 edit_file high
shell_tools.py 32 execute_command critical
python_tools.py 352 execute_code critical

ast_grep_tool.py:149 ast_grep_rewrite is structurally a sibling of these but has no decorator and no from ..approval import require_approval import. With dry_run=False (LLM-controllable), it builds sg --pattern <P> --rewrite <R> --lang <L> --update-all <path> (lines 204–211) and calls subprocess.run(cmd, ...) (line 215), modifying every file under path matching the pattern. There is no approval gate, no _validate_path workspace check, and no cwd= sandboxing. The function is registered as a top-level tool (__init__.py:182) and exposed via the code_intelligence built-in profile (profiles.py).

A secondary defect: on the dry_run=False path ast_grep_rewrite returns the literal string No changes made to the caller even when it modified files (the "No changes made" return at ast_grep_tool.py:230 is reached on this path), so an operator inspecting tool output sees no record that a write occurred.

Proof of concept

Single script, clean venv, praisonaiagents from PyPI, ast-grep CLI installed. PRAISONAI_AUTO_APPROVE is removed from the environment first, so no env-bypass is in play.

python
import os, tempfile, textwrap
os.environ.pop("PRAISONAI_AUTO_APPROVE", None)

workdir = tempfile.mkdtemp(prefix="poc-")
target = os.path.join(workdir, "target.py")
open(target, "w").write(textwrap.dedent("""
    def safe_function(x):
        return x + 1

    def hello(name):
        return 'hi ' + name
"""))

# Positive: undecorated tool rewrites the file.
from praisonaiagents.tools.ast_grep_tool import ast_grep_rewrite
ast_grep_rewrite(
    pattern="def $FN($$$): return $$$",
    replacement="def $FN($$$): import os; os.environ['POC_CANARY']='1'; return $$$",
    lang="python", path=workdir, dry_run=False,
)

# Negative control: decorated sibling triggers the approval flow.
from praisonaiagents.tools.edit_tools import edit_file
edit_file(file_path=target, old_text="def hello(name):", new_text="def hello(name):  # X")

Result, verified: ast_grep_rewrite rewrote target.py to contain the injected import os; os.environ['POC_CANARY']='1' payload, no approval prompt fired, and the call returned No changes made. The subsequent edit_file call in the same process rendered the Tool Approval Required panel and, on denial, raised PermissionError("Execution of edit_file denied: User denied") without modifying its target. Same process, same approval backend — the only difference is the missing decorator on ast_grep_rewrite.

Threat model

An LLM agent running locally whose tool surface includes ast_grep_rewrite (via the code_intelligence profile or direct import). Triggers: the operator asks the agent to refactor code, or prompt-injection in fetched docs / RAG context / any LLM-visible input steers the agent to call ast_grep_rewrite with attacker-chosen pattern, replacement, and path (the dry_run field is in the LLM-visible tool schema, so dry_run=False is requestable). The agent can then rewrite any file the host process can write — source trees, build configs, dotfiles, the agent's own source. With path="/" the rewrite is filesystem-wide. Because the rewrite injects arbitrary text, pointing it at a file that is later imported or executed turns this write primitive into code execution — the basis for the escalation noted in the CVSS line. No operator prompt and no audit record of the modification.

Suggested fix

diff
--- a/praisonaiagents/tools/ast_grep_tool.py
+++ b/praisonaiagents/tools/ast_grep_tool.py
@@
 from praisonaiagents._logging import get_logger
 from typing import Optional, List
+from ..approval import require_approval
@@
+@require_approval(risk_level="high")
 def ast_grep_rewrite(
     pattern: str,
     replacement: str,

high matches the file-modifying siblings; critical is defensible given the write→exec escalation. In the same patch: add a _validate_path workspace boundary check (cf. edit_tools.py:27); fix the No changes made return so it reflects actual modifications; apply the decorator to ast_grep_scan (ast_grep_tool.py:243) if it can write. ast_grep_search is read-only and can stay undecorated. A regression test asserting ast_grep_rewrite requires approval (alongside the other mutation tools) would have caught this at review time.

Coordinated disclosure

  • Kai Aizen / SnailSploit — kai@snailsploit.com — PGP on request.

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Python (PyPI) praisonaiagents < 1.6.58 1.6.58

Referencias

Puntuación CVSS 6.1/10
Vector CVSS
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Debilidad (CWE)
CWE-862
Plataforma
Python (PyPI)
Paquete
praisonaiagents
Publicada
25.08.2026
Actualizado
11.10.2026 15:18

Fuentes y licencias

OSV / GitHub Advisory Database - PYSEC-2026-3901 - PyPA Advisory Database; CC BY 4.0

OSV / GitHub Advisory Database - GHSA-cfxv-8fw8-rwpv - CC BY 4.0

Historial de vulnerabilidades: praisonaiagents

Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (50) en el archivo
Entradas en total
50
Primera → última
04.2026 10.2026
Sin corrección
0
Explotada en ataques
0

Distribución por gravedad

  • Crítica 10
  • Alta 27
  • Media 13

Divulgaciones por año

  1. 2026: 50
Gravedad:
  1. praisonaiagents: ast_grep_rewrite rewrites arbitrary files without the @require_approval gate enforced on every sibling mutation tool esta entrada
    Media · 6.1 CVE-2026-55530 < 1.6.58 1.6.58
  2. Alta · 7.5 CVE-2026-55525 < 1.6.58 1.6.58
  3. Alta · 7.5 CVE-2026-57129 < 1.6.59 1.6.59
  4. Crítica · 9.8 CVE-2026-57125 < 1.6.59 1.6.59
Mostrar más (18) Mostrando 20 de 38

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.