pdftract/notes/pdftract-5m3hp.md
jedarden 3fa783f628 test(pdftract-5m3hp): implement TH-03 MCP no-auth bind security tests
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>
2026-05-24 18:43:52 -04:00

86 lines
3.9 KiB
Markdown

# 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
1. **test_case_1_ipv4_all_without_token** - Verifies exit code 78 when binding to 0.0.0.0:18125 without token
2. **test_case_2_ipv6_all_without_token** - Verifies exit code 78 when binding to [::]:0 without token
3. **test_case_5_ipv4_all_with_env_token** - Verifies successful bind with PDFTRACT_MCP_TOKEN environment variable
4. **test_case_6_ipv4_all_with_token_file** - Verifies successful bind with --auth-token-file argument
#### Loopback Exemption Tests
5. **test_case_3_ipv4_loopback_without_token** - Verifies 127.0.0.1:18123 bind succeeds without token
6. **test_case_4_ipv6_loopback_without_token** - Verifies [::1]:18124 bind succeeds without token
7. **test_case_7_localhost_without_token** - Verifies localhost:18126 bind succeeds without token (multi-address resolution)
#### Atomic Failure Verification
8. **test_atomic_failure_no_listener_during_failure** - Verifies process exits BEFORE binding listener (no connection window)
#### Exit Code Specificity Tests
9. **test_exit_code_is_78_not_any_nonzero** - Verifies exit code is specifically 78 (EX_CONFIG), not just any non-zero
#### Concurrency Tests
10. **test_parallel_bind_attempts_all_fail** - Verifies multiple parallel insecure binds all fail with exit 78
#### Edge Case Tests
11. **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 tokens
- `wait_with_timeout()` - Waits for process completion with timeout and auto-kill
- `try_connect_to_bound_port()` - Verifies listener actually accepts connections
- `extract_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 `column` field in `SpanJson` initializers (19 instances)
- `CCITTFaxDecoder::decode()` API signature mismatch (6 instances)
- `ParsedCCITTParams` struct 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
- [x] Test file created at `crates/pdftract-core/tests/TH-03-mcp-no-auth.rs`
- [x] All 11 TH-03 security scenarios implemented
- [x] Exit code 78 verification for non-loopback binds without token
- [x] Loopback address exemption tests (IPv4, IPv6, localhost)
- [x] Token authentication tests (env var, file)
- [x] Atomic failure verification (no listener during failure)
- [x] Proper rustfmt formatting
- [x] 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)