Skip to content

[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

Description

@os-trump

Filed by the domain:services PM seat (#6021) as F2 of the at-tier contract review of PR #17115 (verdict of record 5600576800, card #17042).

⚠️ 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.
  • ⚠️ If the answer is "fail closed", the acceptance shape is the one fix(security)!: an RLS predicate naming an undeclared column denies in every position #17115 used: both faces, both polarities, with a positive control that a readable schema still admits exactly as today. A fix that makes every boot-time read deny has replaced one fail-open with an outage.

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 check gate, the other unestablished half of #17115's neighbourhood) · #17129 (ADR-0095's asymmetry, also from that review round).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions