A PartitionAccessPolicy under a satellite segment, or with an id other than _Policy, is stored but never applied by the permission fold
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 20/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Stale
- Tech stack
- csharp
- Domain
- authorization
Research direction
Read PermissionEvaluator.ObserveScopePolicies and StorageAdapterMeshQueryProvider.IsExcludedFromResults, then inspect fix PR #7017 and RuntimeInheritanceBreakingPolicyTest in Graph.Test. The issue describes a deployed production verification and a read-only sweep for existing misplaced policies; done means deployed refusal is observed and every sweep finding is resolved.
Written by the indexing model from the issue text.
Description
What happens
A PartitionAccessPolicy node created at runtime in either of two placements is stored, can be read back by its path, and is never applied by the permission fold:
- a path under a configured satellite segment (for example
{partition}/_Storage/_Policy, or any path containing_Thread,_Activity,_Access,_Comment, … — seeSatelliteTableMapping.Defaults); - any id other than
_Policy(for example{scope}/MyPolicy).
A restricting policy in either placement (for example BreaksInheritance, or a narrowed permission set) therefore has no effect: the inherited grants keep granting. Nothing is logged and the write succeeds, so the author has every reason to believe the restriction is in force. That is a silently wrong access result, hence sev:H.
What it is not: it does not widen any existing grant or bypass an existing policy. The failure is that a new restriction does not take effect.
Root cause
PermissionEvaluator.ObserveScopePolicies reads a partition's runtime policies through a content query:
path:{partition} scope:descendants id:_Policy nodeType:PartitionAccessPolicy
- A content query resolves to one storage table. Without a satellite segment in the query path, that table is
mesh_nodes. Rows placed under a satellite segment live in that segment's own table on Postgres (_Storage→storage,_Thread→threads, …), and the in-memory provider drops them on purpose to mirror Postgres (StorageAdapterMeshQueryProvider.IsExcludedFromResults). So placement 1 is never returned. - The fold also skips any node whose id is not
_Policy. So placement 2 is never considered.
A statically declared policy of the same shape does apply, because static policies are collected straight from the static node providers and never pass through the query. This static/runtime difference is how the defect surfaced (see #7013's review thread).
Fix
#7017 adds PolicyPlacementValidator to the creation chain. On Create it refuses a PartitionAccessPolicy in either placement, and the refusal names the main-node scope where the policy belongs. Pinned by RuntimeInheritanceBreakingPolicyTest (Graph.Test), including a repro on unmodified main and a negative control with the validator unregistered.
What is NOT established
- The fix refuses new writes only. It neither removes nor applies a policy that already exists in either placement. Whether any such row exists on a deployed portal is what the read-only sweep below checks; its result is posted as a comment.
- The sweep runs as one caller and is row-level-security filtered: partitions that caller reads only in part, and partitions it cannot read at all, are not covered. A clean sweep is therefore a floor, not a proof of absence, and the sweep comment states its denominator.
- Paths that reach a policy write other than a generic create (for example an import that bypasses the creation chain) were not audited beyond what the PR states: a move's copy leg and an import's create branch go through the same chain.
Closing condition
sev:H closes on post-roll production verification, not on merge:
- the running portal(s) refuse such a create (the validator's refusal is observed on the deployed image), and
- the sweep for existing misplaced policies is clean, or every finding has been resolved by the owner (moved to the main-node
_Policyscope or deleted).
Fix PR: #7017
- Dominant language
- C#
- Stars
- 12
- Forks
- 5
- Avg merge
- 6h
- Merged PRs (30d)
- 967
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Systemorph/MeshWeaver
-
bug sev:L
Difficulty 4/5 3-5 days Newbie friendliness 25/100
Systemorph/MeshWeaver#7051 ·
Maintainers usually reply within 1 day
-
bug sev:M
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Systemorph/MeshWeaver#7049 ·
Maintainers usually reply within 1 day
-
bug sev:M
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Systemorph/MeshWeaver#7043 · 5 comments ·
Maintainers usually reply within 1 day
-
bug sev:M
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Systemorph/MeshWeaver#7020 ·
Maintainers usually reply within 1 day
-
bug sev:L
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Systemorph/MeshWeaver#7002 ·
Maintainers usually reply within 1 day
All issues in Systemorph/MeshWeaver
Similar issues
-
[Bug]: Revit selector reads process ids 2000-2099 as years (flaky AgentClientTests.AYearOrAProcessIdSelectsTheHost)Possibly taken @Wurschdhaud claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
pyrevitlabs/pyRevit#3817 ·
Maintainers usually reply within 1 day
-
bug effort:S P2
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
nightscout/nocturne#2449 ·
Maintainers usually reply within 1 day
-
audit:1 bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
NethermindEth/dotnet-libp2p#395 ·
Maintainers usually reply within 1 day
-
area: client bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bug mcp misleading small
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day