Skip to content

fix(guest-panel): fail closed when getCurrentPlaylistAuth() resolves to null - #1405

Closed
Grimothy wants to merge 1 commit into
m3ue:devfrom
Grimothy:fix/1398-guest-panel-null-auth-fail-open
Closed

fix(guest-panel): fail closed when getCurrentPlaylistAuth() resolves to null#1405
Grimothy wants to merge 1 commit into
m3ue:devfrom
Grimothy:fix/1398-guest-panel-null-auth-fail-open

Conversation

@Grimothy

Copy link
Copy Markdown
Contributor

Closes #1398

Bug

The three guest-panel DVR query entry points all share the same pattern: they filter on $currentAuth?->id, where $currentAuth comes from getCurrentPlaylistAuth(). When that helper returns null, Laravel's query builder translates the null right-hand side into WHERE playlist_auth_id IS NULL — which doesn't fail closed, it returns the playlist owner's records to the guest.

Affected entry points:

  • app/Filament/GuestPanel/Resources/DvrRecordings/GuestDvrRecordingResource::getEloquentQuery()
  • app/Filament/GuestPanel/Resources/DvrRules/GuestDvrRuleResource::getEloquentQuery()
  • app/Filament/GuestPanel/Widgets/GuestScheduledSeriesWidget::getSeriesRules()

Fix

Added && ! static::isOwnerAuth() to the null-auth guard in each entry point. When getCurrentPlaylistAuth() returns null AND the request is NOT in the owner-auth path (no PlaylistAuth row), return an empty result set instead of leaking the owner's records.

isOwnerAuth() is already defined in app/Filament/GuestPanel/Pages/Concerns/HasGuestDvr.php and is the canonical predicate for the owner-auth path; reusing it preserves the existing two owner-auth tests that legitimately rely on getCurrentPlaylistAuth() returning null for the playlist owner.

Tests

Added 7 regression tests across the three affected files. All assert that when getCurrentPlaylistAuth() resolves to null (stale / mismatched state), the entry point returns an empty collection rather than the playlist owner's records.

  • tests/Feature/GuestDvrRecordingResourceTest.php — table query, header stat, nav badge (3 tests)
  • tests/Feature/GuestDvrRuleResourceTest.php — table query, header stat (2 tests)
  • tests/Feature/GuestScheduledSeriesWidgetTest.phpgetSeriesRules(), nav badge (2 tests)

Verification

  • vendor/bin/pest on the three target files: 72 tests pass (86 assertions), up from 65 pre-fix
  • vendor/bin/pint --dirty --test: clean
  • Mutation check: 3 rounds, each round reverted exactly one of the three guards, each round failed only that file's new tests, the other 70 stayed green — confirms each guard is independently load-bearing

…to null

The merged m3ue#1398 fix scoped the three guest-panel DVR queries to
playlist_auth_id, but used $currentAuth?->id which silently becomes
WHERE playlist_auth_id IS NULL when the credentials no longer resolve
to a live PlaylistAuth row (e.g. revoked/disabled mid-session while
stale session credentials still exist). That matches the playlist
owner's recordings — the exact privacy leak m3ue#1398 exists to close —
now reachable through a different path.

Add an early-return guard immediately after $currentAuth is computed
in all three sites. The guard fails closed unless isOwnerAuth() returns
true: the playlist owner has no PlaylistAuth row by design (they log in
via the owner_auth fallback in PlaylistService::authenticate), so
getCurrentPlaylistAuth() legitimately returns null for them, and the
existing whereNull coercion is how their own playlist_auth_id = null
records surface. Both code paths now have a regression test.

Followup to m3ue#1398.
@sparkison

Copy link
Copy Markdown
Member

Already addressed here e967ce4 here 658fe5a and here 9b9342b

should be covered 😉

@sparkison sparkison closed this Aug 11, 2026
@Grimothy

Copy link
Copy Markdown
Contributor Author

thanks boss man

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants