Skip to content

fix(records): withhold personal credentials over Tor (#131) - #134

Open
JordanCoin wants to merge 2 commits into
mainfrom
fix/131-creds-over-tor
Open

JordanCoin wants to merge 2 commits into
mainfrom
fix/131-creds-over-tor

Conversation

@JordanCoin

Copy link
Copy Markdown
Owner

Closes #131

With network.tor: true, personal credentials no longer leave the machine.

  • RecordAdapter._personal_credential() (records/base.py) returns None over Tor and sets credentials_withheld. MuckRock, NARA and DataGovAdapter resolve their credential through it in the constructor, so every caller is covered, get_adapter included. get_adapter no longer special-cases Tor.
  • MuckRock: no Authorization token over Tor.
  • GovInfo (and fec, regulations): DEMO_KEY over Tor even with OPENFOIA_GOVINFO_API_KEY set and api_key=None.
  • NARA: has_key is False over Tor. records search -s nara / records fetch -s nara exit 1 with "NARA Catalog API needs your personal API key, which would identify you, so NARA is not used over Tor." --all-sources shows skipped (personal key not sent over Tor). Direct mode is unchanged.
  • Route line: via Tor, real IP hidden, credentials withheld when an adapter held one back (search, search --all-sources, fetch, download).

The crossref Tor DEMO_KEY guard is unchanged. It is now redundant but harmless.

test_records_nara.py::test_objects_use_the_configured_tor_policy asserted that fetch -s nara --objects ran over Tor. That fetch sends the key, so the test now asserts it exits before any request.

Tests: per-adapter MockTransport checks for TOR and DIRECT in tests/test_security_egress_adapters.py. The CLI exit and route-line tests are in tests/test_security_egress_cli.py because the tor_records fixture lives there. Full suite: 592 passed. The 2 TestLLMExtraction failures need Ollama and were already failing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce

With network.tor on, the route notice said "real IP hidden" while
OPENFOIA_MUCKROCK_TOKEN, OPENFOIA_NARA_API_KEY and the
OPENFOIA_GOVINFO_API_KEY env fallback still went out with each request
and named the user to the server.

RecordAdapter._personal_credential() now returns None over Tor and sets
credentials_withheld. MuckRock (token optional), NARA (key required) and
DataGovAdapter (govinfo, fec, regulations; falls back to DEMO_KEY) resolve
their credential through it in the constructor, so every path is covered,
not only get_adapter. get_adapter no longer special-cases Tor.

NARA over Tor: has_key is False, `records search/fetch -s nara` exit with
a message that the personal key would identify you, --all-sources lists
it as skipped. The route line gains ", credentials withheld" when an
adapter held one back.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce
The key is tied to an account and named the user even with the real IP
hidden. Over Tor the request goes keyless and a 401/403 reports the key
as withheld rather than missing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce
@JordanCoin

Copy link
Copy Markdown
Owner Author

Review (Claude opus reviewer, read-only, 2026-11-06): FIX FIRST, then MERGE. Enumerated every credential source: config api.data.gov key, OPENFOIA_GOVINFO_API_KEY, OPENFOIA_MUCKROCK_TOKEN, OPENFOIA_NARA_API_KEY/CATALOG_API_KEY all withheld over Tor on every construction path (explicit arg, env, config); no _egress assignment after construction; SEC, CIA, OpenCorporates, USAspending, ProPublica, web ingest and agent.py carry no credential. One high finding: crossref's _check_opensanctions still sent OPENFOIA_OPENSANCTIONS_API_KEY over Tor. Fixed in the follow-up commit: keyless over Tor, 401/403 reports 'withheld over Tor', test added, changelog extended. Latent, no caller today: DocumentCloud auth_token is ungated. git merge-tree with #133 is clean and the merged tree passes the full suite.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Personal API keys (NARA, MuckRock, GovInfo env) still sent over Tor

1 participant