Action attribute forgery

I have a wire:click(function(value,value)). Both values are passed correctly to the function in the component. However, if I change the values manually from the Chrome Inspect function, the manipulated value are passed to the component. I thought this kind of forgery was handled by Livewire automatically? Am I missing something?

Nope, Livewire will try to stop forgery if you try to directly change any of the data stored in javascript objects via a checksum. Anything you pass into a function should be treated as if it were apart of a form and you should never trust user passed data. If it’s not something you would ever let the user pick, it shouldn’t be in your html like that and you’ll need to rethink your design pattern.

1 Like

Hey, @baardisk

Look at this thread:
Livewire Security Issues

1 Like

Thanks, skywalker! A useful read.


Thank you for your input. I acknowledge your point and that it’s probably a design flaw.
Could you help me get my mind on the right track?

I have a dropdown to select the “system” to work with. This is populated with names to chose from and the value is an id which corresponds to the id in the DB. How should I get rid of the DB id?
But the complicated part (for me) is the main component. This fetches data from an external API. The data is in arrays to populate a table with column headers and row “headers”. The cells are populated with 2 items (buttons) each with on or off states. The states and changes needs to be tracked. Upon pressing save (or undo to clear the changes) the changes are sent to the external API to update.

Any pointers would be appreciated :slight_smile:

If you have it in a repo somewhere, I’d be happy to look at it tomorrow and then I can tell you how I’d personally go about it.

1 Like

Thank you! I’m sorry, but it’s not currently in any public repo. Anyway you can help me without it?

I’m currently in the process of creating a datatable and came across a similar issue.

Check out the following datatable example open up DevTools and inspect one of the delete buttons and find the wire:click action. Now, imagine you’re an administrator and have permission to delete users and you’ve had a falling out with the site owner (chances are their user ID is 1) so go ahead and update the code inside DevTools to wire:click="delete(1)" and click the button. Boom, user 1 is gone - crazy!

My solution was to turn each table row into a separate component as @xxdalexx suggested in the linked post.

@foreach ($users as $user)
    <livewire:users-table-row :user="$user">

The first problem I had was that I lost all reactivity as a result of a DOM diffing issue, which is weird because each <tr> has a unique wire:id (it mustn’t be used by Livewire when it is doing its thing). So, I added :key="$loop->index" which only half fixed the issue. When navigating to page two (paginator) $loop->index is the same therefore Livewire doesn’t update as expected.

I needed a unique ID to use for the key, so for a sanity check I used :key="$user-id" and it worked. By this time I’m scratching my head thinking that was a pointless exercise I’m back where I started with the user ID in the source code.

My solution was to use the method @skywalker mentioned :key="Crypt::encrypt($user->id)" but then I discovered something unexpected wire:key="a6d2ce3... doesn’t even exist in the code. I’m now at the point where I am using

<livewire:users-table-row :user="$user" :key="$user->id">

with a wire:click="delete" action that each component is responsible for and I can’t hijack another component and run delete by updating the code with DevTools.

I still want to delve a little deeper to see what is happening with wire:key - it’s got to be getting set somewhere.

1 Like

Hi Pom,

This i really helpful! Thanks a lot!
However; the :key="$user->id" you reference. How are you able to use that/reference it in the component? In the delete action you mentioned.

The wire:key is used by Livewire when it is trawling the DOM checking to see what data needs to be swapped out.

As for the delete function because each user model has its own component you don’t need to use the ID.

public $user:

public function mount($user)
    $this->user = $user;

public function delete()
1 Like