A LangChain application is a pipeline that moves data between a language model, your code, external resources, and stored state. Security in that pipeline reduces to one principle.

Model output and retrieved content are untrusted input. Treat all of it as hostile at the point where it reaches a sink.

Anything the model emits, tool calls, arguments, generated queries, generated code, and anything you retrieve, documents, web pages, vector-store metadata, cached state, can be attacker-influenced, because a real attacker can plant a document, poison a page, or write to a shared store. This is not pessimism. It is the empirical finding of the benchmark literature: AgentDojo (Debenedetti et al., NeurIPS 2024) and InjecAgent (Zhan et al., 2024) both show tool-using agents are susceptible to indirect prompt injection at meaningful rates while proposed defenses degrade utility. So this model does not try to harden the model. It bounds what a steered model can reach.

How the labels work

Fixed is a published CVE with a release that patches it. By design is a capability that requires deployment controls, not a framework patch. Configuration risk is unsafe only when an application enables or configures it insecurely. This edition describes published vulnerabilities, known vulnerability classes, and design considerations. It introduces no new vulnerabilities beyond those already publicly disclosed; it summarizes the published record and generalizes from known classes. If you find a new issue in these components, report it through the LangChain Open Source VDP rather than publishing it.

Read this first: package maintenance status

The cited CVEs are, with few exceptions, already patched; their value here is the vulnerability class, which persists as long as the component does. But the components do not all persist. As of August 2026, LangChain has restructured, and a large part of this catalog lives in packages that are now archived and no longer maintained.

PackageStatus (Aug 2026)Where it appears
langchain-coreActive (1.6.0)Templates, deserialization, parsers
langchain (v1)ActiveShell and code middleware
langgraphActiveCheckpoints, store, cache
langchain-text-splittersActiveSplitters
Partner packagesActiveMultimodal SSRF
langsmith SDKActiveTracing
langchain-communityArchived / sunsetLoaders, stores, requests, caches
langchain-experimentalArchivedCode execution
langserveArchivedConfig-loading network exposure
Implications of archived packages

A vulnerability in an archived package will not be fixed by the vendor; the only mitigation is to stop using it, or to vendor and patch it yourself. LangChain moved integrations out of the monolithic langchain-community into standalone partner packages, so the current maintained integration surface is those partner packages. If you are on langchain-community, treat it as an unmaintained dependency and plan migration; its CVEs are frozen at their last-released state.

The core model: three trust boundaries

LangChain gives you capable, general components; scoping and sandboxing them is your job. The framework running developer-supplied code, configuration, or integrations as designed is expected behavior, not a vulnerability. What the framework does owe you is that its own guards are applied consistently, and most of the CVEs below are cases where one was not. Three trust boundaries carry almost every concrete issue.

BoundaryWhat crosses itWhere it lands
Untrusted data to sinkingested or retrieved contenta fetch (SSRF), a query (injection), a parser (XXE, deserialization), a file path (traversal), a template (injection)
Model to actionthe tool name, arguments, or query the model choosesPydantic constrains argument shape, not intent; a capable tool plus a steerable model is that capability in an attacker's hands
Tenant to tenantshared cache, checkpoint, and memory statethroughput layers become an isolation boundary nobody designed as one

Deployment archetypes

Identify yours; it decides which of the catalog applies.

ArchetypeDominant risks
RAG ingestion / retrievalSSRF and XXE in loaders; query-language injection in the store; stored template injection via few-shot selection
Agent with toolsSSRF, SQLi, or code execution through tool arguments; generated-query injection; shell and code tools
Config / checkpoint loadingunsafe deserialization; path traversal in loaders; object reconstruction with attacker arguments
Multi-tenant servicecross-tenant reads and writes through shared checkpoint, cache, and memory backends

Attack-surface catalog

Each entry names the component, the attack, a real CVE or known class as evidence, and the mitigation. The primary boundary is noted per subsection.

Document loaders and text splitters

Untrusted data to sink.

SSRF. A loader fetches a URL you or your users supply, with no egress control. This is the oldest LangChain vulnerability class: the recursive URL crawler had an external-to-internal SSRF in 2023 (CVE-2023-46229), whose fix added a same-domain restriction, and WebResearchRetriever was separately fixed (CVE-2024-3095). Same-domain restrictions are defense in depth, not a guarantee: treat any loader that fetches a URL as a potential SSRF primitive regardless.

XXE. Community loaders parse XML with the standard library or unhardened lxml. One was fixed (CVE-2025-6984); outside XMLOutputParser, defusedxml is not used systematically across the XML-loader tree, so loaders remain exposed to external-entity and billion-laughs attacks.

Text splitters are part of this surface. langchain-text-splitters is not just string chunking: HTMLHeaderTextSplitter.split_text_from_url fetches a URL (SSRF, CVE-2026-41481) and the HTML and XML splitters parse untrusted markup (XXE, CVE-2025-6985).

Mitigations

Put loaders that fetch behind an egress proxy or a deny-by-default network policy; block link-local and private ranges (169.254.169.254, 127/8, 10/8, 172.16/12, 192.168/16, and IPv6 fc00::/7 and fe80::/10). The in-framework reference is langchain_core._security._transport.ssrf_safe_client, a resolve-then-pin client; even it needed a DNS-rebinding fix (CVE-2026-41488), so pair it with network egress control rather than trusting validation alone. Pin lxml >= 5 and prefer defusedxml. Validate that file and archive extraction targets stay within root.

Vector and graph stores

Untrusted data to sink.

Metadata-filter and ingestion injection. Community stores vary widely in how they build queries. Some build the metadata-filter WHERE clause, or the ingestion INSERT, by string-splicing filter keys, values, or document-metadata identifiers into SQL, Cypher, Gremlin, or a store-specific DSL. This class is established publicly for similar architectures in other frameworks (the LlamaIndex metadata-filter injection CVEs); in LangChain, CVE-2024-8309 is a related instance, though it covers generated Cypher from model output rather than a metadata filter specifically. Graph stores whose sink is Cypher or Groovy-backed Gremlin raise the ceiling to code execution. The hardened reference is pgvector, which validates the key as an identifier and binds the value.

Mitigations

Prefer stores that parameterize (pgvector, singlestore, neo4j via UNWIND $data). Attacker-controlled document metadata at ingestion is a stored-injection vector even without a filter API. Self-check for a custom store: if its filter builder interpolates a value into a WHERE or Cypher clause with an f-string or .format (the shape f"... = '{value}'"), it is in the danger set. Constrain query-generating chains with a read-only role.

Tools and utilities

Model to action.

SSRF through the requests wrapper. RequestsToolkit gained an allow_dangerous_requests gate (CVE-2025-2828), but the underlying TextRequestsWrapper and consumers like LLMRequestsChain use it with no gate. This becomes attacker-reachable when an application passes a model-selected or retrieved URL to the wrapper; exploitability depends on your wiring.

SQL, Cypher, and command sinks. SQL utilities, the graph-QA chains (CVE-2024-8309), shell, and code tools execute model-chosen input by design. Multimodal image-token counting has had its own SSRF (CVE-2026-26013) and a DNS-rebinding TOCTOU bypass of the fix (CVE-2026-41488).

Deserialization from tool results. Tools that fetch and deserialize a remote resource (pickle, yaml, torch.load) inherit its trust. Community had a pickle CVE (CVE-2024-5998); the allow_dangerous_deserialization flag, which is an RCE toggle, now gates the known cases.

Mitigations

Give the model the least capable tool that works, with least-privilege credentials: read-only DB users, scoped API keys, an egress proxy. Never enable allow_dangerous_requests or allow_dangerous_deserialization for input you do not fully trust. For SQL and Cypher, prefer a read-only connection and a query allowlist over a general database tool.

Shell and code execution

Model to action.

The shell tool defaults to host access, by design. ShellToolMiddleware runs commands with HostExecutionPolicy by default, which is no sandbox. A prompt-injected agent gets a shell on the host. DockerExecutionPolicy and CodexSandboxExecutionPolicy exist and are opt-in. This is a capability, not a framework defect; the sandbox is yours.

Human-in-the-loop does not compose with a stateful shell. Per-command approval shows the reviewer a command string, not the session state (PATH, aliases, functions) an earlier command set. As shipped, the persistent shell session and the interrupt do not currently compose: the session is checkpoint-excluded and lost on interrupt (LangGraph issue #33684). Do not rely on per-command approval to bound a stateful shell.

Mitigations

If you expose a shell or code tool to anything a prompt-injected model can steer, run it under DockerExecutionPolicy with no network, or an equivalent sandbox, never the host default. Treat human approval of a shell command as advisory, not a boundary.

Prompt templates

Untrusted data to sink.

Template injection. If an untrusted template string, not just its variables, reaches a template, attribute and index access can reach object internals. This was patched for PromptTemplate and extended to DictPromptTemplate and ImagePromptTemplate (CVE-2025-65106, CVE-2026-40087). The general lesson: any template class that formats an untrusted string, and any path that re-interprets retrieved content as a template, is in this class.

The jinja2 nuance. LangChain's jinja2 formatter uses SandboxedEnvironment, which blocks dunder access, so jinja2 template injection is bounded to information disclosure, not remote code execution. The f-string formatter allows attribute and index access but not calls.

Mitigations

Never accept a template string from an untrusted source. Treat few-shot examples loaded from a datastore as untrusted template content, not inert data. Do not pass sensitive objects as template variables where an untrusted template could reference them.

Serialization and checkpoints

Untrusted data to sink, and tenant to tenant.

The load() and loads() system. LangChain reconstructs objects from a JSON format against an allowlist. Over-broad allowlists were narrowed (CVE-2026-44843), and free-form dicts carrying an lc key were revived as objects, enabling secret extraction, until fixed (CVE-2025-68664, the highest-severity item here). Even the narrowed allowlist reconstructs dozens of trusted classes with attacker-controlled constructor arguments, a bounded but real primitive.

Prompt loaders. load_prompt and its siblings read files from paths embedded in a deserialized config, and had traversal fixes (CVE-2026-34070, CVE-2024-28088). A related host file-read affected ImagePromptTemplate (CVE-2024-10940). File-search and config loaders had a path-confinement and symlink advisory (CVE-2026-55443).

LangGraph checkpoints. Checkpoint loading has had multiple deserialization RCEs: JSON-mode JsonPlusSerializer (CVE-2025-64439), BaseCache (CVE-2026-27794), and unsafe msgpack (CVE-2026-28277), plus SQL injection in the SQLite checkpointer (CVE-2025-67644, CVE-2025-64104) and namespace prefix-matching crossing segment boundaries (CVE-2026-71433). The recurring lesson: a checkpoint or store an untrusted party can write to is an untrusted deserialization source, and the fixes arrived in waves.

Mitigations

Never load(), load_prompt, or resume a LangGraph checkpoint from a source you do not control. In a multi-tenant service, a checkpoint, cache, or memory backend any tenant can write to is an untrusted source for every other tenant.

Output parsers and schema handling

Untrusted data to sink.

XMLOutputParser had an XML-entity-expansion CVE (CVE-2024-1455) and now defaults to defusedxml. Schema handling can be amplified: deeply nested or recursive schemas passed to function-schema conversion can expand into an algorithmic-complexity cost. Keep the defusedxml default; bound the size and recursion of any model- or tool-derived schema you convert, and cap the content pushed back into the context window.

Experimental and by-design code execution

PAL, PythonREPLTool, llm_bash, and the pandas, spark, and xorbits agents execute model-authored code by design (out of scope for the vendor; the package is archived). It is not a framework vulnerability; it is a capability you chose to grant. The same applies to agent harnesses that pre-declare host access. If you use these, the sandbox is entirely your responsibility.

Callbacks, tracing, and LangSmith

Data egress.

Callback and tracing handlers move prompts, tool input and output, and errors out of the process. If LangSmith tracing is enabled, that data leaves your trust boundary to a SaaS, and a leaked or over-scoped LangSmith API key exposes the traces. A prompt-hub pull deserializes a remote manifest (GHSA-3644), so a poisoned hub entry is untrusted input. The LangSmith SDK itself has a real CVE record: arbitrary server-side file read in TracingMiddleware (CVE-2026-59152), SSRF via tracing-header injection (CVE-2026-25528), and streaming token events that bypass output redaction (CVE-2026-41182). Treat trace destinations as a data-egress decision; scope and rotate LangSmith keys; treat hub-pulled prompts as untrusted content.

Multi-tenant and network posture

Shared state does not isolate tenants by existing. Checkpoint, cache, and memory implementations must bind tenant identity into authorization and storage-key design, then enforce it at the backend. Semantic caches make this concrete, and it is a well-studied class: semantic cache poisoning via embedding fuzzy-match collision is documented in the NDSS work "Cache Me, Catch You" and related research, which names GPTCache. LangChain's semantic caches are instances of it: RedisSemanticCache, CassandraSemanticCache, and AzureCosmosDBSemanticCache index only on a hash of the model config string, with no tenant field, and match on prompt-embedding similarity. On a shared backend one tenant can seed a poisoned entry that another tenant's different-but-similar prompt retrieves, controlling the victim's model output. To harden a shared semantic cache today, bind the tenant id into the index name or cache key, restrict caching to prompts safe to share, or do not share the cache across tenants.

Egress is a control point. A single egress proxy with a private-range denylist neutralizes most of the SSRF surface at once, more reliably than trusting each component's own guard.

Keep current. Fixes are often incomplete on the first pass. The image-token SSRF fix (CVE-2026-26013) was bypassed by DNS rebinding (CVE-2026-41488), and the template-injection fix (CVE-2025-65106) had to be extended to more classes (CVE-2026-40087). Pin versions and re-verify after upgrades.

The hardening checklist

Set these before shipping. Each maps to a section above.

  • Sandbox code and shell tools. Never ship ShellToolMiddleware on the default HostExecutionPolicy for steerable input; use DockerExecutionPolicy with no network.
  • Leave the dangerous flags off. allow_dangerous_requests, allow_dangerous_deserialization, and any allow_dangerous_code stay off unless input is fully trusted.
  • Do not load untrusted serialized data. No load(), load_prompt, chain config, or LangGraph checkpoint from a hub, request body, or shared store you do not control.
  • Do not accept untrusted template strings, including few-shot examples selected from a datastore.
  • Parameterize metadata filters and generated queries. Bind values, validate keys, constrain query-generating chains with a read-only role.
  • Control egress. A proxy with a private-range denylist in front of every fetch; prefer ssrf_safe_client.
  • Harden XML. Pin lxml >= 5; prefer defusedxml; keep the XMLOutputParser default.
  • Least privilege for tools. Read-only DB users, scoped API keys, per-tool credentials.
  • Partition shared state per tenant. Bind tenant identity into the storage key and authorize at the backend.
  • Bound resource use. Size and recursion limits on parsed and converted schemas; cap content pushed into the context window.
  • Scope tracing and keys. Decide whether prompts may leave your boundary; scope and rotate LangSmith keys.
  • Pin and patch. Track the advisories; re-verify after upgrades.

What LangChain does not protect you from

  • Prompt injection itself. The framework does not stop a model from being steered by its inputs; it is a security issue only when it is the delivery mechanism for reaching a vulnerable sink.
  • The intent of a tool call or generated query. Pydantic validates argument shapes, not whether the model should make the call.
  • Running model-authored code. PAL, PythonREPL, shell, and code tools execute by design. The sandbox is yours.
  • Untrusted templates and configs. Accepting a template string, chain config, or serialized object from an untrusted source is your decision and your risk.
  • The destination of a fetch. A loader or tool will fetch the URL it is given.
  • Cross-tenant isolation of shared throughput layers. Caches, checkpoints, and memory are not tenant-isolated unless you partition them.
  • Where your prompts and traces go. Tracing and callbacks are a data-egress decision you own.

A reusable procedure

Apply this to your own application.

  • Map where untrusted data enters. User messages, uploaded files, ingested documents, crawled URLs, retrieved store content and metadata, tool results, loaded configs and checkpoints, hub-pulled prompts. Everything the model emits counts as untrusted.
  • Enumerate your sinks. Every fetch, query, file open, parser, template render, deserialization, and subprocess, including the ones inside the LangChain components you use.
  • Trace each untrusted source to each sink. Where a path exists, you have a candidate. Find the guard, find the sink, report the paths that reach the sink without the guard.
  • Apply the guard at the boundary. Egress proxy for fetches, parameterization for queries, sandbox for code, allowlist for deserialization, no untrusted templates for renders, per-tenant keys for shared state.
  • Assume the fixes are incomplete. Check the patch covers the sibling you actually use. Several fixes here were bypassed or extended after release.
  • Prove it, do not assume it. Confirm a guard is reached through your real control flow, not just that it exists in the code.
Worked example: a helpdesk RAG agent with a SQL tool, multi-tenant

Untrusted data in: the user's chat message; a URL the user pastes for ingestion; documents in the shared vector store; the SQL tool's arguments (model-chosen, so attacker-influenced via injected content in a retrieved doc); the shared LLM cache. Sinks: a URL loader and HTMLHeaderTextSplitter.split_text_from_url, similarity_search(filter=...), SQLDatabase.run, the semantic cache. Trace: pasted URL to loader fetch is SSRF to the VPC metadata service; a retrieved doc steers the model, so the SQL tool argument is an injection if the store or tool splices values, and the RAG doc is now the injection payload; tenant A's poisoned cache entry is served to tenant B's similar prompt. Guards: egress proxy with a private-range denylist in front of every fetch; lxml >= 5 and defusedxml; a read-only SQL role and a store that binds filter values; a tenant id in the cache key. Then prove the proxy is actually in the fetch path, not just configured.

A hardened LangChain is assembled, not downloaded

As of the reviewed releases, there is no maintained, security-focused fork or official distribution of the Python LangChain libraries that systematically changes these framework defaults. What exists hardens the layers around the framework, not the framework itself: FIPS and Wolfi container images harden crypto compliance and the base-OS CVE surface; code-execution sandboxes (LangSmith Sandboxes, Modal, E2B, Northflank, Fly.io) provide OS-level isolation for the code-execution sink only; third-party checklists cover configuration, not code. The sandbox offerings address exactly one boundary, the model-to-action code-execution sink; none touch the untrusted-data-to-sink or tenant-to-tenant boundaries where most of this catalog lives. LangChain's own first-party sandbox attempt, langchain-sandbox, is archived and disavowed for production.

A hardened LangChain is assembled, not downloaded.

It is patched version pins, plus a hardened base image, plus an external sandbox for code tools, plus the egress proxy, parameterization, gated deserialization, and per-tenant partitioning from the checklist above.

Method and prior work

This model was built in four steps. First, enumerate the LangChain family's published advisories from the GitHub Security Advisory database across 17 packages (roughly 90 advisories as of August 2026), with credits checked per advisory. Second, first-party source review of the pinned releases, tracing untrusted-data and model-output paths to each sink using the set-difference procedure above. Third, verify each cited behavior against the pinned commit and, where feasible, an offline proof of concept. Fourth, check every observation against the published record and the prior literature before claiming novelty.

The literature this sits in: AgentDojo and InjecAgent anchor the steerability premise; surveys by Gan et al. and He et al. build agent-threat taxonomies; Unit 42, Cyera, Upwind, Microsoft, the Cloud Security Alliance, and Flatt Security cover LangChain-specific vulnerabilities; OWASP's Top 10 for LLM Applications and for Agentic Applications are the canonical application-level taxonomies. Where this adds: component-to-CVE mapping at the reviewed-version level, the deployer checklist, and the trust-boundary framing. The reviewed releases were langchain-core 1.5.6, langchain 1.3.15, langchain-community 0.4.2, and langgraph 1.2.11; behaviors change between releases, so verify against your pinned versions.

Appendix: cited CVEs

Severity labels are from the published CVSS vectors. Verify the fix version against your package before relying on it. Full set: the GitHub Security Advisory database and OSV.

CVEPackageClassSeverityFixed in
CVE-2025-68664langchain-corelc-key serialization injection, secret extractionCritical0.3.81 / 1.2.5
CVE-2026-44843langchain-coreover-broad load() allowlistHigh0.3.85 / 1.3.3
CVE-2026-34070langchain-coreload_prompt path traversalHigh1.2.22
CVE-2025-2828langchain-communityRequestsToolkit SSRFHighsee advisory
CVE-2025-65106langchain-corePromptTemplate attribute-access injectionHigh0.3.80 / 1.0.7
CVE-2025-64439langgraph-checkpointRCE in JSON-mode JsonPlusSerializerHigh3.0.0
CVE-2025-67644langgraph-checkpoint-sqliteSQLite checkpointer SQL injectionHigh3.0.1
CVE-2025-6985langchain-text-splittersHTML/XML splitter XXEHighsee advisory
CVE-2023-44467langchain-experimentalPALChain prompt-injection code executionHigh0.0.306
CVE-2026-28277langgraph-checkpointunsafe msgpack deserializationMedium1.0.10
CVE-2026-27794langgraph-checkpointBaseCache deserialization RCEMediumsee advisory
CVE-2026-55443langchainfile-search / loader path confinement, sandbox escapeMedium1.3.9 / 1.4.6
CVE-2026-59152langsmithTracingMiddleware arbitrary file readMediumsee advisory
CVE-2024-1455langchain-coreXMLOutputParser billion-laughs DoSMediumsee advisory
CVE-2024-5998langchain-communitypickle deserializationMediumsee advisory
CVE-2025-6984langchain-communityloader XXEMediumsee advisory
CVE-2024-10940langchain-coreImagePromptTemplate host file-readMediumsee advisory
CVE-2024-3095langchainWebResearchRetriever SSRFMediumsee advisory
CVE-2023-46229langchainrecursive URL loader SSRF (foundational)Medium0.0.317
CVE-2026-41481langchain-text-splitterssplit_text_from_url SSRFMediumsee advisory
CVE-2024-8309langchain-communityGraphCypherQAChain prompt-injection-to-CypherLow0.2.19
CVE-2026-40087langchain-coreincomplete f-string validationLow0.3.84 / 1.2.28
CVE-2026-41488langchain-openaiimage-token SSRF DNS-rebinding bypassLow1.1.14

Prepared by Hedgerow from first-party source review and the published CVE record for the LangChain package family, August 2026. Independent of LangChain and its maintainers. This edition omits undisclosed source-review findings, which are withheld pending coordinated disclosure.