Threat Intelligence

Live CVE feed

299 threats tracked across 7 launch stacks — sourced from NVD, GHSA, CISA KEV, OSV, npm Audit, and EPSS.

299threats · All threats· page 4/15
Get guardrails →

React Router has CSRF issue in Action/Server Action Request Processing

React Router (or Remix v2) is vulnerable to CSRF attacks on document POST requests to UI routes when using server-side route action handlers in Framework Mode, or when using React Server Actions in the new unstable RSC modes. > [!NOTE] > This does not impact applications that use Declarative Mode (<BrowserRouter>) or Data Mode (createBrowserRouter/<RouterProvider>).

OWASP A05OWASP A08OWASP Web
Get guardrail →

React Router vulnerable to XSS via Open Redirects

React Router (and Remix v1/v2) SPA open navigation redirects originating from loaders or actions in Framework Mode, Data Mode, or the unstable RSC modes can result in unsafe URLs causing unintended javascript execution on the client. This is only an issue if developers are creating redirect paths from untrusted content or via an open redirect. > [!NOTE] > This does not impact applications that use Declarative Mode (<BrowserRouter>).

OWASP A03OWASP Web
Get guardrail →

React Router SSR XSS in ScrollRestoration

A XSS vulnerability exists in in React Router's <ScrollRestoration> API in Framework Mode when using the getKey/storageKey props during Server-Side Rendering which could allow arbitrary JavaScript execution during SSR if untrusted content is used to generate the keys. > [!NOTE] > This does not impact applications if developers have disabled server-side rendering in Framework Mode, or if they are using Declarative Mode (<BrowserRouter>) or Data Mode (createBrowserRouter/<RouterProvider>).

OWASP A03OWASP Web
Get guardrail →

React Router has unexpected external redirect via untrusted paths

An attacker-supplied path can be crafted so that when a React Router application navigates to it via navigate(), <Link>, or redirect(), the app performs a navigation/redirect to an external URL. This is only an issue if developers pass untrusted content into navigation paths in their application code.

React Router has XSS Vulnerability

A XSS vulnerability exists in in React Router's meta()/<Meta> APIs in Framework Mode when generating script:ld+json tags which could allow arbitrary JavaScript execution during SSR if untrusted content is used to generate the tag. > [!NOTE] > This does not impact applications using Declarative Mode (<BrowserRouter>) or Data Mode (createBrowserRouter/<RouterProvider>).

OWASP A03OWASP Web
Get guardrail →
2 rules

LangChain serialization injection vulnerability enables secret extraction in dumps/loads APIs

Summary A serialization injection vulnerability exists in LangChain's dumps() and dumpd() functions. The functions do not escape dictionaries with 'lc' keys when serializing free-form dictionaries. The 'lc' key is used internally by LangChain to mark serialized objects. When user-controlled data contains this key structure, it is treated as a legitimate LangChain object during deserialization rather than plain user data. Attack surface The core vulnerability was in dumps() and dumpd(): these functions failed to escape user-controlled dictionaries containing 'lc' keys. When this unescaped data was later deserialized via load() or loads(), the injected structures were treated as legitimate LangChain objects rather than plain user data. This escaping bug enabled several attack vectors: 1. Injection via user data: Malicious LangChain object structures could be injected through user-controlled fields like metadata, additional_kwargs, or response_metadata 2. Class instantiation within trusted namespaces: Injected manifests could instantiate any Serializable subclass, but only within the pre-approved trusted namespaces (langchain_core, langchain, langchain_community). This includes classes with side effects in __init__ (network calls, file operations, etc.). Note that namespace validation was already enforced before this patch, so arbitrary classes outside these trusted namespaces could not be instantiated. Security hardening This patch fixes the escaping bug in dumps() and dumpd() and introduces new restrictive defaults in load() and loads(): allowlist enforcement via allowed_objects="core" (restricted to serialization mappings), secrets_from_env changed from True to False, and default Jinja2 template blocking via init_validator. These are breaking changes for some use cases. Who is affected? Applications are vulnerable if they: 1. Use astream_events(version="v1") — The v1 implementation internally uses vulnerable serialization. Note: astream_events(version="v2") is not vulnerable. 2. Use Runnable.astream_log() — This method internally uses vulnerable serialization for streaming outputs. 3. Call dumps() or dumpd() on untrusted data, then deserialize with load() or loads() — Trusting your own serialization output makes you vulnerable if user-controlled data (e.g., from LLM responses, metadata fields, or user inputs) contains 'lc' key structures. 4. Deserialize untrusted data with load() or loads() — Directly deserializing untrusted data that may contain injected 'lc' structures. 5. Use RunnableWithMessageHistory — Internal serialization in message history handling. 6. Use InMemoryVectorStore.load() to deserialize untrusted documents. 7. Load untrusted generations from cache using langchain-community caches. 8. Load untrusted manifests from the LangChain Hub via hub.pull. 9. Use StringRunEvaluatorChain on untrusted runs. 10. Use create_lc_store or create_kv_docstore with untrusted documents. 11. Use MultiVectorRetriever with byte stores containing untrusted documents. 12. Use LangSmithRunChatLoader with runs containing untrusted messages. The most common attack vector is through LLM response fields like additional_kwargs or response_metadata, which can be controlled via prompt injection and then serialized/deserialized in streaming operations. Impact Attackers who control serialized data can extract environment variable secrets by injecting {"lc": 1, "type": "secret", "id": ["ENV_VAR"]} to load environment variables during deserialization (when secrets_from_env=True, which was the old default). They can also instantiate classes with controlled parameters by injecting constructor structures to instantiate any class within trusted namespaces with attacker-controlled parameters, potentially triggering side effects such as network calls or file operations. Key severity factors: Affects the serialization path - applications trusting their own serialization output are vulnerable Enables secret extraction when combined with secrets_from_env=True (the old default) LLM responses in additional_kwargs can be controlled via prompt injection Exploit example ``python from langchain_core.load import dumps, load import os Attacker injects secret structure into user-controlled data attacker_dict = { "user_data": { "lc": 1, "type": "secret", "id": ["OPENAI_API_KEY"] } } serialized = dumps(attacker_dict) # Bug: does NOT escape the 'lc' key os.environ["OPENAI_API_KEY"] = "sk-secret-key-12345" deserialized = load(serialized, secrets_from_env=True) print(deserialized["user_data"]) # "sk-secret-key-12345" - SECRET LEAKED! ` Security hardening changes (breaking changes) This patch introduces three breaking changes to load() and loads(): 1. New allowed_objects parameter (defaults to 'core'): Enforces allowlist of classes that can be deserialized. The 'all' option corresponds to the list of objects specified in mappings.py while the 'core' option limits to objects within langchain_core. We recommend that users explicitly specify which objects they want to allow for serialization/deserialization. 2. secrets_from_env default changed from True to False: Disables automatic secret loading from environment 3. New init_validator parameter (defaults to default_init_validator): Blocks Jinja2 templates by default Migration guide No changes needed for most users If you're deserializing standard LangChain types (messages, documents, prompts, trusted partner integrations like ChatOpenAI, ChatAnthropic, etc.), your code will work without changes: `python from langchain_core.load import load Uses default allowlist from serialization mappings obj = load(serialized_data) ` For custom classes If you're deserializing custom classes not in the serialization mappings, add them to the allowlist: `python from langchain_core.load import load from my_package import MyCustomClass Specify the classes you need obj = load(serialized_data, allowed_objects=[MyCustomClass]) ` For Jinja2 templates Jinja2 templates are now blocked by default because they can execute arbitrary code. If you need Jinja2 templates, pass init_validator=None: `python from langchain_core.load import load from langchain_core.prompts import PromptTemplate obj = load( serialized_data, allowed_objects=[PromptTemplate], init_validator=None ) ` > [!WARNING] > Only disable init_validator if you trust the serialized data. Jinja2 templates can execute arbitrary Python code. For secrets from environment secrets_from_env now defaults to False. If you need to load secrets from environment variables: `python from langchain_core.load import load obj = load(serialized_data, secrets_from_env=True) `` Credits Dumps bug was reported by @yardenporat Changes for security hardening due to findings from @0xn3va and @VladimirEliTokarev

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →

Next has a Denial of Service with Server Components - Incomplete Fix Follow-Up

It was discovered that the fix for CVE-2025-55184 in React Server Components was incomplete and did not fully mitigate denial-of-service conditions across all payload types. As a result, certain crafted inputs could still trigger excessive resource consumption. This vulnerability affects React versions 19.0.2, 19.1.3, and 19.2.2, as well as frameworks that bundle or depend on these versions, including Next.js 13.x, 14.x, 15.x, and 16.x when using the App Router. The issue is tracked upstream as CVE-2025-67779. A malicious actor can send a specially crafted HTTP request to a Server Function endpoint that, when deserialized, causes the React Server Components runtime to enter an infinite loop. This can lead to sustained CPU consumption and cause the affected server process to become unresponsive, resulting in a denial-of-service condition in unpatched environments.

OWASP A06OWASP A08LLM10OWASP Web
Get guardrail →

Denial of Service Vulnerability in React Server Components

Impact It was found that the fix to address CVE-2025-55184 in React Server Components was incomplete and does not prevent a denial of service attack in a specific case. We recommend updating immediately. The vulnerability exists in versions 19.0.2, 19.1.3, and 19.2.2 of: react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack These issues are present in the patches published on December 11th, 2025. Patches Fixes were back ported to versions 19.0.3, 19.1.4, and 19.2.3. If you are using any of the above packages please upgrade to any of the fixed versions immediately. If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability. References See the blog post for more information and upgrade instructions.

OWASP A06OWASP A08LLM10OWASP Web
Get guardrail →

Next Server Actions Source Code Exposure

A vulnerability affects certain React packages for versions 19.0.0, 19.0.1, 19.1.0, 19.1.1, 19.1.2, 19.2.0, and 19.2.1 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as CVE-2025-55183. A malicious HTTP request can be crafted and sent to any App Router endpoint that can return the compiled source code of Server Functions. This could reveal business logic, but would not expose secrets unless they were hardcoded directly into Server Function code.

OWASP A08OWASP Web
Get guardrail →

Next Vulnerable to Denial of Service with Server Components

A vulnerability affects certain React packages for versions 19.0.0, 19.0.1, 19.1.0, 19.1.1, 19.1.2, 19.2.0, and 19.2.1 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as CVE-2025-55184. A malicious HTTP request can be crafted and sent to any App Router endpoint that, when deserialized, can cause the server process to hang and consume CPU. This can result in denial of service in unpatched environments.

OWASP A06OWASP A08LLM10OWASP Web
Get guardrail →

Denial of Service Vulnerability in React Server Components

Impact There is a denial of service vulnerability in React Server Components. React recommends updating immediately. The vulnerability exists in versions 19.0.0, 19.0.1 19.1.0, 19.1.1, 19.1.2, 19.2.0 and 19.2.1 of: react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack These issues are present in the patches published last week. Patches Fixes were back ported to versions 19.0.2, 19.1.3, and 19.2.2. If you are using any of the above packages please upgrade to any of the fixed versions immediately. If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability. References See the blog post for more information and upgrade instructions.

OWASP A06OWASP A08LLM10OWASP Web
Get guardrail →

Source Code Exposure Vulnerability in React Server Components

Impact There is a source code exposure vulnerability in React Server Components. React recommends updating immediately. The vulnerability exists in versions 19.0.0, 19.0.1 19.1.0, 19.1.1, 19.1.2, 19.2.0 and 19.2.1 of: react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack These issues are present in the patches published last week. Patches Fixes were back ported to versions 19.0.2, 19.1.3, and 19.2.2. If you are using any of the above packages please upgrade to any of the fixed versions immediately. If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability. References See the blog post for more information and upgrade instructions.

OWASP A08OWASP Web
Get guardrail →
2 rules

React Server Components are Vulnerable to RCE

Impact There is an unauthenticated remote code execution vulnerability in React Server Components. We recommend upgrading immediately. The vulnerability is present in versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0 of: react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack Patches A fix was introduced in versions 19.0.1, 19.1.2, and 19.2.1. If you are using any of the above packages please upgrade to any of the fixed versions immediately. If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability. References See the blog post for more information and upgrade instructions.

OWASP A08OWASP Web
Get guardrail →

Next.js is vulnerable to RCE in React flight protocol

A vulnerability affects certain React packages<sup>1</sup> for versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as CVE-2025-55182. Fixed in: React: 19.0.1, 19.1.2, 19.2.1 Next.js: 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7, 15.6.0-canary.58, 16.1.0-canary.12+ The vulnerability also affects experimental canary releases starting with 14.3.0-canary.77. Users on any of the 14.3 canary builds should either downgrade to a 14.x stable release or 14.3.0-canary.76. All users of stable 15.x or 16.x Next.js versions should upgrade to a patched, stable version immediately. <sup>1</sup> The affected React packages are: react-server-dom-parcel react-server-dom-turbopack react-server-dom-webpack

OWASP A08OWASP Web
Get guardrail →

vLLM vulnerable to remote code execution via transformers_utils/get_config

Summary vllm has a critical remote code execution vector in a config class named Nemotron_Nano_VL_Config. When vllm loads a model config that contains an auto_map entry, the config class resolves that mapping with get_class_from_dynamic_module(...) and immediately instantiates the returned class. This fetches and executes Python from the remote repository referenced in the auto_map string. Crucially, this happens even when the caller explicitly sets trust_remote_code=False in vllm.transformers_utils.config.get_config. In practice, an attacker can publish a benign-looking frontend repo whose config.json points via auto_map to a separate malicious backend repo; loading the frontend will silently run the backend’s code on the victim host. Details The vulnerable code resolves and instantiates classes from auto_map entries without checking whether those entries point to a different repo or whether remote code execution is allowed. ``python class Nemotron_Nano_VL_Config(PretrainedConfig): model_type = 'Llama_Nemotron_Nano_VL' def __init__(self, kwargs): super().__init__(kwargs) if vision_config is not None: assert "auto_map" in vision_config and "AutoConfig" in vision_config["auto_map"] # <-- vulnerable dynamic resolution + instantiation happens here vision_auto_config = get_class_from_dynamic_module(vision_config["auto_map"]["AutoConfig"].split("--")[::-1]) self.vision_config = vision_auto_config(vision_config) else: self.vision_config = PretrainedConfig() ` get_class_from_dynamic_module(...) is capable of fetching and importing code from the Hugging Face repo specified in the mapping. trust_remote_code is not enforced for this code path. As a result, a frontend repo can redirect the loader to any backend repo and cause code execution, bypassing the trust_remote_code guard. Impact This is a critical vulnerability because it breaks the documented trust_remote_code safety boundary in a core model-loading utility. The vulnerable code lives in a common loading path, so any application, service, CI job, or developer machine that uses vllm`’s transformer utilities to load configs can be affected. The attack requires only two repos and no user interaction beyond loading the frontend model. A successful exploit can execute arbitrary commands on the host. Fixes https://github.com/vllm-project/vllm/pull/28126

OWASP A03LLM01 · Prompt InjectionOWASP LLM
Get guardrail →

body-parser is vulnerable to denial of service when url encoding is used

Impact body-parser 2.2.0 is vulnerable to denial of service due to inefficient handling of URL-encoded bodies with very large numbers of parameters. An attacker can send payloads containing thousands of parameters within the default 100KB request size limit, causing elevated CPU and memory usage. This can lead to service slowdown or partial outages under sustained malicious traffic. Patches This issue is addressed in version 2.2.1.

OWASP A06LLM10OWASP Web
Get guardrail →

vLLM vulnerable to DoS via large Chat Completion or Tokenization requests with specially crafted `chat_template_kwargs`

Summary The /v1/chat/completions and /tokenize endpoints allow a chat_template_kwargs request parameter that is used in the code before it is properly validated against the chat template. With the right chat_template_kwargs parameters, it is possible to block processing of the API server for long periods of time, delaying all other requests Details In serving_engine.py, the chat_template_kwargs are unpacked into kwargs passed to chat_utils.py apply_hf_chat_template with no validation on the keys or values in that chat_template_kwargs dict. This means they can be used to override optional parameters in the apply_hf_chat_template method, such as tokenize, changing its default from False to True. https://github.com/vllm-project/vllm/blob/2a6dc67eb520ddb9c4138d8b35ed6fe6226997fb/vllm/entrypoints/openai/serving_engine.py#L809-L814 https://github.com/vllm-project/vllm/blob/2a6dc67eb520ddb9c4138d8b35ed6fe6226997fb/vllm/entrypoints/chat_utils.py#L1602-L1610 Both serving_chat.py and serving_tokenization.py call into this _preprocess_chat method of serving_engine.py and they both pass in chat_template_kwargs. So, a chat_template_kwargs like {"tokenize": True} makes tokenization happen as part of applying the chat template, even though that is not expected. Tokenization is a blocking operation, and with sufficiently large input can block the API server's event loop, which blocks handling of all other requests until this tokenization is complete. This optional tokenize parameter to apply_hf_chat_template does not appear to be used, so one option would be to just hard-code that to always be False instead of allowing it to be optionally overridden by callers. A better option may be to not pass chat_template_kwargs as unpacked kwargs but instead as a dict, and only unpack them after the logic in apply_hf_chat_template that resolves the kwargs against the chat template. Impact Any authenticated user can cause a denial of service to a vLLM server with Chat Completion or Tokenize requests. Fix https://github.com/vllm-project/vllm/pull/27205

vLLM vulnerable to DoS with incorrect shape of multimodal embedding inputs

Summary Users can crash the vLLM engine serving multimodal models by passing multimodal embedding inputs with correct ndim but incorrect shape (e.g. hidden dimension is wrong), regardless of whether the model is intended to support such inputs (as defined in the Supported Models page). The issue has existed ever since we added support for image embedding inputs, i.e. #6613 (released in v0.5.5) Details Using image embeddings as an example: For models that support image embedding inputs, the engine crashes when scattering the embeddings to inputs_embeds (mismatched shape) For models that don't support image embedding inputs, the engine crashes when validating the inputs inside get_input_embeddings (validation fails). This happens because we only validate ndim of the tensor, but not the full shape, in input processor (via MultiModalDataParser). Impact Denial of service by crashing the engine Mitigation Use API key to limit access to trusted users. Set --limit-mm-per-prompt to 0 for all non-text modalities to ban multimodal inputs, which includes multimodal embedding inputs. However, the model would then only accept text, defeating the purpose of using a multi-modal model. Resolution https://github.com/vllm-project/vllm/pull/27204

vLLM deserialization vulnerability leading to DoS and potential RCE

Summary A memory corruption vulnerability that leading to a crash (denial-of-service) and potentially remote code execution (RCE) exists in vLLM versions 0.10.2 and later, in the Completions API endpoint. When processing user-supplied prompt embeddings, the endpoint loads serialized tensors using torch.load() without sufficient validation. Due to a change introduced in PyTorch 2.8.0, sparse tensor integrity checks are disabled by default. As a result, maliciously crafted tensors can bypass internal bounds checks and trigger an out-of-bounds memory write during the call to to_dense(). This memory corruption can crash vLLM and potentially lead to code execution on the server hosting vLLM. Details A vulnerability that can lead to RCE from the completions API endpoint exists in vllm, where due to missing checks when loading user-provided tensors, an out-of-bounds write can be triggered. This happens because the default behavior of torch.load(tensor, weights_only=True) since pytorch 2.8.0 is to not perform validity checks for sparse tensors, and this needs to be enabled explicitly using the torch.sparse.check_sparse_tensor_invariants context manager. The vulnerability is in the following code in vllm/entrypoints/renderer.py:148 ``python def _load_and_validate_embed(embed: bytes) -> EngineEmbedsPrompt: tensor = torch.load( io.BytesIO(pybase64.b64decode(embed, validate=True)), weights_only=True, map_location=torch.device("cpu"), ) assert isinstance(tensor, torch.Tensor) and tensor.dtype in ( torch.float32, torch.bfloat16, torch.float16, ) tensor = tensor.to_dense() ` Because of the missing checks, loading invalid prompt embedding tensors provided by the user can cause an out-of-bounds write in the call to to_dense` . Impact All users with access to this API are able to exploit this vulnerability. Unsafe deserialization of untrusted input can be abused to achieve DoS and potentially remote code execution (RCE) in the vLLM server process. This impacts deployments running vLLM as a server or any instance that deserializes untrusted/model-provided payloads. Fix https://github.com/vllm-project/vllm/pull/27204 Acknowledgements Finder: AXION Security Research Team (Omri Fainaro, Bary Levy): discovery and coordinated disclosure.

OWASP A03OWASP A08LLM01 · Prompt InjectionLLM05 · Supply Chain
Get guardrail →

LangChain Vulnerable to Template Injection via Attribute Access in Prompt Templates

Context A template injection vulnerability exists in LangChain's prompt template system that allows attackers to access Python object internals through template syntax. This vulnerability affects applications that accept untrusted template strings (not just template variables) in ChatPromptTemplate and related prompt template classes. Templates allow attribute access (.) and indexing ([]) but not method invocation (()). The combination of attribute access and indexing may enable exploitation depending on which objects are passed to templates. When template variables are simple strings (the common case), the impact is limited. However, when using MessagesPlaceholder with chat message objects, attackers can traverse through object attributes and dictionary lookups (e.g., __globals__) to reach sensitive data such as environment variables. The vulnerability specifically requires that applications accept template strings (the structure) from untrusted sources, not just template variables (the data). Most applications either do not use templates or else use hardcoded templates and are not vulnerable. Affected Components langchain-core package Template formats: F-string templates (template_format="f-string") - Vulnerability fixed Mustache templates (template_format="mustache") - Defensive hardening Jinja2 templates (template_format="jinja2") - Defensive hardening Impact Attackers who can control template strings (not just template variables) can: Access Python object attributes and internal properties via attribute traversal Extract sensitive information from object internals (e.g., __class__, __globals__) Potentially escalate to more severe attacks depending on the objects passed to templates Attack Vectors 1. F-string Template Injection Before Fix: ``python from langchain_core.prompts import ChatPromptTemplate malicious_template = ChatPromptTemplate.from_messages( [("human", "{msg.__class__.__name__}")], template_format="f-string" ) Note that this requires passing a placeholder variable for "msg.__class__.__name__". result = malicious_template.invoke({"msg": "foo", "msg.__class__.__name__": "safe_placeholder"}) Previously returned >>> result.messages[0].content >>> 'str' ` 2. Mustache Template Injection Before Fix: `python from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage msg = HumanMessage("Hello") Attacker controls the template string malicious_template = ChatPromptTemplate.from_messages( [("human", "{{question.__class__.__name__}}")], template_format="mustache" ) result = malicious_template.invoke({"question": msg}) Previously returned: "HumanMessage" (getattr() exposed internals) ` 3. Jinja2 Template Injection Before Fix: `python from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage msg = HumanMessage("Hello") Attacker controls the template string malicious_template = ChatPromptTemplate.from_messages( [("human", "{{question.parse_raw}}")], template_format="jinja2" ) result = malicious_template.invoke({"question": msg}) Could access non-dunder attributes/methods on objects ` Root Cause 1. F-string templates: The implementation used Python's string.Formatter().parse() to extract variable names from template strings. This method returns the complete field expression, including attribute access syntax: `python from string import Formatter template = "{msg.__class__} and {x}" print([var_name for (_, var_name, _, _) in Formatter().parse(template)]) # Returns: ['msg.__class__', 'x'] ` The extracted names were not validated to ensure they were simple identifiers. As a result, template strings containing attribute traversal and indexing expressions (e.g., {obj.__class__.__name__} or {obj.method.__globals__[os]}) were accepted and subsequently evaluated during formatting. While f-string templates do not support method calls with (), they do support [] indexing, which could allow traversal through dictionaries like __globals__ to reach sensitive objects. 2. Mustache templates: By design, used getattr() as a fallback to support accessing attributes on objects (e.g., {{user.name}} on a User object). However, we decided to restrict this to simpler primitives that subclass dict, list, and tuple types as defensive hardening, since untrusted templates could exploit attribute access to reach internal properties like class on arbitrary objects 3. Jinja2 templates: Jinja2's default SandboxedEnvironment blocks dunder attributes (e.g., __class__) but permits access to other attributes and methods on objects. While Jinja2 templates in LangChain are typically used with trusted template strings, as a defense-in-depth measure, we've restricted the environment to block all attribute and method access on objects passed to templates. Who Is Affected? High Risk Scenarios You are affected if your application: Accepts template strings from untrusted sources (user input, external APIs, databases) Dynamically constructs prompt templates based on user-provided patterns Allows users to customize or create prompt templates Example vulnerable code: `python User controls the template string itself user_template_string = request.json.get("template") # DANGEROUS prompt = ChatPromptTemplate.from_messages( [("human", user_template_string)], template_format="mustache" ) result = prompt.invoke({"data": sensitive_object}) ` Low/No Risk Scenarios You are NOT affected if: Template strings are hardcoded in your application code Template strings come only from trusted, controlled sources Users can only provide values for template variables, not the template structure itself Example safe code: `python Template is hardcoded - users only control variables prompt = ChatPromptTemplate.from_messages( [("human", "User question: {question}")], # SAFE template_format="f-string" ) User input only fills the 'question' variable result = prompt.invoke({"question": user_input}) ` The Fix F-string Templates F-string templates had a clear vulnerability where attribute access syntax was exploitable. We've added strict validation to prevent this: Added validation to enforce that variable names must be valid Python identifiers Rejects syntax like {obj.attr}, {obj[0]}, or {obj.__class__} Only allows simple variable names: {variable_name} `python After fix - these are rejected at template creation time ChatPromptTemplate.from_messages( [("human", "{msg.__class__}")], # ValueError: Invalid variable name template_format="f-string" ) ` Mustache Templates (Defensive Hardening) As defensive hardening, we've restricted what Mustache templates support to reduce the attack surface: Replaced getattr() fallback with strict type checking Only allows traversal into dict, list, and tuple types Blocks attribute access on arbitrary Python objects `python After hardening - attribute access returns empty string prompt = ChatPromptTemplate.from_messages( [("human", "{{msg.__class__}}")], template_format="mustache" ) result = prompt.invoke({"msg": HumanMessage("test")}) Returns: "" (access blocked) ` Jinja2 Templates (Defensive Hardening) As defensive hardening, we've significantly restricted Jinja2 template capabilities: Introduced _RestrictedSandboxedEnvironment that blocks ALL attribute/method access Only allows simple variable lookups from the context dictionary Raises SecurityError on any attribute access attempt `python After hardening - all attribute access is blocked prompt = ChatPromptTemplate.from_messages( [("human", "{{msg.content}}")], template_format="jinja2" ) Raises SecurityError: Access to attributes is not allowed ` Important Recommendation: Due to the expressiveness of Jinja2 and the difficulty of fully sandboxing it, we recommend reserving Jinja2 templates for trusted sources only. If you need to accept template strings from untrusted users, use f-string or mustache templates with the new restrictions instead. While we've hardened the Jinja2 implementation, the nature of templating engines makes comprehensive sandboxing challenging. The safest approach is to only use Jinja2 templates when you control the template source. Important Reminder: Many applications do not need prompt templates. Templates are useful for variable substitution and dynamic logic (if statements, loops, conditionals). However, if you're building a chatbot or conversational application, you can often work directly with message objects (e.g., HumanMessage, AIMessage, ToolMessage) without templates. Direct message construction avoids template-related security concerns entirely. Remediation Immediate Actions 1. Audit your code for any locations where template strings come from untrusted sources 2. Update to the patched version of langchain-core 3. Review template usage to ensure separation between template structure and user data Best Practices Consider if you need templates at all - Many applications can work directly with message objects (HumanMessage, AIMessage, etc.) without templates## Context A template injection vulnerability exists in LangChain's prompt template system that allows attackers to access Python object internals through template syntax. This vulnerability affects applications that accept untrusted template strings (not just template variables) in ChatPromptTemplate and related prompt template classes. Templates allow attribute access (.) and indexing ([]) but not method invocation (()). The combination of attribute access and indexing may enable exploitation depending on which objects are passed to templates. When template variables are simple strings (the common case), the impact is limited. However, when using MessagesPlaceholder with chat message objects, attackers can traverse through object attributes and dictionary lookups (e.g., __globals__) to reach sensitive data such as environment variables. The vulnerability specifically requires that applications accept template strings (the structure) from untrusted sources, not just template variables (the data). Most applications either do not use templates or else use hardcoded templates and are not vulnerable. Affected Components langchain-core package Template formats: F-string templates (template_format="f-string") - Vulnerability fixed Mustache templates (template_format="mustache") - Defensive hardening Jinja2 templates (template_format="jinja2") - Defensive hardening Impact Attackers who can control template strings (not just template variables) can: Access Python object attributes and internal properties via attribute traversal Extract sensitive information from object internals (e.g., __class__, __globals__) Potentially escalate to more severe attacks depending on the objects passed to templates Attack Vectors 1. F-string Template Injection Before Fix: `python from langchain_core.prompts import ChatPromptTemplate malicious_template = ChatPromptTemplate.from_messages( [("human", "{msg.__class__.__name__}")], template_format="f-string" ) Note that this requires passing a placeholder variable for "msg.__class__.__name__". result = malicious_template.invoke({"msg": "foo", "msg.__class__.__name__": "safe_placeholder"}) Previously returned >>> result.messages[0].content >>> 'str' ` 2. Mustache Template Injection Before Fix: `python from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage msg = HumanMessage("Hello") Attacker controls the template string malicious_template = ChatPromptTemplate.from_messages( [("human", "{{question.__class__.__name__}}")], template_format="mustache" ) result = malicious_template.invoke({"question": msg}) Previously returned: "HumanMessage" (getattr() exposed internals) ` 3. Jinja2 Template Injection Before Fix: `python from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import HumanMessage msg = HumanMessage("Hello") Attacker controls the template string malicious_template = ChatPromptTemplate.from_messages( [("human", "{{question.parse_raw}}")], template_format="jinja2" ) result = malicious_template.invoke({"question": msg}) Could access non-dunder attributes/methods on objects ` Root Cause 1. F-string templates: The implementation used Python's string.Formatter().parse() to extract variable names from template strings. This method returns the complete field expression, including attribute access syntax: `python from string import Formatter template = "{msg.__class__} and {x}" print([var_name for (_, var_name, _, _) in Formatter().parse(template)]) # Returns: ['msg.__class__', 'x'] ` The extracted names were not validated to ensure they were simple identifiers. As a result, template strings containing attribute traversal and indexing expressions (e.g., {obj.__class__.__name__} or {obj.method.__globals__[os]}) were accepted and subsequently evaluated during formatting. While f-string templates do not support method calls with (), they do support [] indexing, which could allow traversal through dictionaries like __globals__ to reach sensitive objects. 2. Mustache templates: By design, used getattr() as a fallback to support accessing attributes on objects (e.g., {{user.name}} on a User object). However, we decided to restrict this to simpler primitives that subclass dict, list, and tuple types as defensive hardening, since untrusted templates could exploit attribute access to reach internal properties like class on arbitrary objects 3. Jinja2 templates: Jinja2's default SandboxedEnvironment blocks dunder attributes (e.g., __class__) but permits access to other attributes and methods on objects. While Jinja2 templates in LangChain are typically used with trusted template strings, as a defense-in-depth measure, we've restricted the environment to block all attribute and method access on objects passed to templates. Who Is Affected? High Risk Scenarios You are affected if your application: Accepts template strings from untrusted sources (user input, external APIs, databases) Dynamically constructs prompt templates based on user-provided patterns Allows users to customize or create prompt templates Example vulnerable code: `python User controls the template string itself user_template_string = request.json.get("template") # DANGEROUS prompt = ChatPromptTemplate.from_messages( [("human", user_template_string)], template_format="mustache" ) result = prompt.invoke({"data": sensitive_object}) ` Low/No Risk Scenarios You are NOT affected if: Template strings are hardcoded in your application code Template strings come only from trusted, controlled sources Users can only provide values for template variables, not the template structure itself Example safe code: `python Template is hardcoded - users only control variables prompt = ChatPromptTemplate.from_messages( [("human", "User question: {question}")], # SAFE template_format="f-string" ) User input only fills the 'question' variable result = prompt.invoke({"question": user_input}) ` The Fix F-string Templates F-string templates had a clear vulnerability where attribute access syntax was exploitable. We've added strict validation to prevent this: Added validation to enforce that variable names must be valid Python identifiers Rejects syntax like {obj.attr}, {obj[0]}, or {obj.__class__} Only allows simple variable names: {variable_name} `python After fix - these are rejected at template creation time ChatPromptTemplate.from_messages( [("human", "{msg.__class__}")], # ValueError: Invalid variable name template_format="f-string" ) ` Mustache Templates (Defensive Hardening) As defensive hardening, we've restricted what Mustache templates support to reduce the attack surface: Replaced getattr() fallback with strict type checking Only allows traversal into dict, list, and tuple types Blocks attribute access on arbitrary Python objects `python After hardening - attribute access returns empty string prompt = ChatPromptTemplate.from_messages( [("human", "{{msg.__class__}}")], template_format="mustache" ) result = prompt.invoke({"msg": HumanMessage("test")}) Returns: "" (access blocked) ` Jinja2 Templates (Defensive Hardening) As defensive hardening, we've significantly restricted Jinja2 template capabilities: Introduced _RestrictedSandboxedEnvironment that blocks ALL attribute/method access Only allows simple variable lookups from the context dictionary Raises SecurityError on any attribute access attempt `python After hardening - all attribute access is blocked prompt = ChatPromptTemplate.from_messages( [("human", "{{msg.content}}")], template_format="jinja2" ) Raises SecurityError: Access to attributes is not allowed ` Important Recommendation: Due to the expressiveness of Jinja2 and the difficulty of fully sandboxing it, we recommend reserving Jinja2 templates for trusted sources only. If you need to accept template strings from untrusted users, use f-string or mustache templates with the new restrictions instead. While we've hardened the Jinja2 implementation, the nature of templating engines makes comprehensive sandboxing challenging. The safest approach is to only use Jinja2 templates when you control the template source. Important Reminder: Many applications do not need prompt templates. Templates are useful for variable substitution and dynamic logic (if statements, loops, conditionals). However, if you're building a chatbot or conversational application, you can often work directly with message objects (e.g., HumanMessage, AIMessage, ToolMessage) without templates. Direct message construction avoids template-related security concerns entirely. Remediation Immediate Actions 1. Audit your code for any locations where template strings come from untrusted sources 2. Update to the patched version of langchain-core 3. Review template usage to ensure separation between template structure and user data Best Practices Consider if you need templates at all - Many applications can work directly with message objects (HumanMessage, AIMessage, etc.) without templates Reserve Jinja2 for trusted sources - Only use Jinja2 templates when you fully control the template content Update: Jinja2 Restrictions Reverted The Jinja2 hardening introduced in the initial patch has been reverted as of langchain-core` 1.1.3. The restriction was not addressing a direct vulnerability but was part of broader defensive hardening. In practice, it significantly limited legitimate Jinja2 usage and broke existing templates. Since Jinja2 is intended to be used only with trusted template sources, the original behavior has been restored. Users should continue to avoid accepting untrusted template strings when using Jinja2, but no security issue exists with trusted templates.

Showing 6180 of 299 threats