Filing gate: ① a product defect, exception class: security (possible data disclosure). Found by #21908's stage-1 dev on PR #22025 (os-dev-report 6021752501, out_of_scope_findings[0]). Read statically by domain:services seat 2 (seat post #21118), session_01WMQprn46CND82KmY8sZWBu, on origin/main 1fb274e61c. Filed for triage. ⛔ Not graded or routed here; ⛔ not a claim. ⛔ Classes, positions and functions only.
First step for whoever takes it: measure reachability
Per the filing gate's exception, nothing here is measured at a public door yet. The first act is to measure:
- whether any caller can see the stamped organization, or the receipt row it lands on;
- which roles in which organization can then see that row.
The grade follows from that reading.
What the code does (packages/services/service-messaging/src/messaging-service.ts)
markRead(userId, ids) (near :710) calls upsertReadReceipt for each notification id the caller names. The authenticated notifications door, and markReadAsCaller, derive userId from the session. The ids come from the caller.
- When no receipt exists for that user and notification,
upsertReadReceipt (near :881) inserts one. It stamps the receipt with the organization of the named notification event, which notificationOrganization (near :953) reads by id.
- Nothing on this path checks that the user was a recipient of that notification: no inbox message and no delivered receipt is consulted. A user's own
read receipt can therefore carry another organization's id.
PR #22025 moves these calls to the explicit system opt-in and leaves this behaviour unchanged. Before that PR the read was principal-less, and it returned the same row.
Direction (for triage to confirm)
Insert a read receipt only for a notification the user was delivered (an inbox message or a delivered receipt keyed on that user). Report the others as not read (readCount excludes them) instead of writing a row. A pin should name both halves: a recipient's mark-read persists, and a non-recipient's mark-read writes nothing.
Dedupe: MCP search_issues, repo-scoped. 「mark-read stamps the read receipt with an organization from a notification the caller names, no recipient check」 and 「notification receipt organization stamp mark read another organization's notification」 both give 0 hits. Positive control in the same session: 「inbox read receipt mark-all-read」 returns #6436 and #6448, and 「principal-less context security hand-off」 returns #21908.
Dedupe words: mark-read organization stamp · notificationOrganization recipient check · read receipt caller-named notification
Generated by Claude Code
Filing gate: ① a product defect, exception class: security (possible data disclosure). Found by #21908's stage-1 dev on PR #22025 (
os-dev-report6021752501,out_of_scope_findings[0]). Read statically bydomain:servicesseat 2 (seat post #21118),session_01WMQprn46CND82KmY8sZWBu, onorigin/main1fb274e61c. Filed for triage. ⛔ Not graded or routed here; ⛔ not a claim. ⛔ Classes, positions and functions only.First step for whoever takes it: measure reachability
Per the filing gate's exception, nothing here is measured at a public door yet. The first act is to measure:
The grade follows from that reading.
What the code does (
packages/services/service-messaging/src/messaging-service.ts)markRead(userId, ids)(near:710) callsupsertReadReceiptfor each notification id the caller names. The authenticated notifications door, andmarkReadAsCaller, deriveuserIdfrom the session. The ids come from the caller.upsertReadReceipt(near:881) inserts one. It stamps the receipt with the organization of the named notification event, whichnotificationOrganization(near:953) reads by id.readreceipt can therefore carry another organization's id.PR #22025 moves these calls to the explicit system opt-in and leaves this behaviour unchanged. Before that PR the read was principal-less, and it returned the same row.
Direction (for triage to confirm)
Insert a
readreceipt only for a notification the user was delivered (an inbox message or a delivered receipt keyed on that user). Report the others as not read (readCountexcludes them) instead of writing a row. A pin should name both halves: a recipient's mark-read persists, and a non-recipient's mark-read writes nothing.Dedupe: MCP
search_issues, repo-scoped. 「mark-read stamps the read receipt with an organization from a notification the caller names, no recipient check」 and 「notification receipt organization stamp mark read another organization's notification」 both give 0 hits. Positive control in the same session: 「inbox read receipt mark-all-read」 returns #6436 and #6448, and 「principal-less context security hand-off」 returns #21908.Dedupe words:
mark-read organization stamp·notificationOrganization recipient check·read receipt caller-named notificationGenerated by Claude Code