Laravel Livewire is absolute magic for building reactive interfaces. However, with great reactivity comes great security responsibility. A very common security oversight for developers is leaving backend component public properties exposed to client-side manipulation.
Today, I want to talk about how this happens in Livewire 4 and how we can enforce a "Secure by Default" pattern with zero effort.
🚨 The Blind Spot: Client-Side Tampering
By default, all public properties in a Livewire component are part of the component's state and can be modified from the front-end (via browser dev tools or intercepted requests).
Consider this innocent-looking component:
class UserDashboard extends Component {
public string \$name = 'Jane Doe';
public string \$role = 'member'; // ⚠️ Vulnerable!
// ...
}
If you don't explicitly validate or authorize every single request touching $role, a malicious user can easily payload-inject role = 'admin' through their browser. Remembering to protect every sensitive property across dozens of files creates huge cognitive load and introduces human error.
✅ The Elegant Solution: Auto-Lock Everything
To solve this pain point entirely, I built and published an open-source package: Livewire Secure Properties.
It completely flips the default security model of Livewire 4: Everything is locked and immutable from the client-side unless you explicitly mark it as unlocked.
You no longer have to guess what's exposed. Your backend state stays secure out of the box, throwing a 403 PropertyLockedException the moment any unauthorized client-side update is attempted.
🛠️ Installation
You can drop this into your Livewire 4 project instantly via Composer:
composer require janecodelife/livewire-secure-properties
🔓 How to Use It
The package offers a zero-configuration experience. It fully supports both Livewire 4's native Single File Components (SFC) and traditional Class-based layouts.
To open up specific properties for data-binding (like form inputs bound to wire:model), simply apply the #[Unlocked] attribute:
1. Single File Components (SFC)
<?php
use Livewire\Component;
use JaneCodeLife\LivewireSecureProperties\Unlocked;
new class extends Component {
// 🔒 SECURED: Auto-locked by default. Front-end manipulation triggers a 403 error.
public string \$role = 'admin';
// 🔓 UNLOCKED: Safe and open for client-side wire:model updates
#[Unlocked]
public string \$name = 'Jane Doe';
};
?>
<div>
<input type="text" wire:model.live="name">
<p>Name: {{ \$name }}</p>
</div>
2. Multiple File Components (Class-based)
use Livewire\Component;
use JaneCodeLife\LivewireSecureProperties\Unlocked;
class UserProfile extends Component
{
public string \$userId = '12345'; // 🔒 Locked by default
#[Unlocked]
public string \$bio = 'Software Engineer'; // 🔓 Unlocked for editing
public function render() {
return view('livewire.user-profile');
}
}
🔗 Repo Link
- 🔗 GitHub Repository: janecodelife/livewire-secure-properties
- 💖 Official Support Page: Sponsor janecodelife on GitHub
🔗 My Other Plugins
Check out my other open-source tools to supercharge your Neovim environment:
- livewire-secure-properties - Secure livewire app properties by default and void headache.
- todo-tracker.nvim - Assign and list app todos in a blink
- folders-bookmark.nvim - Bookmark folders and accessing them by keymap in a blink
- copy-history.nvim - Access your copy (Yank) history and paste it again with support of edit by 1 click in a blink.
- rest-client.nvim - run http request from anywhere in a blink
- smart-window-focus.nvim - resize split window on focus to be full size to easy to see and debug.
- markdown-toc.nvim - access markdown file headings (Table Of Content)
- tiny-textobject.nvim - handle text objects (inner/around) without need for Tree-sitter.
Top comments (0)