You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
security(plugin-audit): an activity row composed at write time may carry a changed field's values to a reader who can read the parent record but not that field (unmeasured; measure first) #21081
Filing gate: ① a product defect, filed under the possible-data-disclosure exception, whose first point is measure reach first. No reach: is measured yet. ⚠️ Disclosure discipline: positions and caller classes only.
Source: #20833's dev report (5924706600, out_of_scope_findings, the carrier: entry, "noted, not filed"). The at-tier contract review of PR #21069 (5924857517, ③) escalated it: "a data-exposure class with no carrier yet — the seat should give it a card or a row in the close-out rather than acceptance notes alone". It is not the same mechanism as the close-out family card filed beside it, so it gets its own card. Filed by the domain:services execution seat (#6021, session_01XY5uCwTjZj7884yYtyur4H). ⛔ Not a claim.
The suspicion (by class; ⛔ not measured)
The caller: a non-system reader who can read a parent record but not every field of it (a field masked for this reader, or one its sets do not grant).
The position:packages/plugins/plugin-audit/src/audit-writers.ts composes the activity row at write time, as the system. Its human-readable summary and its recorded details can carry the changed fields' values. The writer masks credential fields (secret, and password off better-auth objects) and drops virtual ones. It does not apply the reading caller's field-level answer, which it cannot know at write time.
Measure first, privately: on a real boot, with a reader of each field class above and an unmasking reader as the control, does the activity row about a change to that field serve the field's value? Measure through the generic data doors and the activity feed. If nothing is served, close this card with the reading.
Dedupe words: activity summary masked field value · activity row field level · write-time summary field permission · audit activity before after values
Filing gate: ① a product defect, filed under the possible-data-disclosure exception, whose first point is measure reach first. No⚠️ Disclosure discipline: positions and caller classes only.
reach:is measured yet.Source: #20833's dev report (
5924706600,out_of_scope_findings, thecarrier:entry, "noted, not filed"). The at-tier contract review of PR #21069 (5924857517, ③) escalated it: "a data-exposure class with no carrier yet — the seat should give it a card or a row in the close-out rather than acceptance notes alone". It is not the same mechanism as the close-out family card filed beside it, so it gets its own card. Filed by thedomain:servicesexecution seat (#6021,session_01XY5uCwTjZj7884yYtyur4H). ⛔ Not a claim.The suspicion (by class; ⛔ not measured)
packages/plugins/plugin-audit/src/audit-writers.tscomposes the activity row at write time, as the system. Its human-readable summary and its recorded details can carry the changed fields' values. The writer masks credential fields (secret, andpasswordoff better-auth objects) and drops virtual ones. It does not apply the reading caller's field-level answer, which it cannot know at write time.getReadableFields, which counts a field the caller is served masked as readable, so such a field may reach an approver as stored rather than masked (source-read, not yet measured) #20964 (PR fix(approvals): a snapshot field the reader is served masked is no longer served as stored (#20964) #20993) closed the same class for approval payload snapshots, at read time and through the security service's own answer.Direction (⛔ not a ruling)
getReadableFields, which counts a field the caller is served masked as readable, so such a field may reach an approver as stored rather than masked (source-read, not yet measured) #20964's redaction does.plugin-audit.Reader who acts
Triage (grade and route;
plugin-auditisdomain:services), then this lane's seat for the measurement.Dedupe
mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:getReadableFields, which counts a field the caller is served masked as readable, so such a field may reach an approver as stored rather than masked (source-read, not yet measured) #20964 (closed) is the same class for approval snapshots: the precedent.maskingRule's describe and the result masker mask it — which one a public door serves is not measured #20995 (open) are the zero-set caller's field answers at other doors.collectMaskedReadFieldsand objectui'sMASKED_FIELD_TYPESeach own a copy of one fact #20141, A field denied by FLS (readable:false) is exactly recoverable from a readable formula that references it — measured on showcase_project.budget #9562, spec/security: field masking is all-or-nothing — no partial masking (phone last-4, ID middle-8), andmaskingRulewas pruned as dead in 2026-06 #8993, finding: after ADR-0106, a restricted caller's GET → edit → PUT of an object schema DELETES the fields that were masked out of their read #6603, A permission set accepts a hierarchyreadScopebesideviewAllRecords: true, never reads it, and emits no diagnostic — the declaration materialises and a capability census counts it as coverage #16870, [permissions] 行级读可见范围无法按业务字段收窄:viewAllRecords 全有/全无两档之间缺共享规则 #4376 and finding: the #7929 read-scope disclosure is NOT analytics-only — an RLS$fieldfilter injected by the security middleware discloses the same policy column on the ordinary CRUD path, and predates #7598 #7988 (closed) are other masking or FLS defects.Dedupe words:
activity summary masked field value·activity row field level·write-time summary field permission·audit activity before after valuesGenerated by Claude Code