From 49c5ac07ed6d73baf171798772c8ad8ec72d4c06 Mon Sep 17 00:00:00 2001 From: "corridor-security[bot]" <203152403+corridor-security[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 06:10:27 +0000 Subject: [PATCH] Fix: Fix Regex pattern injection via user-controlled ripgrep search pattern --- .mcp.json | 12 ------------ .../langchain/agents/middleware/file_search.py | 13 ++++++++++++- 2 files changed, 12 insertions(+), 13 deletions(-) delete mode 100644 .mcp.json diff --git a/.mcp.json b/.mcp.json deleted file mode 100644 index c55e4cb21cc..00000000000 --- a/.mcp.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "mcpServers": { - "docs-langchain": { - "type": "http", - "url": "https://docs.langchain.com/mcp" - }, - "reference-langchain": { - "type": "http", - "url": "https://reference.langchain.com/mcp" - } - } -} diff --git a/libs/langchain_v1/langchain/agents/middleware/file_search.py b/libs/langchain_v1/langchain/agents/middleware/file_search.py index 89651015718..bdb163119f7 100644 --- a/libs/langchain_v1/langchain/agents/middleware/file_search.py +++ b/libs/langchain_v1/langchain/agents/middleware/file_search.py @@ -21,6 +21,9 @@ from langchain_core.tools import tool from langchain.agents.middleware.types import AgentMiddleware, AgentState, ContextT, ResponseT +_MAX_REGEX_PATTERN_LENGTH = 1000 +_MAX_REGEX_LINE_LENGTH = 10000 + def _is_within_root(candidate: Path, root: Path) -> bool: """Return True iff `candidate` resolves to a path inside `root` (symlinks resolved). @@ -358,7 +361,13 @@ class FilesystemFileSearchMiddleware(AgentMiddleware[AgentState[ResponseT], Cont if not base_full.exists(): return {} - regex = re.compile(pattern) + if len(pattern) > _MAX_REGEX_PATTERN_LENGTH: + return {} + + try: + regex = re.compile(pattern) + except re.error: + return {} results: dict[str, list[tuple[int, str]]] = {} # Walk directory tree without following symlinked directories so traversal @@ -390,6 +399,8 @@ class FilesystemFileSearchMiddleware(AgentMiddleware[AgentState[ResponseT], Cont # Search content for line_num, line in enumerate(content.splitlines(), 1): + if len(line) > _MAX_REGEX_LINE_LENGTH: + continue if regex.search(line): virtual_path = "/" + str(file_path.relative_to(self.root_path)) if virtual_path not in results: