langchain - 💡(How to fix) Fix Bug: SSRF bypass in validate_safe_url when LANGCHAIN_ENV=local_test

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

I'm auditing the SSRF protection layer in langchain-core.

I expect validate_safe_url() to always block untrusted hostnames.

Instead, when LANGCHAIN_ENV=local_test, any hostname matching startswith("test") and "server" in hostname bypasses all validation and is returned unchecked — including attacker-controlled hostnames like test.attacker.server.com.

A second issue: _effective_allowed_hosts() uses startswith("local") which expands the allowlist for any env var prefixed with "local" (e.g. "local_staging"), not just the two intended values.

I have a working fix + regression tests ready on my fork (PR #37295). Requesting assignment.

Error Message

Error Message and Stack Trace (if applicable)

Root Cause

I'm auditing the SSRF protection layer in langchain-core.

I expect validate_safe_url() to always block untrusted hostnames.

Instead, when LANGCHAIN_ENV=local_test, any hostname matching startswith("test") and "server" in hostname bypasses all validation and is returned unchecked — including attacker-controlled hostnames like test.attacker.server.com.

A second issue: _effective_allowed_hosts() uses startswith("local") which expands the allowlist for any env var prefixed with "local" (e.g. "local_staging"), not just the two intended values.

I have a working fix + regression tests ready on my fork (PR #37295). Requesting assignment.

Fix Action

Fix / Workaround

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Code Example

import os
os.environ["LANGCHAIN_ENV"] = "local_test"

from langchain_core._security._ssrf_protection import validate_safe_url

result = validate_safe_url("http://test.attacker.server.com/exfil")
print(result)  # prints URL instead of raising ValueError

---

I'm auditing the SSRF protection layer in langchain-core.

I expect validate_safe_url() to always block untrusted hostnames.

Instead, when LANGCHAIN_ENV=local_test, any hostname matching
startswith("test") and "server" in hostname bypasses all validation
and is returned unchecked — including attacker-controlled hostnames
like test.attacker.server.com.

A second issue: _effective_allowed_hosts() uses startswith("local")
which expands the allowlist for any env var prefixed with "local"
(e.g. "local_staging"), not just the two intended values.

I have a working fix + regression tests ready on my fork (PR #37295).
Requesting assignment.
RAW_BUFFERClick to expand / collapse

Submission checklist

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package (Required)

  • langchain
  • langchain-openai
  • langchain-anthropic
  • langchain-classic
  • langchain-core
  • langchain-model-profiles
  • langchain-tests
  • langchain-text-splitters
  • langchain-chroma
  • langchain-deepseek
  • langchain-exa
  • langchain-fireworks
  • langchain-groq
  • langchain-huggingface
  • langchain-mistralai
  • langchain-nomic
  • langchain-ollama
  • langchain-openrouter
  • langchain-perplexity
  • langchain-qdrant
  • langchain-xai
  • Other / not sure / general

Related Issues / PRs

#37295

Reproduction Steps / Example Code (Python)

import os
os.environ["LANGCHAIN_ENV"] = "local_test"

from langchain_core._security._ssrf_protection import validate_safe_url

result = validate_safe_url("http://test.attacker.server.com/exfil")
print(result)  # prints URL instead of raising ValueError

Error Message and Stack Trace (if applicable)

I'm auditing the SSRF protection layer in langchain-core.

I expect validate_safe_url() to always block untrusted hostnames.

Instead, when LANGCHAIN_ENV=local_test, any hostname matching
startswith("test") and "server" in hostname bypasses all validation
and is returned unchecked — including attacker-controlled hostnames
like test.attacker.server.com.

A second issue: _effective_allowed_hosts() uses startswith("local")
which expands the allowlist for any env var prefixed with "local"
(e.g. "local_staging"), not just the two intended values.

I have a working fix + regression tests ready on my fork (PR #37295).
Requesting assignment.

Description

I'm auditing the SSRF protection layer in langchain-core.

I expect validate_safe_url() to always block untrusted hostnames.

Instead, when LANGCHAIN_ENV=local_test, any hostname matching startswith("test") and "server" in hostname bypasses all validation and is returned unchecked — including attacker-controlled hostnames like test.attacker.server.com.

A second issue: _effective_allowed_hosts() uses startswith("local") which expands the allowlist for any env var prefixed with "local" (e.g. "local_staging"), not just the two intended values.

I have a working fix + regression tests ready on my fork (PR #37295). Requesting assignment.

System Info

python -m langchain-core latest, Python 3.11+

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING