langchain - ✅(Solved) Fix Symlink-Based File Read via Relative Path in LangChain Core Prompt Loader [1 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langchain-ai/langchain#36854Fetched 2026-04-18 05:51:51
View on GitHub
Comments
2
Participants
2
Timeline
12
Reactions
0
Timeline (top)
labeled ×3mentioned ×3subscribed ×3commented ×2

Report.pdf

How i find this bug.pdf

How hackers can use this bug.pdf

I am using langchain-core to load a prompt from a relative file path via template_path.

I expect that path validation ensures the application loads only the intended file. In particular, I expect the system to validate the resolved file path, not just the user-provided string.

Instead, the loader accepts a relative path and follows symbolic links without validating the final resolved target. By modifying the symlink target, it is possible to change which file is loaded while keeping the input path unchanged.

This behavior can lead to unintended file access if an attacker is able to influence filesystem state (e.g., by modifying or replacing symlinks in writable directories). The application may assume it is loading a safe file, while in reality it is loading a different file.

Error Message

Error Message and Stack Trace (if applicable)

Root Cause

Report.pdf

How i find this bug.pdf

How hackers can use this bug.pdf

I am using langchain-core to load a prompt from a relative file path via template_path.

I expect that path validation ensures the application loads only the intended file. In particular, I expect the system to validate the resolved file path, not just the user-provided string.

Instead, the loader accepts a relative path and follows symbolic links without validating the final resolved target. By modifying the symlink target, it is possible to change which file is loaded while keeping the input path unchanged.

This behavior can lead to unintended file access if an attacker is able to influence filesystem state (e.g., by modifying or replacing symlinks in writable directories). The application may assume it is loading a safe file, while in reality it is loading a different file.

Fix Action

Fix / Workaround

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

jsonpatch: 1.33

PR fix notes

PR #36860: fix(core): prevent symlink path escape in prompt loaders (#36854)

Description (problem / solution / changelog)

Fixes #36854

Prevent symlink-based path escape in deprecated prompt loaders by validating resolved paths for template_path and examples when allow_dangerous_paths=False.

Added regression tests Existing tests pass.

Verification: Ran targeted tests in libs/core/tests/unit_tests/prompts/test_loading.py. Added tests for symlink escape scenarios. All tests in that file pass locally.

LinkedIn: https://linkedin.com/in/akshayatam

Changed files

  • libs/core/langchain_core/prompts/loading.py (modified, +29/-7)
  • libs/core/tests/unit_tests/prompts/test_loading.py (modified, +99/-0)

Code Example

from langchain_core.prompts.loading import load_prompt_from_config
import os

# Clean environment
for f in ["normal.txt", "secret.txt", "link.txt"]:
    if os.path.exists(f):
        os.remove(f)

# Step 1: create files
with open("normal.txt", "w") as f:
    f.write("NORMAL_FILE")

with open("secret.txt", "w") as f:
    f.write("SECRET_DATA")

# Step 2: create symlink pointing to normal file
os.symlink("normal.txt", "link.txt")

# Step 3: load config using relative path
cfg = {
    "_type": "prompt",
    "template_path": "link.txt",
    "input_variables": []
}

obj = load_prompt_from_config(cfg)
print("First load:", obj.template.strip())

# Step 4: change symlink target to another file
os.remove("link.txt")
os.symlink("secret.txt", "link.txt")

# Step 5: load again using same path
obj = load_prompt_from_config(cfg)
print("Second load:", obj.template.strip())

---

First load: NORMAL_FILE
Second load: SECRET_DATA
RAW_BUFFERClick to expand / collapse

Submission checklist

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package (Required)

  • langchain
  • langchain-openai
  • langchain-anthropic
  • langchain-classic
  • langchain-core
  • langchain-model-profiles
  • langchain-tests
  • langchain-text-splitters
  • langchain-chroma
  • langchain-deepseek
  • langchain-exa
  • langchain-fireworks
  • langchain-groq
  • langchain-huggingface
  • langchain-mistralai
  • langchain-nomic
  • langchain-ollama
  • langchain-openrouter
  • langchain-perplexity
  • langchain-qdrant
  • langchain-xai
  • Other / not sure / general

Related Issues / PRs

No response

Reproduction Steps / Example Code (Python)

from langchain_core.prompts.loading import load_prompt_from_config
import os

# Clean environment
for f in ["normal.txt", "secret.txt", "link.txt"]:
    if os.path.exists(f):
        os.remove(f)

# Step 1: create files
with open("normal.txt", "w") as f:
    f.write("NORMAL_FILE")

with open("secret.txt", "w") as f:
    f.write("SECRET_DATA")

# Step 2: create symlink pointing to normal file
os.symlink("normal.txt", "link.txt")

# Step 3: load config using relative path
cfg = {
    "_type": "prompt",
    "template_path": "link.txt",
    "input_variables": []
}

obj = load_prompt_from_config(cfg)
print("First load:", obj.template.strip())

# Step 4: change symlink target to another file
os.remove("link.txt")
os.symlink("secret.txt", "link.txt")

# Step 5: load again using same path
obj = load_prompt_from_config(cfg)
print("Second load:", obj.template.strip())

Error Message and Stack Trace (if applicable)

First load: NORMAL_FILE
Second load: SECRET_DATA

Description

Report.pdf

How i find this bug.pdf

How hackers can use this bug.pdf

I am using langchain-core to load a prompt from a relative file path via template_path.

I expect that path validation ensures the application loads only the intended file. In particular, I expect the system to validate the resolved file path, not just the user-provided string.

Instead, the loader accepts a relative path and follows symbolic links without validating the final resolved target. By modifying the symlink target, it is possible to change which file is loaded while keeping the input path unchanged.

This behavior can lead to unintended file access if an attacker is able to influence filesystem state (e.g., by modifying or replacing symlinks in writable directories). The application may assume it is loading a safe file, while in reality it is loading a different file.

System Info

Based on the image provided, here is the text extracted from the terminal output:

System Information OS: Linux

OS Version: #1 SMP PREEMPT_DYNAMIC Kali 6.18.12-1kali1 (2026-02-25)

Python Version: 3.13.12 (main, Feb 4 2026, 15:06:39) [GCC 15.2.0]

Package Information langchain_core: 1.2.31

langsmith: 0.7.32

Optional packages not installed deepagents

deepagents-cli

Other Dependencies httpx: 0.28.1

jsonpatch: 1.33

orjson: 3.11.8

packaging: 26.1

pydantic: 2.13.2

pyyaml: 6.0.3

requests: 2.33.1

requests-toolbelt: 1.0.0

tenacity: 9.1.4

typing-extensions: 4.15.0

uuid-utils: 0.14.1

xxhash: 3.6.0

zstandard: 0.25.0

extent analysis

TL;DR

The issue can be mitigated by resolving the file path and validating the target before loading the prompt.

Guidance

  • Validate the resolved file path to ensure it matches the intended file, rather than just the user-provided string.
  • Consider using os.path.realpath to resolve the symbolic link and get the actual file path.
  • Check the file path against a whitelist or expected paths to prevent unintended file access.
  • Review the load_prompt_from_config function to ensure it handles file paths securely.

Example

import os

# ...

# Resolve the symbolic link and get the actual file path
actual_path = os.path.realpath(cfg["template_path"])

# Validate the actual file path
if not actual_path.startswith("/expected/path/"):
    raise ValueError("Invalid file path")

# ...

Notes

This solution assumes that the load_prompt_from_config function can be modified to handle file paths securely. If this is not possible, alternative solutions may be needed.

Recommendation

Apply a workaround by validating the resolved file path and checking it against a whitelist or expected paths. This will help prevent unintended file access and ensure the application loads only the intended files.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING