High

LangChain load_prompt Deserialization Code Execution

This detects a two-step pattern tied to an old LangChain vulnerability (CVE-2023-36281): a Python process reads a prompt, chain, or agent configuration file, and shortly after, that same process launches a shell command, network tool, or Python one-liner. That sequence is what code execution via a poisoned prompt/chain file looks like from the outside.

How the attack works

An attacker crafts a malicious prompt or chain specification file (JSON or YAML) whose template content abuses LangChain's `load_prompt`/`load_chain` deserialization to reach Python internals like `__subclasses__` or `__globals__`. When the application loads this file, the template is evaluated and arbitrary code runs inside the interpreter. The rule cannot see the deserialization itself; instead it watches for the outer signature: a Python process opens a file whose path looks like a prompt/template/chain/agent artifact, and within 5 minutes the same process (or a child it spawned) starts a shell, network utility, encoder, or `python -c` command. The two events are tied together by session and process lineage, not just by timing.

Netzilo detection

Netzilo reports this behaviour when it is observed.

Signature ID
7f3c1a2e-9b4d-4f61-8c2a-5d0e6b7a1c93
Severity
High
Classification

Why it matters

If exploited, an attacker gets arbitrary code execution inside the application's Python process, which can lead to data theft, lateral movement, or full host compromise via a single malicious prompt or chain file - a supply-chain-style entry point since the file itself is the attack payload.

What you can do

  • Upgrade LangChain past the version affected by CVE-2023-36281 and avoid loading prompt/chain files from untrusted or user-supplied sources.
  • Treat prompt/chain JSON and YAML files as executable content: validate their origin, restrict write access, and avoid dynamic template evaluation on untrusted input.
  • Review any case where a Python agent process reads a prompt/template/chain file and then spawns a shell or network command shortly after, since this is the exact observable behavior.
  • Be aware this pattern also occurs in legitimate agent frameworks (shell tools, CI test fixtures, notebooks that pip install after loading prompts) - confirm intent before treating a match as an incident.

Known benign look-alikes

  • A LangChain / LlamaIndex application that legitimately loads a prompt or chain JSON from disk and then, in the same session, uses a Bash/Terminal tool - agent frameworks routinely spawn `sh -c` for their shell tool.
  • CI and pytest runs that read prompt fixtures (`tests/**/prompt*.json`) and then invoke shell helpers, `chmod +x`, or `curl` for artifact upload.
  • Notebook / Streamlit / Chainlit dev loops where the kernel reads a `*_prompt.json` and the same kernel later shells out for `pip install`.
  • Non-LangChain configuration files that happen to carry a `agent`, `chain` or `template` token in the filename (e.g. `agent.json` for an unrelated service) read by a python process that later runs `curl`.
  • Deployment scripts that render a Jinja/`template.yaml` and then run a packaging shell command.

References

Related threats