Locks all public properties on Livewire components by default, preventing the frontend from modifying them. Properties must be explicitly unlocked with the #[Unlocked] attribute.
In Livewire, every public property is writable from the frontend. A malicious user can open browser DevTools and send a crafted request to change any public property - even ones not bound to any input.
class Invoice extends Component
{
public int $invoiceId = 1;
public float $total = 99.99;
public string $status = 'pending';
}An attacker could send a Livewire update to set $total = 0 or $status = 'paid' without any UI interaction.
use WireElements\LivewireStrict\LivewireStrict;
// In your AppServiceProvider::boot()
LivewireStrict::lockProperties();Once enabled, all public properties are locked by default. Any frontend attempt to modify them throws a CannotUpdateLockedPropertyException.
Use the #[Unlocked] attribute on properties that should be writable from the frontend:
use WireElements\LivewireStrict\Attributes\Unlocked;
class SearchUsers extends Component
{
#[Unlocked]
public string $query = ''; // ✅ Frontend can update (e.g., wire:model)
public array $results = []; // 🔒 Locked - only server can modify
public int $totalCount = 0; // 🔒 Locked - only server can modify
}{{-- This works because $query is #[Unlocked] --}}
<input wire:model="query" type="text" placeholder="Search...">
{{-- These are display-only, protected from tampering --}}
<p>{{ $totalCount }} results found</p>If a component needs all properties writable, apply #[Unlocked] at the class level:
use WireElements\LivewireStrict\Attributes\Unlocked;
#[Unlocked]
class ContactForm extends Component
{
public string $name = ''; // ✅ Unlocked
public string $email = ''; // ✅ Unlocked
public string $message = ''; // ✅ Unlocked
}Locked properties can still be modified by server-side code. Only frontend updates are blocked.
class Counter extends Component
{
public int $count = 0; // 🔒 Locked from frontend
public function increment()
{
$this->count++; // ✅ This works - server-side update
}
}// Only components under App\Livewire\Admin
LivewireStrict::lockProperties(components: 'App\Livewire\Admin\*');
// Only a specific component
LivewireStrict::lockProperties(components: App\Livewire\Checkout::class);