From 38a25ce5144424dedf9a8f47a376180c1819737d Mon Sep 17 00:00:00 2001 From: trsdn Date: Wed, 10 Jun 2026 11:18:30 +0200 Subject: [PATCH 1/2] perf: remove path validation delay Path validation was wrapped in a timing-normalization decorator that added at least 50ms to every file-path validation. That delay is unnecessary for path validation because no secret-dependent comparison happens there, and it materially slows convert_file calls and any workflow that validates many paths.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- markitdown_mcp/server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/markitdown_mcp/server.py b/markitdown_mcp/server.py index 1bdfa42..f6c9bef 100644 --- a/markitdown_mcp/server.py +++ b/markitdown_mcp/server.py @@ -535,7 +535,6 @@ def safe_convert_with_limits(markitdown_instance: MarkItDown, file_path: str) -> sys.setrecursionlimit(original_limit) -@normalize_timing def validate_and_sanitize_path( file_path: str, allowed_dirs: list[str] | None = None ) -> tuple[Path, bool]: From 5cce130d2996633e4c15125dbb878bd7a2655478 Mon Sep 17 00:00:00 2001 From: trsdn Date: Wed, 10 Jun 2026 13:00:43 +0200 Subject: [PATCH 2/2] test: cover timing security helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/unit/test_additional_coverage.py | 42 ++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_additional_coverage.py b/tests/unit/test_additional_coverage.py index a0bf03b..7d6a6ec 100644 --- a/tests/unit/test_additional_coverage.py +++ b/tests/unit/test_additional_coverage.py @@ -12,16 +12,17 @@ from markitdown_mcp.server import ( MarkItDownMCPServer, - MCPRequest, SecurityError, - validate_xml_security, - validate_json_security, extract_text_from_binary, + normalize_timing, + safe_convert_with_limits, sanitize_unicode_text, - with_timeout, + secure_compare, validate_base64, - safe_convert_with_limits, validate_file_content_security, + validate_json_security, + validate_xml_security, + with_timeout, ) @@ -201,6 +202,35 @@ def operation(): result = operation() assert result == "no timeout" + def test_secure_compare(self): + """Test constant-time comparison helper.""" + assert secure_compare("same", "same") is True + assert secure_compare("same", "different") is False + + def test_normalize_timing_success(self): + """Test timing normalization decorator returns successful results.""" + @normalize_timing + def operation(): + return "normalized" + + start_time = time.time() + result = operation() + + assert result == "normalized" + assert time.time() - start_time >= 0.05 + + def test_normalize_timing_exception(self): + """Test timing normalization decorator re-raises exceptions.""" + @normalize_timing + def operation(): + raise ValueError("normalized error") + + start_time = time.time() + with pytest.raises(ValueError, match="normalized error"): + operation() + + assert time.time() - start_time >= 0.05 + def test_validate_base64_valid(self): """Test base64 validation with valid data.""" import base64 @@ -320,4 +350,4 @@ def test_validate_file_content_security_other(self): result = validate_file_content_security(temp_path) assert result == temp_path # Should return original for non-special files finally: - Path(temp_path).unlink(missing_ok=True) \ No newline at end of file + Path(temp_path).unlink(missing_ok=True)