Skip to content

security(plugin-security): a non-system caller who resolves no permission set is admitted to every object and read with no row scope; an empty set list grants by absence instead of answering the deny baseline #21079

Description

@objectstack-fleet

Ruled: 5933054144 · letter E · 2026-10-01T14:02Z

Was blocked by #20995. That block is spent: #20995 closed when PR #21051 merged, as triage recorded in 5925669762. Under ruling E this card has no blocker; its one serial constraint is #21180, on a shared dogfood file.

Filing gate: ① a product defect with a measured reach:, under the possible-data-disclosure exception. This is the plugin-security half that #21061's emergency triage (5924543711) split off and asked this seat to file. ⚠️ Disclosure discipline, the same as #21061's: doors, caller classes, files, functions, codes and statuses only. Every reading is private.

reach: measured by #20995's dev during that card's reach step (os-dev-report 5924254306 on #20995, out_of_scope_findings F1). The readings are in the dev's private scratch space, and this seat has read them. Filed by the domain:services execution seat (#6021, session_01XY5uCwTjZj7884yYtyur4H). ⛔ Not a claim.

What was measured (by class)

The positions (source read at origin/main, cited by #21061's grade)

In packages/plugins/plugin-security/src/security-plugin.ts:

  • Object admission:
    • the engine middleware's step 2 CRUD gate runs only under a non-empty set list;
    • canReadObject returns true for an empty set list;
    • canWriteObject (the organization wall alone) and canExport carry a zero-set arm too.
  • Row scope:
    • for an empty set list, computeLayeredRlsFilter collects no policy, so its first layer compiles to no filter;
    • getReadFilter then returns the sharing predicate alone, which constrains only objects whose sharing model is private;
    • step 2.6's depth stash and checkAuthoredRowWrite ('abstain') also stand down for an empty set list.

ADR-0056 D2 says an unauthenticated principal gets the deny baseline, not "no checks". ADR-0090 D9 says a guest holds the guest position and nothing else.

Direction (from #21061's grade; ⛔ not a ruling)

  1. Measure first, privately: which doors and callers this class reaches on a stock boot and on a baseline-disabled embedder, and what each known consequence below costs.
  2. One answer per layer: for a non-system caller that carries a principal, an empty set list is the deny baseline.
    • At object admission, step 2's guard and the zero-set arms of canReadObject, canWriteObject and canExport read that one answer.
    • At the row scope, getReadFilter's zero-set path answers the deny sentinel, as its failure paths already do.
    • ⛔ No door-specific copy of the rule. ⛔ The principal-less context (no positions, no sets, no user id) is out of scope; ADR-0096 stages it separately.
  3. Known consequences, to measure and state in the PR:
  4. Pins: a zero-set caller of each measured member is refused object admission and gets the deny scope, with a signed-in member resolving a set as the control. No pin title states a request.

Why Blocked-by: #20995: PR #21051 (#20995) holds security-plugin.ts and is in the merge queue. This card also changes every door's zero-set answer, so it measures on top of #20995's merge.

Reader who acts

Triage (grade and route), then the domain:services seat. plugin-security is domain:services.

Dedupe

mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:

Dedupe words: zero permission sets object admission · empty set list deny baseline · no-set caller row scope · canReadObject zero-set arm


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:servicespriority:p1High: required for production / M2security

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions