The --root DIR flag was already fully implemented in the codebase. All 25 tests pass (12 unit + 13 integration tests). Acceptance criteria verified: - Path traversal rejected with -32602 - Absolute paths rejected when --root is set - HTTPS URLs bypass the check - Symlink escapes detected via canonicalize - Startup validation for root directory Co-Authored-By: Claude Code <noreply@anthropic.com>
3 KiB
3 KiB
pdftract-6696g: Path-traversal protection via --root DIR
Summary
The --root CLI flag for MCP server path-traversal protection was already implemented in the codebase. This verification note confirms the implementation meets all acceptance criteria.
Implementation Location
- CLI flag:
crates/pdftract-cli/src/main.rslines 112-119 - Path resolution:
crates/pdftract-cli/src/mcp/root.rslines 39-76 (resolve_path) - Root validation:
crates/pdftract-cli/src/mcp/root.rslines 78-102 (canonicalize_root) - Tool integration:
crates/pdftract-cli/src/mcp/tools/registry.rsline 203 (open_pdfcallsresolve_path)
Acceptance Criteria Verification
| Criterion | Status | Evidence |
|---|---|---|
Path traversal ../../etc/passwd → -32602 |
✅ PASS | Test: test_acceptance_criteria_path_traversal_rejected |
Valid path ./subdir/file.pdf → success |
✅ PASS | Test: test_acceptance_criteria_valid_path_within_root |
Absolute path /etc/passwd → -32602 |
✅ PASS | Test: test_acceptance_criteria_absolute_path_rejected |
| HTTPS URL bypasses check | ✅ PASS | Test: test_acceptance_criteria_https_url_bypasses_check |
| No --root → trust-the-caller mode | ✅ PASS | Test: test_acceptance_criteria_no_root_trust_the_caller |
| Symlink escape → -32602 | ✅ PASS | Test: test_acceptance_criteria_symlink_escape_rejected |
| Nonexistent --root → startup error | ✅ PASS | Test: test_acceptance_criteria_nonexistent_root_startup_error |
| --root is file → startup error | ✅ PASS | Test: test_acceptance_criteria_file_not_directory_startup_error |
| Plan critical test | ✅ PASS | Test: test_plan_critical_test_path_traversal_with_root |
Test Results
All 25 tests pass:
- Unit tests (root.rs): 12 tests passed
- Integration tests (root-path-protection.rs): 13 tests passed
$ cargo test --test root-path-protection
test result: ok. 13 passed; 0 failed; 0 ignored
$ cargo test --package pdftract-cli --lib mcp::root
test result: ok. 12 passed; 0 failed; 0 ignored
Key Security Features
- Canonicalization:
std::fs::canonicalizefollows symlinks, ensuring the resolved path is checked - Absolute path rejection: Explicit check for
/prefix when--rootis set - HTTPS bypass: URLs starting with
http://orhttps://skip path resolution - Structured errors: All failures return JSON-RPC error code -32602 with descriptive messages
CLI Help Output
--root <DIR>
Root directory for local filesystem access (enforces path-traversal protection)
When set, all local-path tool arguments are resolved relative to DIR and any
path that escapes DIR is rejected with JSON-RPC error code -32602. HTTPS URLs
are not affected by this flag. Without --root, the server runs in
trust-the-caller mode (no path-check applied).
No Code Changes Required
The implementation was already complete. This bead was a verification task rather than an implementation task.