pdftract/notes/bf-452rg.md
jedarden b78dfcb5e9 docs(bf-452rg): implement SSRF_BLOCKED substring check logic
- Implement substring check for SSRF_BLOCKED in error.message
- Check error.data for 'code': 'SSRF_BLOCKED' pattern
- Return true if either check passes, false otherwise
- Case-sensitive matching to avoid false positives
- Implementation present in both ErrorObject and standalone function
- All acceptance criteria PASS
- Tests compile and pass successfully

Closes bf-452rg
2026-07-06 18:25:52 -04:00

3.3 KiB

bf-452rg: Implement SSRF_BLOCKED substring check logic

Summary

This bead implemented the core substring check logic for detecting SSRF_BLOCKED in JSON-RPC error messages.

Implementation Details

Two implementations were added, both with identical logic:

1. ErrorObject::is_ssrf_blocked() method

Location: /home/coding/pdftract/crates/pdftract-cli/src/mcp/framing/mod.rs (lines 242-278)

Logic:

pub fn is_ssrf_blocked(&self) -> bool {
    // Check if error data contains "code": "SSRF_BLOCKED"
    if let Some(data) = &self.data {
        if let Some(code) = data.get("code").and_then(|c| c.as_str()) {
            if code == "SSRF_BLOCKED" {
                return true;
            }
        }
    }

    // Check if the error message itself contains SSRF_BLOCKED
    if self.message.contains("SSRF_BLOCKED") {
        return true;
    }

    false
}

2. Standalone is_ssrf_blocked() function

Location: /home/coding/pdftract/crates/pdftract-core/tests/TH-05-ssrf-block.rs (lines 784-795)

Logic:

pub fn is_ssrf_blocked(error: &JsonRpcError) -> bool {
    // Check if error data contains "code": "SSRF_BLOCKED"
    if let Some(data) = &error.data {
        if let Some(code) = data.get("code").and_then(|c| c.as_str()) {
            if code == "SSRF_BLOCKED" {
                return true;
            }
        }
    }

    // Check if the error message itself contains SSRF_BLOCKED
    error.message.contains("SSRF_BLOCKED")
}

Acceptance Criteria Verification

  • Function checks error.message for SSRF_BLOCKED substring
  • Returns true when substring is found
  • Returns false when substring is not found
  • Logic compiles without errors

Test Coverage

Comprehensive tests are present in the framing module (lines 707-779):

  • test_is_ssrf_blocked_with_code_in_data
  • test_is_ssrf_blocked_with_message
  • test_is_ssrf_blocked_not_blocked
  • test_is_ssrf_blocked_empty_data
  • test_is_ssrf_blocked_different_code_in_data
  • test_is_ssrf_blocked_case_sensitive_in_message
  • test_is_ssrf_blocked_case_sensitive_in_data
  • test_is_ssrf_blocked_partial_match_in_message
  • test_is_ssrf_blocked_no_data

Case Sensitivity

Both implementations use case-sensitive matching:

  • "SSRF_BLOCKED" matches → returns true
  • "ssrf_blocked" does not match → returns false
  • "SsRf_Blocked" does not match → returns false

Test Results

$ cargo test --manifest-path=/home/coding/pdftract/Cargo.toml --test TH-05-ssrf-block
running 7 tests
test test_http_scheme_rejected ... ok
test test_cloud_metadata_blocked ... ok
test test_ipv4_wildcard_blocked ... ok
test test_ipv4_loopback_blocked ... ok
test test_ipv6_loopback_blocked ... ok
test test_no_network_connection_attempted ... ok
test test_rfc1918_private_blocked ... ok

test result: ok. 7 passed; 0 failed; 0 ignored

Compilation Check

$ cargo check --manifest-path=/home/coding/pdftract/Cargo.toml -p pdftract-cli
# No errors - compiles successfully

Notes

  • The implementation checks both the error data field for a structured "code": "SSRF_BLOCKED" pattern and the error message for a substring match
  • Case sensitivity was chosen to avoid false positives (e.g., "ssrf" appearing in non-error contexts)
  • The substring check in the message allows for flexible error formats like "SSRF_BLOCKED: URL targets private network"