Revise PR #233: mention feed - send reader on the remote path, normalise handles, and stop the cross-channel mention leak - #320
Revise PR #233: mention feed - send reader on the remote path, normalise handles, and stop the cross-channel mention leak#320jaylfc wants to merge 2 commits into
Conversation
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
Warning Review limit reached
Next review available in: 32 minutes Limit details: You’ve used all 1 included review currently available under your plan. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
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 |
| self._send_json(403, {"error": f"registry auth: {exc}"}) | ||
| return | ||
| qp_reader = (qs.get("reader") or [None])[0] | ||
| reader = qp_reader or token_sub |
There was a problem hiding this comment.
CRITICAL: reader = qp_reader or token_sub allows ?reader= to override the authenticated token identity
When a registry verifier is configured, the server authenticates the Bearer token and extracts token_sub, but then silently replaces it with any ?reader= query parameter supplied by the caller. Any valid-token holder can query any other user's mentions simply by changing that parameter — e.g. GET /a2a/mentions?reader=alice with a bob token returns Alice's mentions. The authorize() call validates the token's validity, not that token_sub matches qp_reader.
Remove the qp_reader override when a verifier is configured; reader must always be token_sub.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| import jwt as _jwt # noqa: PLC0415 | ||
| unverified = _jwt.decode(token, options={"verify_signature": False}) | ||
| raw_sub = unverified.get("sub", "") or "" | ||
| except Exception: # noqa: BLE001 |
There was a problem hiding this comment.
WARNING: Bare except Exception on jwt.decode silently masks all JWT parsing errors
jwt.decode() can raise jwt.exceptions.DecodeError, jwt.exceptions.InvalidTokenError, and other specific subclasses for malformed, expired, or algorithm-mismatched tokens. Catching Exception collapses all of these into raw_sub = "", which is then forwarded to authorize(). While authorize() performs its own full verification, the empty-string raw_sub will produce an incorrect or confusing error if the verifier logs or includes it in an error message, and makes it harder to distinguish between a malformed token and a legitimate one whose sub extraction failed for some other reason.
Catch jwt.exceptions.PyJWTError specifically (or Exception only as a final fallback with a logged warning), so genuine JWT format errors are distinguishable.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| except (TypeError, ValueError): | ||
| continue | ||
|
|
||
| root_threads = {msg_thread[mid] for mid in mentioned_ids if mid in msg_thread} |
There was a problem hiding this comment.
WARNING: root_threads is computed but never referenced — dead code
root_threads = {msg_thread[mid] for mid in mentioned_ids if mid in msg_thread}This set comprehension is evaluated but root_threads is never used anywhere in the function. The actual thread-root data is correctly built via thread_roots through _find_thread_root (lines 954–958), so root_threads appears to be a leftover from a refactor. Dead code of this form can mask incomplete logic or confuse future maintainers about which data structure is authoritative.
Remove root_threads = ... or document why it is intentionally unused.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| registry auth on the server side; ``reader`` is forwarded as a query | ||
| parameter so the server returns the requested user's mentions. | ||
| """ | ||
| params: dict = {"reader": reader, "limit": limit} |
There was a problem hiding this comment.
WARNING: a2a_mentions_feed unconditionally sends reader as a query parameter, enabling server-side auth bypass
The remote client always forwards reader in the request params. Combined with the server-side behaviour at http_server.py:1699 (reader = qp_reader or token_sub), any caller that can control the reader argument to the remote client can impersonate any other user's identity when calling this endpoint against a registry-authed server.
Document this risk explicitly, or — better — make the server ignore ?reader= when a verifier is configured, removing the exposure regardless of which client is used.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 4 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)CRITICAL
WARNING
Files Reviewed (5 files)
Fix these issues in Kilo Cloud Reviewed by step-3.7-flash · Input: 93.1K · Output: 9.1K · Cached: 622.3K |
Review: BLOCKReviewed at Suite on the trial merge: 1504 passed, 12 skipped (master baseline 1479/12, +25 = the 25 tests in BLOCKER 1 —
|
|
Revision card is Correction to the record: the close reason on the executing card |
…y posted (#329) Revises PR #318 (card tsk-khej63), which was blocked for two things. Both are fixed and verified independently rather than inherited. BLOCKER A - the audit was reported as posted but never was. It is posted now: build channel message 3126, from taosmd-dev, 4393 chars. Verified by RE-READING the channel, not by trusting a send response. The report is internally consistent: 18 channels, 3051 messages, 37 unique senders, and every channel's per-sender counts sum EXACTLY to its stated channel total (18/18 channels reconcile, 0 mismatches). The PR body quotes the message id, so the claim is checkable by reading one message. BLOCKER B - the census saw 1 sender where there were 11. Measured on the shipped service.a2a_sender_census, run from inside the trial-merge tree (taosmd.__file__ confirmed), over a store rebuilt to the exact 11-sender distribution the card recorded from the live bus: 11 of 11 senders seen, every total exact, every per-channel split exact, 0 mismatches ordering descending by total: True cross-check vs a2a_members('build'): both report 11, sets agree exactly empty store -> {} (negative control: the instrument discriminates) 120 messages from one sender -> 120 (no 50-row cliff; the call carries an explicit limit=100_000, which is the exact defect PR #320 was blocked for dropping) The live report agrees with the card: all 11 senders the card measured appear on build, 0 missing. Build shows 17 distinct senders over its full 1664 messages rather than the card's 11 from the last 200, and the PR body explains the difference as 15 plus 2 test probes - measured and true (test-no-token and test-bad-token, which independently corroborates the observation that bus auth is not enforced). Per-sender token validity and sub/from agreement are NOT answered, and the report says so plainly with the reason: the registry feeds require a registry_feeds_read grant the bus token does not hold. The card explicitly permits stopping short when it is stated plainly, so this is within scope rather than a gap. a2a_sender_census mirrors its sibling a2a_channels exactly - same explicit limit, same admin_action / superseded / alias / deleted-channel handling, same thread resolution - plus the GET /a2a/census endpoint and RemoteClient forwarding, and it is exported in __all__. Full suite on a trial merge with current master: 1501 passed, 12 skipped (master baseline 1496/12, +5 = exactly the 5 tests this PR adds). Conflict-marker scan clean, check_deleted_symbols clean, normalise-handle gate clean, witness gate clean, all run on the merged tree.
CARD TITLE (intent, not commit subject): Revise PR #233: mention feed - send reader on the remote path, normalise handles, and stop the cross-channel mention leak
Autonomous build of board card tsk-6icvd4.
Files:
changelog.d/tsk-6icvd4-mentions-feed.md | 7 +
taosmd/api.py | 4 +
taosmd/http_server.py | 53 ++-
taosmd/mentions.py | 92 ++++++
taosmd/remote.py | 20 ++
taosmd/service.py | 168 +++++++++-
tests/test_a2a_mentions.py | 564 ++++++++++++++++++++++++++++++++
7 files changed, 906 insertions(+), 2 deletions(-)