GitHub Security Advisory: GHSA-qh6h-p6c9-ff54
Package: langchain-core (PIP)
Severity: HIGH (CVSS 7.5)
CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable versions: < 1.2.22
Patched in: 1.2.22

Summary: LangChain Core has Path Traversal vulnerabilites in legacy `load_prompt` functions

Details:
## Summary

Multiple functions in `langchain_core.prompts.loading` read files from paths embedded in deserialized config dicts without validating against directory traversal or absolute path injection. When an application passes user-influenced prompt configurations to `load_prompt()` or `load_prompt_from_config()`, an attacker can read arbitrary files on the host filesystem, constrained only by file-extension checks (`.txt` for templates, `.json`/`.yaml` for examples).

**Note:** The affected functions (`load_prompt`, `load_prompt_from_config`, and the `.save()` method on prompt classes) are undocumented legacy APIs. They are superseded by the `dumpd`/`dumps`/`load`/`loads` serialization APIs in `langchain_core.load`, which do not perform filesystem reads and use an allowlist-based security model. As part of this fix, the legacy APIs have been formally deprecated and will be removed in 2.0.0.

## Affected component

**Package:** `langchain-core`
**File:** `langchain_core/prompts/loading.py`
**Affected functions:** `_load_template()`, `_load_examples()`, `_load_few_shot_prompt()`

## Severity

**High** 

The score reflects the file-extension constraints that limit which files can be read.

## Vulnerable code paths

| Config key | Loaded by | Readable extensions |
|---|---|---|
| `template_path`, `suffix_path`, `prefix_path` | `_load_template()` | `.txt` |
| `examples` (when string) | `_load_examples()` | `.json`, `.yaml`, `.yml` |
| `example_prompt_path` | `_load_few_shot_prompt()` | `.json`, `.yaml`, `.yml` |

None of these code paths validated the supplied path against absolute path injection or `..` traversal sequences before reading from disk.

## Impact

An attacker who controls or influences the prompt configuration dict can read files outside the intended directory:

- **`.txt` files:** cloud-mounted secrets (`/mnt/secrets/api_key.txt`), `requirements.txt`, internal system prompts
- **`.json`/`.yaml` files:** cloud credentials (`~/.docker/config.json`, `~/.azure/accessTokens.json`), Kubernetes manifests, CI/CD configs, application settings

This is exploitable in applications that accept prompt configs from untrusted sources, including low-code AI builders and API wrappers that expose `load_prompt_from_config()`.

## Proof of concept

```python
from langchain_core.prompts.loading import load_prompt_from_config

# Reads /tmp/secret.txt via absolute path injection
config = {
    "_type": "prompt",
    "template_path": "/tmp/secret.txt",
    "input_variables": [],
}
prompt = load_prompt_from_config(config)
print(prompt.template)  # file contents disclosed

# Reads ../../etc/secret.txt via directory traversal
config = {
    "_type": "prompt",
    "template_path": "../../etc/secret.txt",
    "input_variables": [],
}
prompt = load_prompt_from_config(config)

# Reads arbitrary .json via few-shot examples
config = {
    "_type": "few_shot",
    "examples": "../../../../.docker/config.json",
    "example_prompt": {
        "_type": "prompt",