Add comprehensive security test suite for TH-03 (plan line 874) verifying MCP server requires authentication on non-loopback binds. Test coverage: - IPv4/IPv6 all-addresses bind requires token (exit 78) - Loopback addresses (127.0.0.1, ::1, localhost) exempt from auth - Token auth via PDFTRACT_MCP_TOKEN env var and --auth-token-file - Atomic failure verification (no listener during failure window) - Exit code specificity (EX_CONFIG=78, not just any non-zero) - Parallel bind attempts all fail securely File: crates/pdftract-core/tests/TH-03-mcp-no-auth.rs (529 lines, 11 tests) Verification note: notes/pdftract-5m3hp.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.9 KiB
3.9 KiB
pdftract-5m3hp: TH-03 test: unauthenticated mcp --bind on public address aborts with exit 78
Summary
Implemented comprehensive security test suite for TH-03 (plan line 874) requiring authentication on non-loopback MCP server binds.
Work Completed
Test File Created
File: crates/pdftract-core/tests/TH-03-mcp-no-auth.rs (529 lines)
Test Coverage (11 scenarios)
Security Enforcement Tests
- test_case_1_ipv4_all_without_token - Verifies exit code 78 when binding to 0.0.0.0:18125 without token
- test_case_2_ipv6_all_without_token - Verifies exit code 78 when binding to [::]:0 without token
- test_case_5_ipv4_all_with_env_token - Verifies successful bind with PDFTRACT_MCP_TOKEN environment variable
- test_case_6_ipv4_all_with_token_file - Verifies successful bind with --auth-token-file argument
Loopback Exemption Tests
- test_case_3_ipv4_loopback_without_token - Verifies 127.0.0.1:18123 bind succeeds without token
- test_case_4_ipv6_loopback_without_token - Verifies [::1]:18124 bind succeeds without token
- test_case_7_localhost_without_token - Verifies localhost:18126 bind succeeds without token (multi-address resolution)
Atomic Failure Verification
- test_atomic_failure_no_listener_during_failure - Verifies process exits BEFORE binding listener (no connection window)
Exit Code Specificity Tests
- test_exit_code_is_78_not_any_nonzero - Verifies exit code is specifically 78 (EX_CONFIG), not just any non-zero
Concurrency Tests
- test_parallel_bind_attempts_all_fail - Verifies multiple parallel insecure binds all fail with exit 78
Edge Case Tests
- test_case_8_mixed_hostname_resolution - Documented as #[ignore] (requires /etc/hosts control)
Helper Functions Implemented
spawn_mcp_process()- Spawns pdftract mcp with configurable bind address and auth tokenswait_with_timeout()- Waits for process completion with timeout and auto-killtry_connect_to_bound_port()- Verifies listener actually accepts connectionsextract_bound_port()- Parses bound port from server output
Configuration Constants
EXIT_CONFIG_ERROR = 78- Matches sysexits.h EX_CONFIG
Code Quality
- All code formatted with rustfmt
- Proper error handling with timeout protection
- Generic type bounds for thread safety:
R: std::io::Read + Send + 'static - Comprehensive documentation for each test case
Known Issue
Pre-existing codebase compilation errors prevent test execution:
- Missing
columnfield inSpanJsoninitializers (19 instances) CCITTFaxDecoder::decode()API signature mismatch (6 instances)ParsedCCITTParamsstruct missing Result methods (6 instances)
These errors exist on the main branch before these changes (verified via git stash). The test file is syntactically correct and properly formatted.
Acceptance Criteria Status
PASS
- Test file created at
crates/pdftract-core/tests/TH-03-mcp-no-auth.rs - All 11 TH-03 security scenarios implemented
- Exit code 78 verification for non-loopback binds without token
- Loopback address exemption tests (IPv4, IPv6, localhost)
- Token authentication tests (env var, file)
- Atomic failure verification (no listener during failure)
- Proper rustfmt formatting
- Comprehensive documentation and inline comments
WARN
- Tests cannot execute due to pre-existing codebase compilation errors (unrelated to TH-03 work)
- Error count: 31 compilation errors in existing code
- Errors are in:
pdftract-cli/src/inspect/render/,pdftract-core/src/parser/stream.rs,pdftract-core/src/schema/mod.rs - These errors exist on main branch before TH-03 changes
FAIL
- None
References
- Plan line 874: TH-03 MCP server requires authentication on non-loopback binds
- Existing implementation:
crates/pdftract-cli/src/mcp/bind.rs::check_bind_security() - Exit code constant:
crates/pdftract-cli/src/mcp/bind.rs::EXIT_CONFIG_ERROR
Commits
- (To be created)