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

GHSA-f2h6-7xfr-xm8w MEDIUM
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

Risk Assessment

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.

Attack Kill Chain

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

Affected Systems

Package Ecosystem Vulnerable Range Patched
PraisonAI pip < 4.5.128 4.5.128

Do you use PraisonAI? You're affected.

Severity & Risk

CVSS 3.1
6.5 / 10
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

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

Recommended Action

  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.

Classification

Compliance Impact

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?

No confirmed active exploitation of CVE-2026-40148 has been reported, but organizations should still patch proactively.

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).

Technical Details

NVD Description

## 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.

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