Skip to content

Security: filterNodesByChannelPermission ignores sourceId — cross-source permission leak for guests #3745

Description

@Yeraze

Summary

filterNodesByChannelPermission in nodeEnhancer.ts is called from server.ts:1004 without passing the nodesSourceId parameter. This causes the permission filter to perform a union across all sources rather than scoping to the requested source, creating a cross-source permission leak for guest users.

Affected Files

  • server.ts:1004 — call site where nodesSourceId is extracted but not forwarded to filterNodesByChannelPermission
  • nodeEnhancer.ts:160filterNodesByChannelPermission implementation where sourceId === undefined triggers a global permission union

Root Cause

In server.ts around line 1004, nodesSourceId is correctly extracted to scope which nodes are fetched. However, when filterNodesByChannelPermission is invoked, nodesSourceId is not passed as an argument.

Inside filterNodesByChannelPermission (nodeEnhancer.ts:160), when sourceId is undefined, the call to getUserPermissionSetAsync falls back to a union of permissions across all configured sources. This means the permission check is evaluated against the broadest possible permission set rather than the specific source the nodes belong to.

Impact

A guest user who holds channel 0 read permission on source A will pass the permission filter for channel 0 nodes fetched from source B, even if they have been granted zero permissions on source B.

  • The sourceId correctly controls which nodes are fetched (source-scoped fetch).
  • But the permission filter uses a global union, so the security boundary is not enforced at the filter layer.
  • Guests can view nodes from sources they have no explicit permission for, as long as the channel index overlaps with a source they do have access to.

Reproduction

  1. Configure two sources (A and B) with channel 0 on each.
  2. Create a guest user with channel 0 read permission on source A only.
  3. Request nodes scoped to source B.
  4. Observe that channel 0 nodes from source B pass the permission filter.

Fix

Pass nodesSourceId (or the equivalent source identifier) through to filterNodesByChannelPermission at the server.ts:1004 call site, and ensure getUserPermissionSetAsync inside nodeEnhancer.ts:160 scopes its lookup to that specific source rather than performing a cross-source union when a sourceId is provided.

Related

This is the same class of bug as #3712 (sourceId scoping gaps). The fetch path was corrected but the permission filter path was not updated to match.


Authored by NodeZero 0️⃣

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions