Is there a way to reduce data exposure by default in EditRecord and ViewRecord? #19814
Replies: 2 comments
-
|
btw if anyone else needs a still-quick-but-better fix, i'm not using this. it's still a bit hacky, but it works. this is for editrecord and a very similar function for the viewrecord page - the only difference is |
Beta Was this translation helpful? Give feedback.
-
|
For this specific issue I would focus on reducing the Livewire payload / model data that reaches the page, not only on authorization. Policies and query scopes are still important, but they do not solve the “hidden field data is present in component state/payload” problem by themselves. A practical app-level approach is to trim the data before filling the form/infolist: protected function mutateFormDataBeforeFill(array $data): array
{
return Arr::only($data, [
'name',
'email',
// fields actually used by this page
]);
}For dynamic schemas, the harder version is deriving the visible/used state paths from the schema and only keeping those keys, like the workaround above. That is probably closer to what you want. I can see why making this the default is tricky for Filament, though:
So my ideal framework-level shape would be an opt-in page/resource flag, something like “only hydrate visible/declared fields”, rather than a silent global default. That would let security-sensitive resources reduce payload exposure without breaking existing custom pages. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
From Filament\Resources\Pages\EditRecord line 145 (in mutateFormDataBeforeFill) and ViewRecord line 128 there are security advisories about how all non-hidden model attributes are sent to Livewire.
That is definitely a security risk when it comes to such things as API keys, as is mentioned in the advisory text, and it would be great if the default behaviour could be tightened up, while allowing for simple extensibility when needed.
Ideally only the attributes which are referenced directly by any form/infolist components should be sent by default, and this should be applied after any visible() or hidden() modifiers too if possible.
Alternatively, perhaps a canAccess()-type function could be added to form components that could be applied first and effectively remove that component (and hence the model attribute) completely, visible or not, and that way Livewire would still get non-visible() attributes.
This would keep the amount of data exposure to a minimum but there might be other attributes that are required by custom fields. To handle this, I'd envision something like $component->withModelAttributes('api_key', ...) to allow Livewire access to arbitrary fields, but as far as I can tell the data sent to Livewire only applies to information that needs to be visible client-side or sent/received via $get and $set, and not arbitrary $record attributes which can be referenced in PHP, and as such, I don't predict massive breakage anyway.
For now, as a quick fix in my project where my $fillable property on the models closely matches the fields I want to expose anyway, I'm using the code below, but this obviously isn't a satisfactory long-term solution.
I'm happy to take a bash at implementing any of these approaches if you think it'll benefit the project. Obviously the main risk here is breaking existing behaviour so I'm happy to hear any modifications or other approaches with potentially less impact?
Beta Was this translation helpful? Give feedback.
All reactions