From 7af33accf100743f994b78e86700e10b5c4d3cf2 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Mon, 9 Mar 2026 00:49:46 -0700 Subject: [PATCH] fix: apply secret redaction to file tool outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Terminal output was already redacted via redact_sensitive_text() but read_file and search_files returned raw content. Now both tools redact secrets before returning results to the LLM. Based on PR #372 by @teyrebaz33 (closes #363) — applied manually due to branch conflicts with the current codebase. --- tests/tools/test_file_tools.py | 2 ++ tools/file_tools.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/tests/tools/test_file_tools.py b/tests/tools/test_file_tools.py index a31abf22c..7b71465f7 100644 --- a/tests/tools/test_file_tools.py +++ b/tests/tools/test_file_tools.py @@ -38,6 +38,7 @@ class TestReadFileHandler: def test_returns_file_content(self, mock_get): mock_ops = MagicMock() result_obj = MagicMock() + result_obj.content = "line1\nline2" result_obj.to_dict.return_value = {"content": "line1\nline2", "total_lines": 2} mock_ops.read_file.return_value = result_obj mock_get.return_value = mock_ops @@ -52,6 +53,7 @@ class TestReadFileHandler: def test_custom_offset_and_limit(self, mock_get): mock_ops = MagicMock() result_obj = MagicMock() + result_obj.content = "line10" result_obj.to_dict.return_value = {"content": "line10", "total_lines": 50} mock_ops.read_file.return_value = result_obj mock_get.return_value = mock_ops diff --git a/tools/file_tools.py b/tools/file_tools.py index 4457fa986..5ba098bd7 100644 --- a/tools/file_tools.py +++ b/tools/file_tools.py @@ -7,6 +7,7 @@ import os import threading from typing import Optional from tools.file_operations import ShellFileOperations +from agent.redact import redact_sensitive_text logger = logging.getLogger(__name__) @@ -128,6 +129,8 @@ def read_file_tool(path: str, offset: int = 1, limit: int = 500, task_id: str = try: file_ops = _get_file_ops(task_id) result = file_ops.read_file(path, offset, limit) + if result.content: + result.content = redact_sensitive_text(result.content) return json.dumps(result.to_dict(), ensure_ascii=False) except Exception as e: return json.dumps({"error": str(e)}, ensure_ascii=False) @@ -186,6 +189,10 @@ def search_tool(pattern: str, target: str = "content", path: str = ".", pattern=pattern, path=path, target=target, file_glob=file_glob, limit=limit, offset=offset, output_mode=output_mode, context=context ) + if hasattr(result, 'matches'): + for m in result.matches: + if hasattr(m, 'content') and m.content: + m.content = redact_sensitive_text(m.content) result_dict = result.to_dict() result_json = json.dumps(result_dict, ensure_ascii=False) # Hint when results were truncated — explicit next offset is clearer