CVE-2026-4308
agent-zero 0.9.7 is vulnerable to remote SSRF in its PDF document handler.
- CVSS 2.1
- CWE-918
- Input Validation and Sanitization
- Remote
A weakness has been identified in frdel/agent0ai agent-zero 0.9.7. This affects the function handle_pdf_document of the file python/helpers/document_query.py. This manipulation causes server-side request forgery. The attack is possible to be carried out remotely. The exploit has been made available to the public and could be used for attacks. The vendor was contacted early about this disclosure but did not respond in any way.
- CWE
- CWE-918
- CVSS base score
- 2.1
- Published
- 2026-03-17
- OWASP
- A10 Server-Side Request Forgery (SSRF)
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Server-Side Request Forgery (SSRF)
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- frdel/agent0
- Fixed by upgrading
- Yes
Solution
Upgrade to version 0.9.8 or later.
Vulnerable code sample
import requests
from io import BytesIO
# This code is a representative example of the vulnerability described
# in the hypothetical CVE-2026-4308, as the actual source code is not available.
# The vulnerability lies in the direct, unvalidated use of a user-provided URL.
def handle_pdf_document(pdf_url: str):
"""
Fetches a PDF document from a given URL and processes it.
This function is vulnerable to Server-Side Request Forgery (SSRF) because
it makes a GET request to any URL supplied by the user in the `pdf_url`
parameter without any validation or sanitization. An attacker can use this
to make the server send requests to internal-only services, cloud metadata
endpoints, or other arbitrary locations on the internet.
Args:
pdf_url: The URL of the PDF document to fetch.
"""
try:
# VULNERABLE LINE: The user-controlled 'pdf_url' is used directly.
# An attacker can point this to an internal service like 'http://127.0.0.1/admin'
# or a cloud metadata service like 'http://169.254.169.254/latest/meta-data/'.
response = requests.get(pdf_url, timeout=10)
response.raise_for_status() # Will raise an HTTPError for bad responses (4xx or 5xx)
print(f"Successfully fetched document from {pdf_url} with status {response.status_code}")
# Simulate processing the PDF
# In a real application, this might involve libraries like PyPDF2 or pdfplumber
pdf_content = BytesIO(response.content)
print(f"Processing {len(pdf_content.read())} bytes of PDF data.")
return {"status": "success", "url": pdf_url}
except requests.exceptions.RequestException as e:
print(f"Failed to fetch document from {pdf_url}: {e}")
return {"status": "error", "message": str(e)}Patched code sample
import requests
import socket
import urllib.parse
from ipaddress import ip_address, AddressValueError
def handle_pdf_document(pdf_url: str):
"""
Downloads a PDF from a URL and processes it.
This version includes a fix for a potential SSRF vulnerability.
"""
try:
# --- SSRF Fix Start ---
# 1. Parse the URL to isolate the hostname and validate the scheme.
parsed_url = urllib.parse.urlparse(pdf_url)
if parsed_url.scheme not in ['http', 'https']:
raise ValueError("Invalid URL scheme. Only 'http' and 'https' are allowed.")
hostname = parsed_url.hostname
if not hostname:
raise ValueError("URL is missing a valid hostname.")
# 2. Resolve the hostname to an IP address. This helps prevent DNS rebinding
# attacks where a domain might resolve to a public IP first, then a private one.
try:
ip_addr = socket.gethostbyname(hostname)
except socket.gaierror:
raise ValueError(f"Could not resolve hostname: {hostname}")
# 3. Check if the resolved IP address is a private, reserved, or loopback address.
# This is the core of the SSRF protection.
ip_obj = ip_address(ip_addr)
# The 'is_global' property is a convenient way to check that the address is not
# private, reserved, loopback, or otherwise unspecified.
if not ip_obj.is_global:
raise ValueError(f"Request to non-global IP address '{ip_addr}' is forbidden.")
# --- SSRF Fix End ---
# If all security checks pass, proceed with making the web request.
# A timeout is crucial to prevent the server from hanging on slow or malicious endpoints.
with requests.get(pdf_url, stream=True, timeout=10) as response:
response.raise_for_status()
# Placeholder for actual PDF processing (e.g., using PyMuPDF/fitz)
# In a real implementation, you would process the response content here.
# For demonstration, we'll just confirm successful download.
print(f"Successfully and securely validated URL. Fetching content from {pdf_url}")
# Example: Reading the first chunk to simulate processing
first_chunk = next(response.iter_content(chunk_size=1024), None)
if first_chunk:
print("PDF content stream started.")
return "Document validation and processing successful."
except (ValueError, requests.exceptions.RequestException) as e:
# Catch specific validation, network, or HTTP errors
return f"Processing failed: {e}"
except Exception as e:
# Catch any other unexpected errors during processing
return f"An unexpected error occurred: {e}"Payload
{
"document_url": "http://169.254.169.254/latest/meta-data/"
}
Cite this entry
@misc{vaitp:cve20264308,
title = {{agent-zero 0.9.7 is vulnerable to remote SSRF in its PDF document handler.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-4308},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-4308/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
