Skip to content

CVE-2026-10129: Verified Repro With Script Download

CVE-2026-10129: Langflow OSS SSRF and privilege escalation

CVE-2026-10129 is verified against the affected target. Vulnerability class: SSRF. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00240.

REPRO-2026-00240 SSRF Variant found Jul 6, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.5
Confidence
HIGH
Reproduced in
56m 49s
Tool calls
446
Spend
$15.88
01 · Overview

What Is CVE-2026-10129?

CVE-2026-10129 is a high-severity Server-Side Request Forgery vulnerability (CWE-918) in IBM Langflow OSS that bypasses SSRF protection and can be chained to escalate privileges. Pruva reproduced it (reproduction REPRO-2026-00240).

02 · Severity & CVSS

CVE-2026-10129 Severity & CVSS Score

CVE-2026-10129 is rated high severity, with a CVSS base score of 8.5 out of 10.

HIGH threat level
8.5 / 10 CVSS base
Weakness CWE-918 (Server-Side Request Forgery) — Server-Side Request Forgery (SSRF)

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce CVE-2026-10129

$ pruva-verify REPRO-2026-00240
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00240/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-10129

Privilege escalation — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

API Request component URL set to a public redirector that redirects to http://127.0.0.1:9999/admin-token with follow_redirects=true

Attack chain
  1. POST /api/v1/flows/ then POST /api/v1/build/{flow_id}/flow?event_delivery=direct executes API Request component
Observed — the exploit firing
internal marker service listening on 127.0.0.1:9998
127.0.0.1 - "GET /marker HTTP/1.1" 200 -
127.0.0.1 - "GET /marker HTTP/1.1" 200 -
Variants tested

Alternate same-root-cause redirect SSRF trigger through Langflow URLComponent: vulnerable lfx 0.4.6 validates the initial public URL then RecursiveUrlLoader follows a redirect to loopback; latest HEAD blocks the same redirect, so this is not a fixed-version bypass.

How the agent worked 952 events · 446 tool calls · 57 min
57 minDuration
446Tool calls
193Reasoning steps
952Events
3Dead-ends
Agent activity over 57 min
Support
22
Repro
681
Judge
48
Variant
196
0:0056:49

Root Cause and Exploit Chain for CVE-2026-10129

Versions: IBM reports Langflow OSS 1.0.0 through 1.9.3 as affected. The reproduction installs langflow==1.9.3, pins langflow-base==0.9.3, and confirms the resolved vulnerable component stack is lfx==0.4.6 with no _follow_redirects_with_validation method.

CVE-2026-10129 is a Server-Side Request Forgery (SSRF) protection bypass in the Langflow OSS API Request component. When SSRF protection is enabled, the component validates the initial URL and pins DNS for that original host, but if follow_redirects=true it lets httpx automatically follow redirects without re-validating each redirect destination. A low-privileged Langflow flow author can submit a public URL that redirects to 127.0.0.1 or another internal address and receive the internal response through normal Langflow build events. In this run, the SSRF was chained on the real Langflow HTTP API surface to a privilege boundary effect: the low-privileged attacker retrieved a loopback-only internal admin bearer token, used it against Langflow's real admin-only user-management API, promoted their own account, and verified that the original attacker session became a superuser.

  • Package/component affected: lfx.components.data_source.api_request.APIRequestComponent, used by Langflow OSS as the "API Request" component.
  • Affected versions: IBM reports Langflow OSS 1.0.0 through 1.9.3 as affected. The reproduction installs langflow==1.9.3, pins langflow-base==0.9.3, and confirms the resolved vulnerable component stack is lfx==0.4.6 with no _follow_redirects_with_validation method.
  • Risk level and consequences: High. An authenticated low-privileged flow author can bypass SSRF protections intended to block loopback/private/link-local destinations. The bypass can expose internal admin panels, metadata services, credentials, or tokens. This run demonstrates a concrete privilege escalation consequence: an internal admin token was obtained through the API Request component and used to promote the attacker account to superuser.

Impact Parity

  • Disclosed/claimed maximum impact: Privilege escalation through an SSRF protection bypass to an internal/admin endpoint.
  • Reproduced impact from this run: Full production-surface privilege escalation. The script runs a real Langflow 1.9.3 server in multi-user mode, creates a real non-superuser attacker account through POST /api/v1/users/, proves that the attacker receives 403 from the admin-only GET /api/v1/users/ endpoint before exploitation, runs a real API Request flow through POST /api/v1/build/{flow_id}/flow, retrieves a loopback-only internal admin bearer token from the flow output, uses that stolen token against real Langflow admin APIs, promotes the attacker with PATCH /api/v1/users/{attacker_id}, and verifies the original attacker token now returns is_superuser=true from GET /api/v1/users/whoami.
  • Parity: full for the ticket claim. The validated surface is api_remote, and the observed impact is privilege_escalation.
  • Not demonstrated: The proof does not attempt arbitrary code execution or cloud metadata compromise; it focuses on the claimed SSRF-to-privilege-escalation chain.

Root Cause

The vulnerable API Request component performs SSRF validation only for the initial user-supplied URL:

  1. It parses and validates the URL and resolves the initial hostname.
  2. It rejects private, loopback, link-local, and otherwise blocked IP ranges for that initial host.
  3. It creates an SSRF-protected transport that pins DNS for the original hostname.
  4. It calls the HTTP request layer with follow_redirects=follow_redirects.

When follow_redirects=true, httpx handles 3xx redirects internally. For a redirect from a public host to http://127.0.0.1:9999/..., the original public URL passes validation, but the redirect destination is a new host. The vulnerable code does not call validate_and_resolve_url() again for that redirect target. As a result, the 127.0.0.1 destination is reached even though a direct request to the same URL is correctly blocked by SSRF protection.

The fixed code path present in repository HEAD / fixed api_request.py adds _follow_redirects_with_validation, which performs each request with redirects disabled, resolves the Location header, and re-runs SSRF validation before following every redirect hop. The reproduction's fixed-control swap uses that official HEAD api_request.py and observes the expected error: SSRF Protection: blocked redirect to http://127.0.0.1:9999/admin-token.

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh.
  2. What the script does:
    • Reuses/creates bundle/data/venv and installs the vulnerable stack: langflow==1.9.3, langflow-base==0.9.3, lfx==0.4.6.
    • Starts a real Langflow server on 127.0.0.1:7860 in multi-user mode with SSRF protection enabled.
    • Configures a real Langflow superuser (admin) and creates a real low-privileged user (attacker) via the public user API.
    • Starts a loopback-only internal admin/metadata service on 127.0.0.1:9999. This service reads the real Langflow admin user from SQLite and returns a real admin JWT signed with the same Langflow SECRET_KEY.
    • Generates a real Langflow flow containing the API Request component with a public postman-echo.com/redirect-to URL that redirects to http://127.0.0.1:9999/admin-token.
    • Logs in as the low-privileged attacker, creates the flow through POST /api/v1/flows/, executes it through POST /api/v1/build/{flow_id}/flow?event_delivery=direct, extracts the internal admin token from returned build events, and uses it against real admin-only Langflow endpoints to promote the attacker.
    • Runs a negative control showing a direct http://127.0.0.1:9999/admin-token API Request is blocked by SSRF protection.
    • Runs a fixed control by swapping in the official fixed api_request.py, showing redirect re-validation blocks the same public-to-loopback redirect.
  3. Expected evidence of reproduction:
    • logs/exploit_summary.json contains attacker_is_superuser_before=false, lowpriv_admin_list_status_before=403, marker_found=true, stolen_token_is_superuser=true, stolen_token_admin_list_status=200, promote_attacker_status=200, attacker_is_superuser_after=true, and privilege_escalation_observed=true.
    • logs/direct_summary.json contains marker_found=false and ssrf_blocked=true.
    • logs/fixed_harness.json contains ok=false and a blocked-redirect SSRF protection error.
    • bundle/repro/runtime_manifest.json records entrypoint_kind="api_remote", service_started=true, healthcheck_passed=true, and target_path_reached=true.

Evidence

Primary evidence artifacts:

  • bundle/logs/reproduction_steps.log — high-level script log and final verdict.
  • bundle/logs/exploit_summary.json — structured exploit and privilege-escalation evidence.
  • bundle/logs/build_exploit.ndjson — raw Langflow build events showing the API Request component response from the loopback internal service.
  • bundle/logs/direct_summary.json and bundle/logs/build_direct.ndjson — negative control showing direct loopback access is blocked.
  • bundle/logs/fixed_harness.json — fixed-control evidence that redirect re-validation blocks the attack.
  • bundle/logs/vuln_harness.json — secondary component-level evidence that the vulnerable component follows the redirect.
  • bundle/logs/langflow_server.log — real Langflow server runtime log.
  • bundle/logs/internal_admin.log — loopback internal admin service log.
  • bundle/repro/runtime_manifest.json — runtime manifest written by the reproduction script.

Key excerpts from the successful run:

  • Vulnerable stack confirmation: installed: langflow 1.9.3 langflow-base 0.9.3 lfx 0.4.6 and installed api_request.py has redirect re-validation fix? no.
  • Pre-exploit privilege boundary: attacker_is_superuser_before: false and lowpriv_admin_list_status_before: 403 with body The user doesn't have enough privileges.
  • SSRF bypass: marker_found: true, reached_internal: true, and stolen_admin_token_found: true in logs/exploit_summary.json.
  • Admin-token use: stolen_token_whoami_status: 200, stolen_token_username: admin, stolen_token_is_superuser: true, and stolen_token_admin_list_status: 200.
  • Privilege escalation: promote_attacker_status: 200, attacker_is_superuser_after: true, and privilege_escalation_observed: true.
  • Direct SSRF protection control: direct_blocked=true and SSRF Protection: Hostname 127.0.0.1 resolves to blocked IP address(es): 127.0.0.1.
  • Fixed control: ValueError: SSRF Protection: blocked redirect to http://127.0.0.1:9999/admin-token.

Environment details captured by the script include the Langflow package versions, SQLite runtime, internal admin service endpoint, public redirector URL, and all runtime proof artifact paths in bundle/repro/runtime_manifest.json.

Recommendations / Next Steps

  • Apply per-hop SSRF validation for all redirects. Each Location destination should be resolved and checked against the same denylist/allowlist policy before the client connects.
  • Prefer manually handling redirects with follow_redirects=False, validating the next URL before each hop, enforcing a maximum redirect count, and preserving DNS pinning semantics for every validated host.
  • Upgrade affected deployments to a Langflow/Langflow-base/LFX build containing _follow_redirects_with_validation or an equivalent redirect-validation fix.
  • Add regression tests for public-to-loopback, public-to-private, public-to-link-local, and multi-hop redirect chains with SSRF protection enabled.
  • Treat internal admin/metadata endpoints as sensitive. Avoid exposing reusable admin credentials on loopback-only HTTP services where possible, because SSRF bugs can convert loopback trust into remote privilege escalation.

Additional Notes

  • Idempotency: bundle/repro/reproduction_steps.sh was executed twice consecutively and exited successfully both times.
  • The primary proof uses the real Langflow HTTP API and real API Request component. The direct component harnesses are secondary controls only.
  • The internal admin service is intentionally local to the reproduction environment and models the internal/admin endpoint class described by the ticket. The privilege escalation effect is real within the running Langflow product: a non-superuser account is promoted via Langflow's actual admin-only API after SSRF leaks an admin bearer token.
  • The proof redacts JWT values in summaries where possible while preserving enough context to verify that an internal admin credential was retrieved and used.

Variant Analysis & Alternative Triggers for CVE-2026-10129

Versions: version tested: installed reproduction stack langflow==1.9.3, langflow-base==0.9.3, lfx==0.4.6.Fixed: /latest version tested: repository HEAD 315cc41b43c446bfb0e63d420ca55021f6f8987e, by overlaying HEAD url.py and ssrf_transport.py into the repro venv without changing the repository checkout.

A distinct same-root-cause alternate trigger was found in Langflow's built-in URL data-source component (lfx.components.data_source.url.URLComponent). On the vulnerable langflow==1.9.3 / lfx==0.4.6 stack, URLComponent validates only the initial attacker-supplied URL and then delegates fetching to RecursiveUrlLoader, whose HTTP clients follow redirects without re-validating redirect destinations. A public URL that redirects to 127.0.0.1 therefore reaches a loopback-only marker service. This is a real alternate component entry point for the same redirect-SSRF class, but it is not a bypass of latest repository HEAD: the later fixed/latest URLComponent implementation blocks the redirect with per-hop SSRF revalidation.

Fix Coverage / Assumptions

The original parent fix for the reproduced ticket is commit 44d43dbeaf9ce76e7ddf8371317232d07e3f6336 (fix: re-validate redirects against SSRF protection in API Request component (#13394)). It covers src/lfx/src/lfx/components/data_source/api_request.py by replacing automatic httpx redirect following with manual redirect handling that calls validate_and_resolve_url() for every Location hop.

The fix invariant is: if the API Request component follows a redirect, each redirected URL must pass the same SSRF denylist and DNS-pinning checks as the original URL. That invariant is sound for the parent APIRequestComponent path.

What the parent fix does not cover by itself is other components that accept attacker-controlled URLs and use their own HTTP clients. The tested gap is URLComponent, which in lfx==0.4.6 uses RecursiveUrlLoader after only initial URL validation. Later repository commits separately fixed this component, especially 9a868386f2e35ad78041867b22e161665408a8d2 (fix(components): follow HTTP redirects in URL component with per-hop SSRF revalidation (#13572)). Latest HEAD tested here includes that URLComponent fix.

Variant / Alternate Trigger

Tested alternate path:

  • Entrypoint kind: component_harness representing Langflow flow execution of the URL data-source component.
  • Component: lfx.components.data_source.url.URLComponent.
  • Method: fetch_url_contents().
  • Attacker-controlled input: urls=["https://postman-echo.com/redirect-to?url=http%3A%2F%2F127.0.0.1%3A9998%2Fmarker"].
  • Internal target: loopback-only marker service on 127.0.0.1:9998/marker.

Vulnerable code path:

  1. URLComponent.ensure_url() validates the initial public URL.
  2. URLComponent._create_loader() constructs RecursiveUrlLoader.
  3. URLComponent.fetch_url_contents() calls loader.load().
  4. RecursiveUrlLoader._get_child_links_recursive() calls requests.get(...), which follows redirects by default.
  5. The redirect to http://127.0.0.1:9998/marker is fetched without Langflow re-validation.

Fixed/latest code path:

  • src/lfx/src/lfx/components/data_source/url.py at HEAD 315cc41b43c446bfb0e63d420ca55021f6f8987e contains _fetch_with_revalidated_redirects() and _build_http_client() and performs per-hop validation. The same redirect is blocked.

  • Package/component affected: lfx / Langflow URL data-source component.

  • Affected version tested: installed reproduction stack langflow==1.9.3, langflow-base==0.9.3, lfx==0.4.6.

  • Fixed/latest version tested: repository HEAD 315cc41b43c446bfb0e63d420ca55021f6f8987e, by overlaying HEAD url.py and ssrf_transport.py into the repro venv without changing the repository checkout.

  • Risk: high in affected deployments with untrusted or low-privileged flow authors. The component can reach loopback/private/link-local services despite SSRF protection, enabling internal data exposure and potential privilege escalation when internal credentials or admin APIs are reachable.

Impact Parity

  • Parent disclosed/claimed maximum impact: SSRF protection bypass chained to privilege escalation.
  • Reproduced variant impact: internal loopback resource disclosure through a distinct component. The proof retrieves a loopback-only marker JSON containing INTERNAL_ADMIN_TOKEN_CVE_2026_10129 through URLComponent output.
  • Parity: partial. The same SSRF primitive is reproduced through a distinct component, but this variant script does not repeat the full admin-token promotion chain from the parent reproduction.
  • Not demonstrated: full remote Langflow API flow creation/build for URLComponent, cloud metadata compromise, or final privilege escalation from this alternate component. The component harness is sufficient to prove the vulnerable server-side sink and fixed/latest blocking behavior.

Root Cause

The root cause is the same redirect-validation error as the parent: SSRF validation was applied to only the original user-controlled URL while the actual HTTP client could follow a redirect to a new, unvalidated host.

For the parent, the downstream client was httpx inside APIRequestComponent. For the variant, the downstream client was RecursiveUrlLoader (requests/aiohttp) used by URLComponent. In both cases, the security boundary is crossed when an authenticated flow author supplies a URL to a server-side Langflow component while SSRF protection is expected to prevent loopback/internal network access.

Known fixes:

  • Parent API Request fix: 44d43dbeaf9ce76e7ddf8371317232d07e3f6336.
  • URLComponent redirect fix: 9a868386f2e35ad78041867b22e161665408a8d2.
  • Latest tested HEAD: 315cc41b43c446bfb0e63d420ca55021f6f8987e.

Reproduction Steps

  1. Run bundle/vuln_variant/reproduction_steps.sh.
  2. The script:
    • Uses the successful repro virtualenv (bundle/data/venv) containing vulnerable lfx==0.4.6.
    • Starts a loopback-only marker service on 127.0.0.1:9998.
    • Runs bundle/vuln_variant/run_url_component.py against vulnerable installed URLComponent with a public redirector URL.
    • Confirms the vulnerable component returns the loopback marker.
    • Creates an isolated Python overlay containing fixed/latest URLComponent copied from repository HEAD, without mutating the repro checkout.
    • Runs the same input against the fixed/latest overlay.
    • Confirms fixed/latest blocks the redirect and does not return the marker.
  3. Expected script exit: 1, because the variant is an alternate vulnerable-version trigger but not a HEAD bypass. The script ran twice successfully and produced this expected exit code both times.

Evidence

Primary evidence:

  • bundle/logs/vuln_variant/reproduction_steps.log — high-level run log and verdict.
  • bundle/logs/vuln_variant/url_component_vulnerable.json — vulnerable URLComponent reached internal marker.
  • bundle/logs/vuln_variant/url_component_fixed_latest.json — fixed/latest URLComponent blocked the same redirect.
  • bundle/vuln_variant/runtime_manifest.json — runtime identity and evidence list.
  • bundle/logs/vuln_variant/latest_version.txt and bundle/logs/vuln_variant/latest_git_identity.txt — exact fixed/latest source identity.

Key observed facts:

  • Vulnerable log reports variant_reached_internal=true, marker_in_output=true, lfx_version=0.4.6, and has_redirect_revalidation_method=false.
  • Fixed/latest log reports variant_reached_internal=false, has_redirect_revalidation_method=true, and an error blocking http://127.0.0.1:9998/marker because it resolves to 127.0.0.1.
  • Submitted vulnerable tag v1.9.3 resolves to 322e4908b931a3efe2d65c6a7ad5ec373c5a5e1d.
  • Latest tested source resolves to 315cc41b43c446bfb0e63d420ca55021f6f8987e.

Recommendations / Next Steps

  1. Do not ship only the API Request redirect fix as a product-wide SSRF fix. Include URLComponent redirect revalidation (9a868386f2...) or equivalent coverage.
  2. Centralize safe HTTP helpers for all attacker-controlled URL inputs. Components should not call requests.get, httpx with automatic redirects, aiohttp, or third-party loaders on user URLs unless redirect handling re-enters Langflow SSRF validation per hop.
  3. Add regression tests for every built-in component field that accepts a URL or base URL, using both direct internal URLs and public-to-internal redirects.
  4. Prefer deny-by-default helper APIs that reject follow_redirects=True unless the helper owns per-hop validation.

Additional Notes

  • The target SECURITY.md was reviewed and does not exclude SSRF. The RecursiveUrlLoader documentation explicitly warns that crawlers can create SSRF risk; in Langflow this risk crosses a server-side trust boundary because flow authors control component inputs.
  • The repository checkout was not changed. Fixed/latest testing used a temporary overlay under bundle/vuln_variant/fixed_overlay.
  • Idempotency was confirmed: bundle/vuln_variant/reproduction_steps.sh was run twice; both runs completed and returned the expected non-bypass exit code (1).

CVE-2026-10129 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:25
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-10129 · REPRO-20
0:02
0:04
web search
0:06
web search
0:08
0:12
0:14
web search
0:18
0:32
0:35
web search
0:40
0:55
0:57
web search
1:14
1:14
extract_facts
no facts extracted
1:15
1:15
1:15
supportrepro
1:17
1:17
1:17
1:18
1:18
1:20
1:20
1:21
web search
1:25
1:25
1:25
1:25
$cd /data/pruva/project-cache/688af86e-dc4c-4d20-bb02-ccdf8da2c7d0/repo && git log --oneline -15 && echo "---HEAD---" && git rev-parse HEAD && echo "---TAGS---" && git tag | grep -E "1\.9|1\.8" | head -40
{"cwd":"/data/pruva/runs/50e1d94c-35c4-431a-b622-d84ef4d2d9ee","duration_ms":5,"exit_code":0,"stderr":"","stdout":"315cc41b43 ci: surface nightly Group 3 stall via 90s pytest thread-timeout (#13938)\nab8508db73 fix(ci): consolidate recent nightly CI fixes\n26dc6fd3bc chore: update test durations (#13888)\na277209fe4 ci: push nightly .devX Docker images to langflowai/langflow and fix db-migration-validation image references (#13836)\n4da60c4b12 fix: keep nightly prerelease wheels explicit (#13817)\n7db38d1abb fix: unblock nightly bundle install resolution\n1a60220497 Merge remote-tracking branch 'origin/release-1.10.1'\na66b75ac26 chore: require bumped sdk for lfx release\nf85901e49d chore: bump sdk release version\n4c8fb6b954 fix: gate release rc setup for stable releases\n7db4bcb890 fix: degrade gracefully when caching unpicklable values in RedisCache (#13781)\n8c98cdf5cc fix(security): block socket/urllib network egress in component code scanner (#13784)\nf58914bc84 fix: release candidate version selection (#13776)\n2302ef9931 fix(component): reconnect stale cached SQL database connections on SQL Database component (#13733)\n408b737980 fix(agents): stop leaking LangChain chain ma… [truncated]
08 · How to Fix

How to Fix CVE-2026-10129

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-10129 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-10129

How does the CVE-2026-10129 SSRF-to-privilege-escalation chain work?

A low-privileged Langflow flow author submits a public URL configured to redirect to a loopback or internal address; because redirect destinations aren't re-validated, the component fetches the internal response and returns it through normal Langflow build events. In the reproduced chain, this leaked a loopback-only internal admin bearer token, which was then used against Langflow's real admin-only user-management API to promote the attacker's own account to superuser.

Which Langflow versions are affected by CVE-2026-10129?

IBM reports Langflow OSS 1.0.0 through 1.9.3 as affected. The reproduction installs langflow==1.9.3, pinned to langflow-base==0.9.3, and confirms the resolved vulnerable component stack is lfx==0.4.6 with no _follow_redirects_with_validation method.

How severe is CVE-2026-10129?

It is rated high severity: an authenticated low-privileged flow author can bypass SSRF protections intended to block loopback/private/link-local destinations, potentially exposing internal admin panels and, as reproduced here, escalating to superuser.

How can I reproduce CVE-2026-10129?

Download the verified script from this page and run it in an isolated environment against Langflow OSS 1.9.3 with SSRF protection enabled. It creates a low-privileged flow, uses the API Request component with a redirect-following URL pointed at an internal admin endpoint, retrieves the leaked internal bearer token, and uses it to promote the attacker account to superuser.
11 · References

References for CVE-2026-10129

Authoritative sources for CVE-2026-10129 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.