From cdb2df49827b674fb5a685acc44dc3a8f99329dd Mon Sep 17 00:00:00 2001 From: amplifierplus <160200579+amplifierplus@users.noreply.github.com> Date: Tue, 21 Jul 2026 12:08:19 +0800 Subject: [PATCH] fix(files): reject oversized reads before loading --- nanobot/agent/tools/filesystem.py | 10 ++++++++++ tests/tools/test_filesystem_tools.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/nanobot/agent/tools/filesystem.py b/nanobot/agent/tools/filesystem.py index 2c7d8955..2d3eedc2 100644 --- a/nanobot/agent/tools/filesystem.py +++ b/nanobot/agent/tools/filesystem.py @@ -237,6 +237,7 @@ class ReadFileTool(_FsTool): _scopes = {"core", "subagent", "memory"} _MAX_CHARS = 128_000 + _MAX_FILE_SIZE_BYTES = 100 * 1024 * 1024 _DEFAULT_LIMIT = 2000 _MAX_PDF_PAGES = 20 @@ -290,6 +291,15 @@ class ReadFileTool(_FsTool): if not fp.is_file(): return ToolResult.error(f"Error: Not a file: {path}") + file_size = fp.stat().st_size + if file_size > self._MAX_FILE_SIZE_BYTES: + size_mib = file_size / (1024 * 1024) + max_mib = self._MAX_FILE_SIZE_BYTES // (1024 * 1024) + return ToolResult.error( + f"Error: File too large to read ({size_mib:.1f} MiB). " + f"Maximum is {max_mib} MiB." + ) + # PDF support if fp.suffix.lower() == ".pdf": return self._read_pdf(fp, pages) diff --git a/tests/tools/test_filesystem_tools.py b/tests/tools/test_filesystem_tools.py index 52667030..9b917dc6 100644 --- a/tests/tools/test_filesystem_tools.py +++ b/tests/tools/test_filesystem_tools.py @@ -99,6 +99,22 @@ class TestReadFileTool: assert len(result) <= ReadFileTool._MAX_CHARS + 500 # small margin for footer assert "Use offset=" in result + @pytest.mark.asyncio + async def test_oversized_file_is_rejected_before_read(self, tool, tmp_path, monkeypatch): + f = tmp_path / "huge.txt" + with f.open("wb") as stream: + stream.truncate(ReadFileTool._MAX_FILE_SIZE_BYTES + 1) + + def fail_read_bytes(self): + raise AssertionError("oversized file content should not be loaded") + + monkeypatch.setattr(type(f), "read_bytes", fail_read_bytes) + + result = await tool.execute(path=str(f)) + + assert "File too large to read" in result + assert "Maximum is 100 MiB" in result + # --------------------------------------------------------------------------- # _find_match (unit tests for the helper)