Skip to content
Pro Analyzer — Available with ShieldCI Pro

Filament Navigation Analyzer

Analyzer IDCategorySeverityTime To Fix
filament-navigation🛡️ SecurityMedium10 minutes

What This Checks

Validates that Filament navigation items have proper permission gates. Checks for:

  • Resources hidden via shouldRegisterNavigation() but missing canAccess() - the URL remains directly reachable
  • canAccess() or shouldRegisterNavigation() that only checks authentication, not authorization (weak gate)
  • Resources with sensitive navigation groups (e.g., "Admin", "System", "Users") that have no visibility gate
  • Navigation badges that may leak count information without authorization
  • Custom navigation items in panel providers without visibility controls

Why It Matters

  • Security by Obscurity Fails: Hiding a navigation item does not protect the route: users can still reach it via direct URL. shouldRegisterNavigation() only controls sidebar visibility; canAccess() is required for actual route protection.
  • Weak Gates: canAccess() returning true or auth()->check() allows any authenticated panel user to access sensitive resources regardless of their role or permissions.
  • Information Disclosure: Navigation badges showing counts (e.g., "42 Users") leak data to unauthorized users.
  • Attack Surface: Visible admin navigation reveals application structure to potential attackers.

How to Fix

Quick Fix (5 minutes)

Add visibility controls to sensitive resources:

php
// app/Filament/Resources/UserResource.php
class UserResource extends Resource
{
    public static function shouldRegisterNavigation(): bool
    {
        return auth()->user()?->hasRole('admin');
    }
}

Proper Fix (10 minutes)

1. Control badge visibility:

php
class OrderResource extends Resource
{
    public static function getNavigationBadge(): ?string
    {
        if (!auth()->user()?->can('viewAny', Order::class)) {
            return null;
        }

        return static::getModel()::where('status', 'pending')->count();
    }
}

2. Add visibility to custom navigation items:

php
// In your PanelProvider
->navigationItems([
    NavigationItem::make('Analytics')
        ->url('/analytics')
        ->icon('heroicon-o-chart-bar')
        ->visible(fn () => auth()->user()?->hasPermission('view-analytics')),
])

3. Control navigation group visibility:

php
class PaymentResource extends Resource
{
    protected static ?string $navigationGroup = 'Finance';

    public static function shouldRegisterNavigation(): bool
    {
        return auth()->user()?->hasRole(['admin', 'accountant']);
    }
}

References