CVE-2026-41182
LangSmith SDKs leak sensitive data as redaction fails on streaming events.
- CVSS 5.3
- CWE-200
- Information Leakage
- Local
LangSmith Client SDKs provide SDK's for interacting with the LangSmith platform. Prior to version 0.5.19 of the JavaScript SDK and version 0.7.31 of the Python SDK, the LangSmith SDK's output redaction controls (hideOutputs in JS, hide_outputs in Python) do not apply to streaming token events. When an LLM run produces streaming output, each chunk is recorded as a new_token event containing the raw token value. These events bypass the redaction pipeline entirely — prepareRunCreateOrUpdateInputs (JS) and _hide_run_outputs (Python) only process the inputs and outputs fields on a run, never the events array. As a result, applications relying on output redaction to prevent sensitive LLM output from being stored in LangSmith will still leak the full streamed content via run events. Version 0.5.19 of the JavaScript SDK and version 0.7.31 of the Python SDK fix the issue.
- CWE
- CWE-200
- CVSS base score
- 5.3
- Published
- 2026-04-23
- OWASP
- A09 Security Logging and Monitoring Failures
- Orthogonal defect classification
- Function
- Code defect classification
- Incorrect Functionality
- Category
- Information Leakage
- Subcategory
- Insecure Handling of Sensitive Data
- Accessibility scope
- Local
- Impact
- Information Disclosure
- Affected component
- LangSmith Cl
- Fixed by upgrading
- Yes
Solution
Upgrade the LangSmith JavaScript SDK to version 0.5.19 and the Python SDK to version 0.7.31.
Vulnerable code sample
import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableConfig
# This code requires a vulnerable version of the langsmith SDK, e.g., pip install langsmith==0.7.30
# You would also need: pip install langchain-openai langchain
# --- Setup: Configure your environment variables ---
# You must set these environment variables for the code to run.
# os.environ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ["LANGCHAIN_API_KEY"] = "YOUR_LANGSMITH_API_KEY"
# os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"
# os.environ["LANGCHAIN_PROJECT"] = "CVE-2026-41182-Demo" # Optional: to group runs
# 1. Define the LLM chain
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_template(
"Tell me a short, sensitive-sounding secret about {topic}."
)
chain = prompt | model | StrOutputParser()
# 2. Configure the run to hide outputs
# This is the configuration that is intended to prevent output logging.
config: RunnableConfig = {
"run_name": "Streaming Run with Redaction",
"metadata": {
"hide_outputs": True,
}
}
# 3. Stream the chain's output
# This action triggers the vulnerability.
print("Streaming output (this will leak to LangSmith events):")
full_output = ""
for chunk in chain.stream({"topic": "the lost city of Atlantis"}, config=config):
print(chunk, end="", flush=True)
full_output += chunk
print("\n\n---")
print("Run completed. Check your LangSmith project.")
print("In the trace, the final 'outputs' field will be redacted as expected.")
print("However, the 'events' list will contain 'new_token' events, each showing a raw piece of the streamed secret.")Patched code sample
import copy
import json
from typing import Any, Dict, List
# This example demonstrates the logic used to fix CVE-2026-41182.
# The vulnerability was that the 'hide_outputs' feature did not redact
# streaming 'new_token' events. The fix involves iterating through these
# events and redacting them, in addition to the final 'outputs' field.
REDACTED_VALUE = "[REDACTED]"
def _apply_output_redaction_fixed(run: Dict[str, Any]) -> Dict[str, Any]:
"""
A representation of the fixed logic that redacts both the final run output
and the intermediate streaming token events.
This function simulates the patched behavior in the LangSmith SDK
(version 0.7.31 and later).
"""
# Create a copy to avoid modifying the original data in this example.
run_copy = copy.deepcopy(run)
# 1. Redact the final 'outputs' field (this part was already working).
if "outputs" in run_copy and run_copy["outputs"] is not None:
run_copy["outputs"] = REDACTED_VALUE
# 2. THE FIX: Iterate through events and redact 'new_token' chunks.
# The original vulnerable code skipped this entire block.
events: List[Dict[str, Any]] = run_copy.get("events", [])
for event in events:
if event.get("name") == "new_token":
# The sensitive token value is typically in event["kwargs"]["chunk"].
if "kwargs" in event and isinstance(event["kwargs"], dict):
if "chunk" in event["kwargs"]:
event["kwargs"]["chunk"] = REDACTED_VALUE
return run_copy
# --- Demonstration ---
# Simulate a LangSmith run object containing sensitive data in streaming events.
# This data structure mimics what would be sent to the LangSmith platform.
run_with_sensitive_stream = {
"name": "SensitiveDataQuery",
"run_type": "llm",
"inputs": {"prompt": "What is the secret access key?"},
"outputs": {
"generations": [{"text": "The secret key is sk-12345."}]
},
"events": [
{"name": "start", "time": "...", "kwargs": {}},
{"name": "new_token", "time": "...", "kwargs": {"chunk": "The "}},
{"name": "new_token", "time": "...", "kwargs": {"chunk": "secret "}},
{"name": "new_token", "time": "...", "kwargs": {"chunk": "key is "}},
{"name": "new_token", "time": "...", "kwargs": {"chunk": "sk-12345."}},
{"name": "end", "time": "...", "kwargs": {}},
],
}
# Apply the fixed redaction logic.
redacted_run_object = _apply_output_redaction_fixed(run_with_sensitive_stream)
# Print the result. Notice that the 'chunk' values in the 'new_token' events
# are now redacted, demonstrating the fix.
print(json.dumps(redacted_run_object, indent=2))Cite this entry
@misc{vaitp:cve202641182,
title = {{LangSmith SDKs leak sensitive data as redaction fails on streaming events.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-41182},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-41182/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
