fix(visibility): route is_owner through did_matches to fix bare-key mirror lockout (#153)#156
fix(visibility): route is_owner through did_matches to fix bare-key mirror lockout (#153)#156Gravirei wants to merge 13 commits into
Conversation
Gitlawb#126) The IPFS visibility gate used withheld_blob_oids (a deny-set enumerating only reachable blobs), so a dangling/unreachable blob was absent from the set and served in cleartext to anonymous callers. Flip to an allowed-set (allowed_blob_set_for_caller) that enumerates reachable blobs the caller may read: a dangling blob has no path, is never in the set, and 404s.
Move store::read_object before the allowed_blob_set_for_caller spawn_blocking call so random-CID spray against repos with path-scoped rules cannot trigger full-history git walks on repos that don't carry the object.
…tion ✓ P3 blocker fixed: cargo fmt applied — the format gate will pass. ✓ P3 cleanup resolved: withheld_blob_oids is still used by replication code in repos.rs, so it stays. • P2 follow-up: Tree/commit disclosure tracked in Gitlawb#135 — out of scope here.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough
ChangesOwner DID Matching Fix
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the contribution. I do not see any actionable issues from my review.
@kevincodex1 LGTM
beardthelion
left a comment
There was a problem hiding this comment.
Verified the security-critical property by execution, not inspection: routing is_owner through did_matches widens who counts as owner by exactly one case, the bare-key mirror owner matched by the same key's full did:key: caller (the #153 fix). Reverting is_owner makes bare_owner_full_caller_allows_owner fail, so it's load-bearing. Cross-method stays denied because only did:key: is stripped, so did:gitlawb:zX keeps its method and can't equal a bare id. Ran the full owner/DID truth table and the node suite (424 green). The short-circuit isn't exploitable by the widening: the newly-matched caller is the Ed25519-verified owner, and this converges the read gate onto the same did:key-aware normalization the mutation gate and SQL owner filter already use, so it reduces gate/query skew.
Findings
- [P3] Pin the empty-DID invariant on the owner gate
crates/gitlawb-node/src/api/mod.rs:70
did_matches("", "did:key:")anddid_matches("", "")return true. Unreachable today (the read-gate caller is always a verifieddid:keyor None, and an empty-owner mirror slug is quarantined before the gate) and it predates this PR sincerequire_repo_owneralready usesdid_matches. But this change makesdid_matchesload-bearing on the read path too, so a one-line test pinning "the gate caller is a validateddid:keyor None" is cheap insurance. Optional.
Concur with the approval; the note is defense-in-depth, not a blocker.
Summary
Switch
is_ownerfromnormalize_owner_key(single-side normalization) todid_matches(two-side normalization with cross-method rejection) so a mirror-only repo owner authenticated with their fulldid:key:is not denied read to their own repo.Motivation & context
Closes #153
visibility::is_ownerusednormalize_owner_key(owner_did)which only stripsdid:key:off the owner side. When a mirror row storesowner_didas bare short key and the caller authenticates with fulldid:key:, the comparison fails and the owner is locked out.The old doc comment warned that
did_matches"would let a non-key canonical row bypass the #124 visibility gate" — butdid_matchesalready rejects cross-method collisions (did:key:X!=did:gitlawb:X), so that reasoning is stale.Kind of change
What changed
crates/gitlawb-node/src/visibility.rs— Replacedis_ownerbody withcrate::api::did_matches(owner_did, caller)and updated the doc comment to reflect current semantics.bare_owner_full_caller_allows_owner(regression for the lockout) andcross_method_did_denied_with_bare_owner(cross-method bypass guard).How a reviewer can verify
cargo test -p gitlawb-node -- visibility::testsProtocol & signing impact
did:key, Ed25519 / RFC 9421 signatures, UCAN, ref certs, or P2P wire formatsSummary by CodeRabbit
did:keyforms).did:web:*vsdid:key:*) are still not treated as the same owner.did:keyrepresentation-agnostic matches and to confirm cross-method matches are denied.