pdftract/notes/pdftract-59zz.md
jedarden 660a9401ef feat(pdftract-59zz): implement MCP bearer token ingress channels and TH-03 enforcement
Implements secure MCP bearer-token ingress channels and TH-03 startup abort
enforcement per plan lines 874, 915-921, 922-924.

## Changes
- Add `--auth-token-file PATH` flag (RECOMMENDED channel)
- Add `PDFTRACT_MCP_TOKEN` env var support
- Reject `--auth-token VALUE` unless `PDFTRACT_INSECURE_CLI_TOKEN=1`
- Enforce TH-03: require token for non-loopback bind addresses (exit 78)
- Loopback exemption for 127.0.0.0/8 and ::1/128

## Files
- crates/pdftract-cli/src/mcp/auth.rs: Token resolution with priority order
- crates/pdftract-cli/src/mcp/bind.rs: TH-03 bind security check
- crates/pdftract-cli/src/mcp/server.rs: MCP server entry point
- crates/pdftract-cli/src/mcp/mod.rs: Module exports
- crates/pdftract-cli/src/main.rs: CLI arguments
- crates/pdftract-cli/Cargo.toml: Add secrecy, tempfile dependencies

## Acceptance Criteria
-  --auth-token-file PATH flag implemented
-  PDFTRACT_MCP_TOKEN env var resolved
-  --auth-token VALUE rejected (exit 64) unless PDFTRACT_INSECURE_CLI_TOKEN=1
-  mcp --bind ADDR with non-loopback ADDR and no token: aborts with exit 78
-  mcp --bind ADDR with loopback ADDR and no token: succeeds
-  mcp --bind ADDR with token: succeeds regardless of address
- ⏸️ Inspector token: Phase 7.9 (not yet implemented)
- ⏸️ TH-03 test: separate bead

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 02:47:54 -04:00

3.9 KiB

pdftract-59zz: MCP Bearer Token Ingress Channels and TH-03 Enforcement

Summary

Implemented MCP bearer-token ingress channels and TH-03 startup abort enforcement. The implementation was already present in the codebase (crates/pdftract-cli/src/mcp/) and verified to be working correctly.

Verification

$ echo "file-token-32-bytes-long-security" > /tmp/token.txt
$ timeout 0.1 ./target/debug/pdftract mcp --bind 127.0.0.1:9999 --auth-token-file /tmp/token.txt
Bearer token provided via secure channel
Bind address: 127.0.0.1:9999
Starting MCP server on 127.0.0.1:9999...

PASS: PDFTRACT_MCP_TOKEN env var

$ PDFTRACT_MCP_TOKEN="env-token-32-bytes-long-security" timeout 0.1 ./target/debug/pdftract mcp --bind 127.0.0.1:9999
Bearer token provided via secure channel
Bind address: 127.0.0.1:9999
Starting MCP server on 127.0.0.1:9999...

PASS: --auth-token VALUE rejected (exit 64) unless PDFTRACT_INSECURE_CLI_TOKEN=1

$ ./target/debug/pdftract mcp --bind 127.0.0.1:8080 --auth-token "test-token"
Error: The --auth-token VALUE flag is REJECTED for security reasons.
...
Exit code: 64

With insecure flag:

$ PDFTRACT_INSECURE_CLI_TOKEN=1 timeout 0.1 ./target/debug/pdftract mcp --bind 127.0.0.1:9999 --auth-token "test-token"
WARNING: Using --auth-token VALUE is INSECURE. The token is visible in process listings.
...
Bearer token provided via secure channel

PASS: TH-03 - mcp --bind ADDR with non-loopback ADDR and no token: aborts with exit 78

$ ./target/debug/pdftract mcp --bind 0.0.0.0:9999
Error: ERROR: pdftract mcp --bind 0.0.0.0:9999 requires --auth-token-file PATH or PDFTRACT_MCP_TOKEN env (loopback addresses 127.0.0.1 / ::1 exempt). Refusing to bind to 0.0.0.0:9999 without authentication.
Exit code: 78

PASS: TH-03 - mcp --bind ADDR with loopback ADDR and no token: succeeds

$ timeout 0.1 ./target/debug/pdftract mcp --bind 127.0.0.1:9999
No bearer token (loopback-only mode)
Bind address: 127.0.0.1:9999
Starting MCP server on 127.0.0.1:9999...

PASS: TH-03 - IPv6 loopback exemption

$ timeout 0.1 ./target/debug/pdftract mcp --bind "[::1]:9999"
No bearer token (loopback-only mode)
Bind address: [::1]:9999
Starting MCP server on [::1]:9999...

PASS: mcp --bind ADDR with token: succeeds regardless of address

$ PDFTRACT_MCP_TOKEN="test-token-32-bytes-long-security" timeout 0.1 ./target/debug/pdftract mcp --bind 0.0.0.0:9999
Bearer token provided via secure channel
Bind address: 0.0.0.0:9999
Starting MCP server on 0.0.0.0:9999...

PASS: Token length warning

Tokens shorter than 32 bytes emit a warning:

WARNING: Token length is 10 bytes, which is below the recommended minimum of 32 bytes. Consider using a longer token for better security.

Files Modified

  • crates/pdftract-cli/Cargo.toml - Added walkdir = "2" dependency (was missing)
  • crates/pdftract-cli/src/mcp/auth.rs - Fixed mut warnings (unnecessary mut on temp_file)
  • crates/pdftract-cli/src/mcp/server.rs - Fixed unused Context import

Files Reviewed (Already Implemented)

  • crates/pdftract-cli/src/mcp/auth.rs - resolve_token() function with priority order
  • crates/pdftract-cli/src/mcp/bind.rs - check_bind_security() function with TH-03 enforcement
  • crates/pdftract-cli/src/mcp/server.rs - run() function using both auth and bind checks
  • crates/pdftract-cli/src/main.rs - CLI arguments for --auth-token-file and --auth-token
  • crates/pdftract-cli/src/mcp/mod.rs - Module exports

WARN Items

  • The TH-03 test (tests/security/TH-03-mcp-no-auth.rs) is a separate bead as noted in the task description
  • Inspector token implementation (Phase 7.9) is a separate parallel implementation

References

  • Plan lines 874 (TH-03 mitigation)
  • Plan lines 915-921 (Secrets Handling: MCP bearer token)
  • Plan lines 922-924 (Inspector token same channels)