Every CVE Search/ Get API key

CVE-2026-55530

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

6.1 MediumFix available

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, ast_grep_rewrite lacks the @require_approval decorator used by sibling mutation tools. With dry_run=False, an agent-controlled call can pass --update-all and a broad path to rewrite matching files without the expected authorization gate. This issue is fixed in version 1.6.58.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
Required

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
Low

Exploit likelihood

0.17%Up 0.1 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.1

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

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, ast_grep_rewrite lacks the @require_approval decorator used by sibling mutation tools. With dry_run=False, an agent-controlled call can pass --update-all and a broad path to rewrite matching files without the expected authorization gate. This issue is fixed in version 1.6.58.

Record
CVE-2026-55530
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Weakness
CWE-862
Updated
2026-11-02
EUVDEUVD-2026-65501 6.1

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, ast_grep_rewrite lacks the @require_approval decorator used by sibling mutation tools. With dry_run=False, an agent-controlled call can pass --update-all and a broad path to rewrite matching files without the expected authorization gate. This issue is fixed in version 1.6.58.

Record
EUVD-2026-65501
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Updated
2026-11-02
GitHub AdvisoriesGHSA-cfxv-8fw8-rwpv 6.1

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

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.

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,…

Record
GHSA-cfxv-8fw8-rwpv
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Weakness
CWE-862
Updated
2026-11-02
NVD 6.1

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, ast_grep_rewrite lacks the @require_approval decorator used by sibling mutation tools. With dry_run=False, an agent-controlled call can pass --update-all and a broad path to rewrite matching files without the expected authorization gate. This issue is fixed in version 1.6.58.

Record
CVE-2026-55530
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Weakness
CWE-862
Updated
2026-11-02
OSV 6.1

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

PraisonAI is a multi-agent teams system. Prior to praisonaiagents 1.6.58, ast_grep_rewrite lacks the @require_approval decorator used by sibling mutation tools. With dry_run=False, an agent-controlled call can pass --update-all and a broad path to rewrite matching files without the expected authorization gate. This issue is fixed in version 1.6.58.

Record
CVE-2026-55530
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Weakness
CWE-862
Updated
2026-11-02
OSVGHSA-cfxv-8fw8-rwpv 6.1

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

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.

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,…

Record
GHSA-cfxv-8fw8-rwpv
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Weakness
CWE-862
Updated
2026-11-02
OSVPYSEC-2026-3901 6.1

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

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.

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,…

Record
PYSEC-2026-3901
CVSS 3.1
6.1 MediumCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
praisonaiagents
PyPI
before 1.6.58
1.6.58
praisonaiagents
PyPI
before 1.6.58, plus listed versions
0.0.10.0.100.0.1000.0.1010.0.102
Show 45 moreShow less
0.0.1030.0.1040.0.1050.0.1060.0.1070.0.1080.0.1090.0.110.0.1100.0.1110.0.1120.0.1130.0.1140.0.1150.0.1160.0.1170.0.1180.0.1190.0.120.0.1200.0.1210.0.1220.0.1230.0.1240.0.1250.0.1260.0.1270.0.1280.0.1290.0.130.0.1300.0.1310.0.1320.0.1330.0.1340.0.1350.0.1360.0.1370.0.1380.0.1390.0.140.0.1400.0.1410.0.1420.0.143
1.6.58

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-55530 is a medium vulnerability (CVSS 6.1) in Mervinpraison Praisonai, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.17%, the 5th percentile. Fixed in praisonaiagents 1.6.58.

References

This page doesn't list everything

Left out here: 535 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open