Repository navigation
v3.35.4 (security)
Security
The filter() query macro could put part of a client-chosen filter key into raw SQL on a date column (MySQL). Any Livewire component that passes an unlocked public $filters array to ->filter() (the documented table pattern) was affected. Upgrade promptly.
This release also stops filter() from being used to probe columns a model hides: keys on a column in $hidden, or outside a non-empty $visible, are now ignored, and operators are limited to a fixed list.
filter() still lets a client filter any other visible column and call any named scope with the value it sends. Where that matters, pass only the keys you allow: filter(Arr::only($this->filters, ['search', 'status', 'dates'])). Do not mark a $filters that atom's table controls bind to (wire:model="filters.…") as #[Locked]: Livewire then refuses every update from them and search, filters and chips stop working. (Corrected after publication: an earlier version of this note recommended #[Locked].)
Behaviour changes (for release notes)
- Filter keys are restricted to
^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z0-9_]+)*$. A digit-leading or hyphenated column name, and a JSON path segment with-or[0], are now skipped instead of filtered. - A key with more than one
:(a:b:c) is skipped; before, the middle part was ignored. - A sub-path on a non-JSON column is skipped.
- A column in the model's
$hidden, or outside a non-empty$visible, can no longer be filtered throughfilter().$visibleis a serialisation list, so a host whose$visibleomitscreated_at,statusor foreign-key columns will have filters on them silently dropped. A host that filters on such a column on purpose must do it outsidefilter(). col:<operator>accepts only= != <> < <= > >= likeandnot like. Others (regexp,rlike,is, bitwise...) are a no-op; before, Laravel either applied them or demoted them to=and bound the operator text as the value. Operators are now case-insensitive.- Array value on a date column, on
like, nested arrays, or an array for thesearchscope: skipped; before, some of these threw. - A list on a plain column:
=or no operator iswhereIn(unchanged),!=/<>is nowwhereNotIn(it used to bewhereIn, i.e. inverted),<,<=,>,>=are skipped. On a JSON column a list means "contains all of" (whereJsonContains) for=/no operator and "does not contain all of" (whereJsonDoesntContain) for!=/<>; ordering operators are skipped. - A date object (Carbon,
DateTimeImmutable) is passed on as an object, so Laravel formats and binds it as usual:whereDate()on a date column, a normal binding on datetime and plain columns, and as sent to a scope.likewith a date object is skipped on a plain column. not likenow gets the same%value%wrapping aslike.