Skip to content

fix(rpc): gate JSON-RPC dispatch landing legs on request provenance (#1956) - #147

Merged
MichaelTaylor3d merged 2 commits into
mainfrom
fix/1956-provenance-dispatch-landing
Aug 2, 2026
Merged

fix(rpc): gate JSON-RPC dispatch landing legs on request provenance (#1956)#147
MichaelTaylor3d merged 2 commits into
mainfrom
fix/1956-provenance-dispatch-landing

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

What changed

Closes DIG-Network/dig_ecosystem#1956.

The POST / JSON-RPC dig.getContent/dig.fetchRange landing legs (the implicit warm/backfill/reshare-on-miss that makes this node a discoverable DHT holder) gated only on the transport-axis ReadOrigin, not the Sec-Fetch-Site request-provenance axis that #1654 added to the /s/ serve path. So a same-origin capsule page could POST dig.getContent and drive landing of arbitrary (chain-anchored) capsules — the CSRF door the /s/ gate already closes, left open on the JSON-RPC path. (Bounded by #1623's chain-anchored verify — no fabrication — and not cross-site-reachable, since a cross-site POST is blocked by CORS + the application/json preflight; this is the same-origin defense-in-depth follow-up from the #1654 audit.)

The fix — one shared provenance fold, applied to the POST landing legs too

Option A (mirrors the shipped #1654 serve_content_plaintext pattern): origin stays the transport axis; a new provenance axis is threaded in and folded to a land_origin used only for the landing side-effects. The read path is untouched — a cross-site POST still serves the bytes; only the durable warm/backfill/reshare/announce is withheld.

  • landing_origin is now the single shared fold — moved from content_serve.rs (module-private) to download.rs as pub(crate), beside ReadOrigin/RequestProvenance/from_sec_fetch_site. Both the /s/ path (#1654) and the JSON-RPC path (#1956) use it.
  • provenance: RequestProvenance threaded through RpcDispatch::dispatch / handle_rpc / handle_rpc_json (a required arg, matching the origin philosophy — fail-safe, no defaulting).
  • Load-bearing wiring: the server.rs POST / handler now classifies Sec-Fetch-Site via the existing provenance_for(&headers) and passes it in — without this the gate would be a no-op (constant FirstParty).
  • Folded at all FOUR landing sites, not just the two maybe_backfill_capsule calls: range_miss_envelope+maybe_backfill (FetchRange) and content_miss_envelope+maybe_backfill (GetContent) — closing the miss-envelope→fetch_resourcespawn_capsule_reshare leg as well.
  • All trusted/non-browser callers pass FirstParty (control.rs, peer.rs peer-wire — landing_origin(Peer, FirstParty)==Peer, so peers still never land — the dig-runtime FFI, and the test callers): behaviour for every pre-existing caller is unchanged; only the browser-facing HTTP POST now classifies cross-site and withholds landing.
  • SPEC.md §21.8 extended to cover the JSON-RPC POST read methods + the shared fold (complements §21.9's token-gate on the explicit cache.fetchAndCache).

Verification

New tests (each RED if any land_origin fold is dropped): cross_site_post_getcontent_serves_but_does_not_land, cross_site_post_fetchrange_serves_but_does_not_land, first_party_post_getcontent_still_lands, peer_transport_post_getcontent_unaffected, read_bytes_identical_regardless_of_provenance (dig-node-core), provenance_is_read_on_the_post_path (dig-node-service). The #1654 /s/ landing_origin serve tests + the #1623 verify + #1614 single-flight tests remain green.

  • cargo test -p dig-node-core → 517 passed; the only 9 failures are the known local-only network-bind env tests (#1961), unrelated.
  • cargo fmt --all -- --check → 0 · cargo clippy -p dig-node-core -p dig-node-service --all-targets --all-features -- -D warnings → clean · Cargo.lock updated + committed.

Version

fix: (security defense-in-depth; no wire/contract shape change — bytes served identically, all callers in-repo) → [workspace.package].version 0.75.5 → 0.75.6. No SYSTEM.md/docs change (internal behaviour).


Generated by Claude Code

MichaelTaylor3d and others added 2 commits August 2, 2026 16:28
…ance (#1956)

WIP anchor: thread RequestProvenance through dispatch/handle_rpc and fold
land_origin at the four getContent/fetchRange landing sites. Tests + Cargo.lock
follow. Salvage push before build.

Co-Authored-By: Claude <noreply@anthropic.com>
…nce (#1956)

The POST / JSON-RPC dig.getContent/dig.fetchRange landing legs gated only on
the transport-axis ReadOrigin, not the #1654 Sec-Fetch-Site provenance axis, so
a SAME-ORIGIN capsule page could POST dig.getContent and drive capsule landing
(warm/backfill/reshare) — the CSRF door the /s/ serve gate already closes.

Thread RequestProvenance through RpcDispatch::dispatch, handle_rpc, and
handle_rpc_json (a required arg, fail-safe like origin). server.rs's POST handler
classifies Sec-Fetch-Site via the existing provenance_for and passes it through;
all trusted/non-browser callers pass FirstParty. Move landing_origin beside
ReadOrigin/RequestProvenance in download.rs as the one shared fold, and apply it
at ALL FOUR landing sites (range_miss_envelope + maybe_backfill_capsule in
fetchRange; content_miss_envelope + maybe_backfill_capsule in getContent) so the
reshare leg is closed too. Reads are never altered — bytes serve identically.

Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d
MichaelTaylor3d force-pushed the fix/1956-provenance-dispatch-landing branch from 69f5bde to 8ddcb85 Compare August 2, 2026 17:08
@MichaelTaylor3d
MichaelTaylor3d merged commit b04dd41 into main Aug 2, 2026
15 checks passed
@MichaelTaylor3d
MichaelTaylor3d deleted the fix/1956-provenance-dispatch-landing branch August 2, 2026 17:26
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.

1 participant