CVE-2026-57113
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
PraisonAI is a multi-agent teams system. From version 2.6.0 to before version 4.6.59, PraisonAI's template loader accepts GitHub template URIs with refs, for example github:owner/repo/[email protected]. The resolver stores the user-controlled template path and ref verbatim, and the cache layer later joins those values into ~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without normalizing each segment or checking that the final path remains inside the template cache root. A crafted ref such as ../../../../../../outside-delete-target therefore escapes the cache directory. The first load can write .cache_meta.json outside the cache. If the normal cache hierarchy for the same owner/repo/template has already been created, the same path reaches shutil.rmtree(cache_path) and removes an attacker-selected outside directory before replacing it with cache metadata. This issue has been patched in version 4.6.59.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.1
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
PraisonAI is a multi-agent teams system. From version 2.6.0 to before version 4.6.59, PraisonAI's template loader accepts GitHub template URIs with refs, for example github:owner/repo/[email protected]. The resolver stores the user-controlled template path and ref verbatim, and the cache layer later joins those values into ~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without normalizing each segment or checking that the final path remains inside the template cache root. A crafted ref such as ../../../../../../outside-delete-target therefore escapes the cache directory. The first load can write .cache_meta.json outside the cache. If the normal cache hierarchy for the same owner/repo/template has already been created, the same path reaches shutil.rmtree(cache_path) and removes an attacker-selected outside directory before replacing it with cache metadata. This issue has been patched in version 4.6.59.
- Record
CVE-2026-57113- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Weakness
- CWE-22, CWE-73
- Updated
- 2026-11-02
EUVDEUVD-2026-108889
8.1
PraisonAI is a multi-agent teams system. From version 2.6.0 to before version 4.6.59, PraisonAI's template loader accepts GitHub template URIs with refs, for example github:owner/repo/[email protected]. The resolver stores the user-controlled template path and ref verbatim, and the cache layer later joins those values into ~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without normalizing each segment or checking that the final path remains inside the template cache root. A crafted ref such as ../../../../../../outside-delete-target therefore escapes the cache directory. The first load can write .cache_meta.json outside the cache. If the normal cache hierarchy for the same owner/repo/template has already been created, the same path reaches shutil.rmtree(cache_path) and removes an attacker-selected outside directory before replacing it with cache metadata. This issue has been patched in version 4.6.59.
- Record
EUVD-2026-108889- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-f44v-7qgw-9gh9
8.1
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
Summary
PraisonAI's template loader accepts GitHub template URIs with refs, for example
github:owner/repo/[email protected]. The resolver stores the user-controlled
template path and ref verbatim, and the cache layer later joins those values into
~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without
normalizing each segment or checking that the final path remains inside the
template cache root.
A crafted ref such as ../../../../../../outside-delete-target therefore
escapes the cache directory. The first load can write .cache_meta.json outside
the cache. If the normal cache hierarchy for the same owner/repo/template has
already been created, the same path reaches shutil.rmtree(cache_path) and
removes an attacker-selected outside directory before replacing it with cache
metadata.
This is distinct from the old template Zip Slip advisory. No malicious archive member is needed, and the PoV disables network access entirely. The bug is in cache-key construction for GitHub template URIs.
Affected versions
Confirmed vulnerable:
v2.6.0v3.9.24v3.9.26v4.5.126v4.5.128v4.6.9v4.6.10v4.6.56v4.6.57- current head
2f9677abb2ea68eab864ee8b6a828fd0141612e1
Recommended affected range: >= 2.6.0, <= 4.6.57.
No fixed version is known at the time of this report.
Impact
An attacker who can cause a user or service to load an attacker-supplied PraisonAI GitHub template URI can:
- create
.cache_meta.jsonoutside the template cache directory; - delete a directory reachable by the PraisonAI process after a normal cache entry exists for the same owner/repo/template prefix;
- corrupt user configuration, project state, or application data reachable by the process permissions.
Root cause
Current-head code path:
praisonai/templates/resolver.py:GITHUB_PATTERNcapturespathandrefwith broad regex groups and returns them without segment validation.praisonai/templates/security.py:is_source_allowed()allows GitHub sources by default whenallow_any_githubis true.praisonai/templates/registry.py:get_template()resolves a GitHub URI, fetches the template, calculates a checksum, then callsself.cache.put(...).praisonai/templates/cache.py:_get_cache_path()builds the cache path asself.cache_dir / "github" / resolved.owner / resolved.repo / resolved.path / ref.praisonai/templates/cache.py:put()removes an existingcache_pathwithshutil.rmtree(cache_path), recreates it, copies content, and writes.cache_meta.json.
There is no check equivalent to:
- reject absolute path segments;
- reject
./..in owner, repo, template path, or ref; - resolve the candidate path;
- require
os.path.commonpath([cache_root, candidate]) == cache_root.
Local-only PoV
Run from a PraisonAI source checkout:
from pathlib import Path
from tempfile import TemporaryDirectory
from praisonai.templates.cache import TemplateCache
from praisonai.templates.loader import TemplateLoader
from praisonai.templates.registry import TemplateRegistry
def loader(cache_dir):
cache = TemplateCache(cache_dir=cache_dir)
registry = TemplateRegistry(cache=cache, offline=False)
registry._make_request = lambda url, headers=None: (_ for _ in ()).throw(
RuntimeError("network disabled")
)
return TemplateLoader(cache=cache, registry=registry)
with TemporaryDirectory(prefix="prai-cache-ref-pov-") as tmp:
root = Path(tmp)
cache_dir = root / "cache" / "templates"
write_target = root / "outside-write-target"
loader(cache_dir).load(
"github:attacker/repo/template@../../../../../../outside-write-target"
)
delete_target = root / "outside-delete-target"
delete_target.mkdir()
canary = delete_target / "canary.txt"
canary.write_text("delete-me")
ldr = loader(cache_dir)
ldr.load("github:attacker/repo/template@main")
ldr.load(
…
- Record
GHSA-f44v-7qgw-9gh9- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Weakness
- CWE-22, CWE-73
- Updated
- 2026-11-02
NVD
8.1
PraisonAI is a multi-agent teams system. From version 2.6.0 to before version 4.6.59, PraisonAI's template loader accepts GitHub template URIs with refs, for example github:owner/repo/[email protected]. The resolver stores the user-controlled template path and ref verbatim, and the cache layer later joins those values into ~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without normalizing each segment or checking that the final path remains inside the template cache root. A crafted ref such as ../../../../../../outside-delete-target therefore escapes the cache directory. The first load can write .cache_meta.json outside the cache. If the normal cache hierarchy for the same owner/repo/template has already been created, the same path reaches shutil.rmtree(cache_path) and removes an attacker-selected outside directory before replacing it with cache metadata. This issue has been patched in version 4.6.59.
- Record
CVE-2026-57113- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Weakness
- CWE-22, CWE-73
- Updated
- 2026-11-02
OSV
8.1
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
PraisonAI is a multi-agent teams system. From version 2.6.0 to before version 4.6.59, PraisonAI's template loader accepts GitHub template URIs with refs, for example github:owner/repo/[email protected]. The resolver stores the user-controlled template path and ref verbatim, and the cache layer later joins those values into ~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without normalizing each segment or checking that the final path remains inside the template cache root. A crafted ref such as ../../../../../../outside-delete-target therefore escapes the cache directory. The first load can write .cache_meta.json outside the cache. If the normal cache hierarchy for the same owner/repo/template has already been created, the same path reaches shutil.rmtree(cache_path) and removes an attacker-selected outside directory before replacing it with cache metadata. This issue has been patched in version 4.6.59.
- Record
CVE-2026-57113- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Weakness
- CWE-22, CWE-73
- Updated
- 2026-11-02
OSVGHSA-f44v-7qgw-9gh9
8.1
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
Summary
PraisonAI's template loader accepts GitHub template URIs with refs, for example
github:owner/repo/[email protected]. The resolver stores the user-controlled
template path and ref verbatim, and the cache layer later joins those values into
~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without
normalizing each segment or checking that the final path remains inside the
template cache root.
A crafted ref such as ../../../../../../outside-delete-target therefore
escapes the cache directory. The first load can write .cache_meta.json outside
the cache. If the normal cache hierarchy for the same owner/repo/template has
already been created, the same path reaches shutil.rmtree(cache_path) and
removes an attacker-selected outside directory before replacing it with cache
metadata.
This is distinct from the old template Zip Slip advisory. No malicious archive member is needed, and the PoV disables network access entirely. The bug is in cache-key construction for GitHub template URIs.
Affected versions
Confirmed vulnerable:
v2.6.0v3.9.24v3.9.26v4.5.126v4.5.128v4.6.9v4.6.10v4.6.56v4.6.57- current head
2f9677abb2ea68eab864ee8b6a828fd0141612e1
Recommended affected range: >= 2.6.0, <= 4.6.57.
No fixed version is known at the time of this report.
Impact
An attacker who can cause a user or service to load an attacker-supplied PraisonAI GitHub template URI can:
- create
.cache_meta.jsonoutside the template cache directory; - delete a directory reachable by the PraisonAI process after a normal cache entry exists for the same owner/repo/template prefix;
- corrupt user configuration, project state, or application data reachable by the process permissions.
Root cause
Current-head code path:
praisonai/templates/resolver.py:GITHUB_PATTERNcapturespathandrefwith broad regex groups and returns them without segment validation.praisonai/templates/security.py:is_source_allowed()allows GitHub sources by default whenallow_any_githubis true.praisonai/templates/registry.py:get_template()resolves a GitHub URI, fetches the template, calculates a checksum, then callsself.cache.put(...).praisonai/templates/cache.py:_get_cache_path()builds the cache path asself.cache_dir / "github" / resolved.owner / resolved.repo / resolved.path / ref.praisonai/templates/cache.py:put()removes an existingcache_pathwithshutil.rmtree(cache_path), recreates it, copies content, and writes.cache_meta.json.
There is no check equivalent to:
- reject absolute path segments;
- reject
./..in owner, repo, template path, or ref; - resolve the candidate path;
- require
os.path.commonpath([cache_root, candidate]) == cache_root.
Local-only PoV
Run from a PraisonAI source checkout:
from pathlib import Path
from tempfile import TemporaryDirectory
from praisonai.templates.cache import TemplateCache
from praisonai.templates.loader import TemplateLoader
from praisonai.templates.registry import TemplateRegistry
def loader(cache_dir):
cache = TemplateCache(cache_dir=cache_dir)
registry = TemplateRegistry(cache=cache, offline=False)
registry._make_request = lambda url, headers=None: (_ for _ in ()).throw(
RuntimeError("network disabled")
)
return TemplateLoader(cache=cache, registry=registry)
with TemporaryDirectory(prefix="prai-cache-ref-pov-") as tmp:
root = Path(tmp)
cache_dir = root / "cache" / "templates"
write_target = root / "outside-write-target"
loader(cache_dir).load(
"github:attacker/repo/template@../../../../../../outside-write-target"
)
delete_target = root / "outside-delete-target"
delete_target.mkdir()
canary = delete_target / "canary.txt"
canary.write_text("delete-me")
ldr = loader(cache_dir)
ldr.load("github:attacker/repo/template@main")
ldr.load(
…
- Record
GHSA-f44v-7qgw-9gh9- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Weakness
- CWE-22, CWE-73
- Updated
- 2026-11-02
OSVPYSEC-2026-3509
8.1
PraisonAI GitHub template cache path traversal allows outside-cache file write and directory deletion
Summary
PraisonAI's template loader accepts GitHub template URIs with refs, for example
github:owner/repo/[email protected]. The resolver stores the user-controlled
template path and ref verbatim, and the cache layer later joins those values into
~/.praison/cache/templates/github/<owner>/<repo>/<template>/<ref> without
normalizing each segment or checking that the final path remains inside the
template cache root.
A crafted ref such as ../../../../../../outside-delete-target therefore
escapes the cache directory. The first load can write .cache_meta.json outside
the cache. If the normal cache hierarchy for the same owner/repo/template has
already been created, the same path reaches shutil.rmtree(cache_path) and
removes an attacker-selected outside directory before replacing it with cache
metadata.
This is distinct from the old template Zip Slip advisory. No malicious archive member is needed, and the PoV disables network access entirely. The bug is in cache-key construction for GitHub template URIs.
Affected versions
Confirmed vulnerable:
v2.6.0v3.9.24v3.9.26v4.5.126v4.5.128v4.6.9v4.6.10v4.6.56v4.6.57- current head
2f9677abb2ea68eab864ee8b6a828fd0141612e1
Recommended affected range: >= 2.6.0, <= 4.6.57.
No fixed version is known at the time of this report.
Impact
An attacker who can cause a user or service to load an attacker-supplied PraisonAI GitHub template URI can:
- create
.cache_meta.jsonoutside the template cache directory; - delete a directory reachable by the PraisonAI process after a normal cache entry exists for the same owner/repo/template prefix;
- corrupt user configuration, project state, or application data reachable by the process permissions.
Root cause
Current-head code path:
praisonai/templates/resolver.py:GITHUB_PATTERNcapturespathandrefwith broad regex groups and returns them without segment validation.praisonai/templates/security.py:is_source_allowed()allows GitHub sources by default whenallow_any_githubis true.praisonai/templates/registry.py:get_template()resolves a GitHub URI, fetches the template, calculates a checksum, then callsself.cache.put(...).praisonai/templates/cache.py:_get_cache_path()builds the cache path asself.cache_dir / "github" / resolved.owner / resolved.repo / resolved.path / ref.praisonai/templates/cache.py:put()removes an existingcache_pathwithshutil.rmtree(cache_path), recreates it, copies content, and writes.cache_meta.json.
There is no check equivalent to:
- reject absolute path segments;
- reject
./..in owner, repo, template path, or ref; - resolve the candidate path;
- require
os.path.commonpath([cache_root, candidate]) == cache_root.
Local-only PoV
Run from a PraisonAI source checkout:
from pathlib import Path
from tempfile import TemporaryDirectory
from praisonai.templates.cache import TemplateCache
from praisonai.templates.loader import TemplateLoader
from praisonai.templates.registry import TemplateRegistry
def loader(cache_dir):
cache = TemplateCache(cache_dir=cache_dir)
registry = TemplateRegistry(cache=cache, offline=False)
registry._make_request = lambda url, headers=None: (_ for _ in ()).throw(
RuntimeError("network disabled")
)
return TemplateLoader(cache=cache, registry=registry)
with TemporaryDirectory(prefix="prai-cache-ref-pov-") as tmp:
root = Path(tmp)
cache_dir = root / "cache" / "templates"
write_target = root / "outside-write-target"
loader(cache_dir).load(
"github:attacker/repo/template@../../../../../../outside-write-target"
)
delete_target = root / "outside-delete-target"
delete_target.mkdir()
canary = delete_target / "canary.txt"
canary.write_text("delete-me")
ldr = loader(cache_dir)
ldr.load("github:attacker/repo/template@main")
ldr.load(
…
- Record
PYSEC-2026-3509- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
praisonaiPyPI |
2.6.0 to 4.6.57 | 4.6.59 |
praisonaiPyPI |
2.6.0 up to 4.6.59, plus listed versions 2.6.12.6.22.6.32.6.42.6.5 Show 45 moreShow less2.6.62.6.72.6.82.7.02.8.32.8.42.8.52.8.62.8.72.8.82.8.92.9.02.9.12.9.23.0.03.0.13.0.23.0.33.0.43.0.53.0.63.0.73.0.83.0.93.1.03.1.13.1.23.1.33.1.43.1.53.1.63.1.73.1.83.1.93.10.03.10.13.10.103.10.113.10.123.10.133.10.143.10.153.10.163.10.173.10.18 |
4.6.59 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-57113 is a high vulnerability (CVSS 8.1) in Mervinpraison Praisonai, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.40%, the 34th percentile. Fixed in praisonai 4.6.59.
References
Left out here: 319 versions and the rest of 3 source descriptions. The JSON record has them.