Beartropy Logo

Hacking Your Own App: Essential Security Patterns for Livewire Components

Livewire exposes your methods to the world. Learn how to secure your components against ID tampering and unauthorized actions using `#[Locked]` and Policies.

Guides 08 Jan, 2026 Beartropy Team

Livewire feels like magic because it bridges the gap between backend and frontend. But this convenience comes with a hidden risk: Every public property and method in your component is a public API endpoint.

If you are not careful, a malicious user can inspect the network payload, modify state you thought was "private", or execute actions they shouldn't have access to.

In this guide, we are going to look at three common vulnerabilities in TALL stack applications and how to fix them using modern Livewire 3 features and Beartropy best practices.


🔓 Vulnerability 1: The "Hidden Button" Fallacy

We often use Blade directives to hide actions from unauthorized users.

1 
2@if(Auth::user()->isAdmin())
3 <x-bt-button wire:click="deleteUser({{ $user->id }})" color="danger">
4 Delete User
5 </x-bt-button>
6@endif
1// ❌ INSECURE COMPONENT
2class UserTable extends Component
3{
4 public function deleteUser(User $user)
5 {
6 // If I open the browser console and type Livewire.find('...').deleteUser(5),
7 // this will execute even if I am not an admin!
8 $user->delete();
9 }
10}

The Fix: Explicit Authorization Never rely on the UI for security. Always authorize the action on the server.

1// ✅ SECURE COMPONENT
2class UserTable extends Component
3{
4 public function deleteUser(User $user)
5 {
6 // Method 1: Laravel Policy Gate
7 $this->authorize('delete', $user);
8 
9 $user->delete();
10 }
11}

🕵️ Vulnerability 2: Sensitive Data Leaks

A common mistake is storing entire Eloquent models in public properties when you only need a few fields.

1// ❌ INSECURE
2class UserProfile extends Component
3{
4 public User $user;
5}

When Livewire dehydrates this component, it sends every single column of the User model to the frontend in the JSON payload. If your user table has is_admin, stripe_id, or api_token columns, they are now visible in the browser's "View Source" or Network tab.

The Fix: DTOs or Specific Properties Only expose what the UI needs to render.

1// ✅ SECURE
2class UserProfile extends Component
3{
4 public string $name;
5 public string $email;
6 
7 public function mount(User $user)
8 {
9 $this->name = $user->name;
10 $this->email = $user->email;
11 }
12}

🔒 Vulnerability 3: ID Tampering

Imagine a component that updates a user's ID card. You might store the ID in a public property.

1class UpdateProfile extends Component
2{
3 public $userId;
4 public $name;
5 
6 public function save()
7 {
8 $user = User::find($this->userId);
9 $user->update(['name' => $this->name]);
10 }
11}

A user can use browser dev tools to change $userId from 5 to 6 and update someone else's profile.

The Fix: The #[Locked] Attribute Livewire 3 introduced a brilliant attribute that prevents the frontend from modifying specific properties.

1use Livewire\Attributes\Locked;
2 
3class UpdateProfile extends Component
4{
5 #[Locked] // 🛡️ This property cannot be tampered with from the client
6 public $userId;
7 
8 public $name;
9 
10 public function save()
11 {
12 $user = User::find($this->userId);
13 $user->update(['name' => $this->name]);
14 }
15}

🛡️ Best Practices Checklist

When building with Beartropy and Livewire, keep this checklist on your desk:

  1. Authorize Everything: Every method triggered by wire:click must have an authorization check.
  2. Lock IDs: Use #[Locked] for any ID or state that shouldn't change.
  3. Validate Inputs: Never trust $this->property without running $this->validate() first.
  4. Middleware: Ensure your routes are protected by auth and verified middleware.

Security isn't a feature; it's the foundation. Build safe apps.

Tags

#security #livewire #laravel #cybersecurity #best-practices

Comments

Leave a comment

0

No comments yet. Be the first to share your thoughts!

Share this post