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
[finding] when the object's schema cannot be read, the RLS field guard is not passed at all — a negated phantom column still widens, on both faces #17170
⚠️This card exists because the seat owed it and did not file it at adoption. The re-review named the omission as its own finding F6: "the prior verdict named F2 as a follow-up-card candidate; of the 13 issues created since 10:45Z none is it (the seat filed #17128 and #17129 from the dev's out_of_scope_findings; neither is F2)." Correct — I carried the delivery's findings and not the reviewer's. A follow-up card named in a verdict and never filed is the same silence this lane spends its days closing.
The residual
PR #17115 (merged as 702614108) makes RLSCompiler.compileFilter judge every column a policy names on the compiled filter tree, so an undeclared column denies in every position and polarity, on using and on check alike. The guard is supplied by the caller:
packages/plugins/plugin-security/src/security-plugin.ts:6058-6063 — the read face
…:6310-6316 — the write face
consumed at packages/plugins/plugin-security/src/rls-compiler.ts:473
⇒ When getObjectFieldNames answers null — the object's schema cannot be read — no guard is passed, and a negated phantom column widens exactly as it did before #17115.
⛔ What this is NOT
⛔ Not a defect in PR #17115, and not a regression. It is the pre-existing pass-1 contract — "a schema-lookup failure keeps all policies" — which the PR's own body and changeset state openly, and which the reviewer classed as residual by design, explicitly out of #17042's scope.
⛔ Not unbounded.fieldNamesCache caches positives only (security-plugin.ts:7640-7647), so the window is boot and unregistered objects rather than steady-state operation.
The question this card puts
⭐ The pass-1 contract says a schema miss keeps all policies. Every other seam in this area has been moved the other way this week — an unreadable answer must not be spent as a permissive one:
⇒ "Schema unreadable ⇒ keep every policy" is the same shape one layer up, and the direction the rest of the area has settled points the other way. ⛔ But it is a maintainer call, not a delivery one: failing closed on a schema miss means an object whose schema is momentarily unloadable serves nothing, and at boot that is a different blast radius from denying one malformed predicate.
What is needed first, and it is a measurement, not an opinion: how often, and in which states, does getObjectFieldNames actually answer null on a live boot? ⛔ A zero from a sweep that cannot answer "yes" is NOT MEASURED — any such probe needs a positive control that produces a real null (an unregistered object) and sees it.
Fences for whoever takes it
⛔ Relaxing a security boundary is the maintainer's floor. Every direction here tightens or is neutral.
⛔ Do not change getObjectFieldNames's caching to make the window smaller and call the card closed — that shrinks the window without deciding what happens inside it.
#17042 / PR #17115 (the fix whose contract this residual belongs to) · #16918 / PR #17125 · #15840 (the read-seam invention rule, ruled) · #17128 (the bulk-write check gate, the other unestablished half of #17115's neighbourhood) · #17129 (ADR-0095's asymmetry, also from that review round).
Filed by the
domain:servicesPM seat (#6021) as F2 of the at-tier contract review of PR #17115 (verdict of record 5600576800, card #17042).out_of_scope_findings; neither is F2)." Correct — I carried the delivery's findings and not the reviewer's. A follow-up card named in a verdict and never filed is the same silence this lane spends its days closing.The residual
PR #17115 (merged as
702614108) makesRLSCompiler.compileFilterjudge every column a policy names on the compiled filter tree, so an undeclared column denies in every position and polarity, onusingand oncheckalike. The guard is supplied by the caller:packages/plugins/plugin-security/src/security-plugin.ts:6058-6063— the read face…:6310-6316— the write facepackages/plugins/plugin-security/src/rls-compiler.ts:473⇒ When
getObjectFieldNamesanswersnull— the object's schema cannot be read — no guard is passed, and a negated phantom column widens exactly as it did before #17115.⛔ What this is NOT
⛔ Not a defect in PR #17115, and not a regression. It is the pre-existing pass-1 contract — "a schema-lookup failure keeps all policies" — which the PR's own body and changeset state openly, and which the reviewer classed as residual by design, explicitly out of #17042's scope.
⛔ Not unbounded.
fieldNamesCachecaches positives only (security-plugin.ts:7640-7647), so the window is boot and unregistered objects rather than steady-state operation.The question this card puts
⭐ The pass-1 contract says a schema miss keeps all policies. Every other seam in this area has been moved the other way this week — an unreadable answer must not be spent as a permissive one:
getService('security')runs the query with NO row scope instead of refusing #16918 / PR fix(service-analytics): row-scope bridge tells absent from broken security service #17125 — a wired-but-broken security service now refuses rather than serving unscoped;find()seams still report an un-happened read as[]— the invention half of #15598's DROP shape, left in place by that card's fence #15840 (ruled, option A) — a read that did not answer must not be reported as "there is nothing there".⇒ "Schema unreadable ⇒ keep every policy" is the same shape one layer up, and the direction the rest of the area has settled points the other way. ⛔ But it is a maintainer call, not a delivery one: failing closed on a schema miss means an object whose schema is momentarily unloadable serves nothing, and at boot that is a different blast radius from denying one malformed predicate.
What is needed first, and it is a measurement, not an opinion: how often, and in which states, does
getObjectFieldNamesactually answernullon a live boot? ⛔ A zero from a sweep that cannot answer "yes" is NOT MEASURED — any such probe needs a positive control that produces a realnull(an unregistered object) and sees it.Fences for whoever takes it
getObjectFieldNames's caching to make the window smaller and call the card closed — that shrinks the window without deciding what happens inside it.Related
#17042 / PR #17115 (the fix whose contract this residual belongs to) · #16918 / PR #17125 · #15840 (the read-seam invention rule, ruled) · #17128 (the bulk-write
checkgate, the other unestablished half of #17115's neighbourhood) · #17129 (ADR-0095's asymmetry, also from that review round).