CVE-2026-55739: Crater: Missing Tenant-Ownership Check in CustomerPolicy Allows Cross-Company Customer Data Theft and Deletion
Crater isolates data per companyid, and its Invoice/Estimate/Payment/Expense policies enforce both a Bouncer ability check and $user->hasCompany($model->companyid). CustomerPolicy's view/update/delete methods omit the company-ownership check entirely, checking only the blanket ability. Route-model-bound customer lookups and the bulk Customer::deleteCustomers() method are similarly unscoped (self::find($id) with no company filter). Any authenticated user of one company can read, reassign (steal), or delete another company's customer records, with deletion cascading to that customer's invoices and payments.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
In CustomerPolicy, update view/update/delete methods to include a company-ownership check (e.g., verify $user->hasCompany($model->company_id) before allowing access or modifications), not only the blanket ability check.
Crater (CustomerPolicy) Tenant-ownership check in view/update/delete = Add company-ownership validation using company_id - Configuration
Ensure route-model-bound customer lookups are scoped to the authenticated user's company (rather than using self::find($id) with no company filter), so a user cannot load a customer record from another company.
Crater (Customer lookups via route model binding) Customer lookup scoping = Scope lookups by company_id - Configuration
Modify Customer::deleteCustomers() so it only deletes customers belonging to the authenticated user's company_id, rather than operating on unscoped customer records.
Crater (Customer::deleteCustomers() bulk delete) Deletion scoping = Bulk delete limited to authenticated user's company