Skip to content

Security: Cross-Team Invoice IDOR - Missing HasTenantScope on Invoice Model #1523

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

The Invoice model is missing the HasTenantScope trait, allowing users from Team A to access, modify, and delete invoices belonging to Team B.

Root Cause

All multi-tenant models in the application correctly use the HasTenantScope trait to scope queries to the current team:

Model HasTenantScope Status
Client ✅ Yes (line 14) Secure
Project ✅ Yes Secure
Task ✅ Yes Secure
Status ✅ Yes Secure
WorkSession ✅ Yes Secure
Contractor ✅ Yes Secure
Invoice No Vulnerable

Vulnerable file: app/Models/Invoice.php (lines 10-14)

The Invoice model uses HasFactory, SoftDeletes, and HasUlids, but NOT HasTenantScope. It has a team_id foreign key and a team() relationship, but without the global scope, Filament resource queries don't filter by team.

Impact

Any authenticated user in a different team can:

  • View another team's invoices (financial data disclosure)
  • Edit another team's invoices (data manipulation)
  • Delete another team's invoices (data destruction)

This affects the InvoiceResource in the Filament panel, where getEloquentQuery() only removes SoftDeletingScope but doesn't add team filtering.

Fix

Add the missing HasTenantScope trait to the Invoice model:

use App\Models\Scopes\HasTenantScope;

class Invoice extends Model
{
    use HasFactory;
    use SoftDeletes;
    use HasUlids;
    use HasTenantScope;  // <-- Add this

This is a one-line fix that brings Invoice in line with all other multi-tenant models in the application.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions