DEV Community

Cover image for Filament v4.12 and v5.7: 92% Faster Forms, and the Security Fixes You Still Have to Turn On
Hafiz
Hafiz

Posted on • Originally published at hafiz.dev

Filament v4.12 and v5.7: 92% Faster Forms, and the Security Fixes You Still Have to Turn On

Originally published at hafiz.dev


Filament shipped its biggest performance release since the v4 launch on August 6. Versions v4.12.6 and v5.7.6 promote the beta the team asked the community to test in late June onto the stable channels for both major versions, and the headline numbers are real: form fields render up to 92% faster, tables up to 52% faster, all in a non-breaking minor release.

So run composer update. Today. The same release resolves what the team describes as a handful of CVEs, and staying behind on a release with security content is not a position you want to defend.

But here's the thing the announcement undersells, and the reason this post exists: two of the three new security features in this release do nothing until you write code. Updating gets you the patched vulnerabilities and all of the performance. It does not turn on the CSV formula-injection protection, and it does not sanitize a single CSS color value. If you read "please update to keep your application secure" and stop there, you'll be running the new version with the new protections sitting unused.

Let's take the release apart properly: what's automatic, what's opt-in, and what the benchmark numbers actually mean for a real admin panel.

The performance numbers, and what they measure

The team published internal benchmarks with the release, and they're worth reading precisely because of what they measure: median render time per component, not page load.

For forms and schema components:

Component Previous Now Change
TextInput 0.559 ms 0.044 ms ~92% faster
Select 0.634 ms 0.052 ms ~92% faster
FileUpload 0.586 ms 0.083 ms ~86% faster
Repeater (10 items, 2 fields) 28.077 ms 2.885 ms ~90% faster
Checkbox 0.314 ms 0.033 ms ~90% faster

Half a millisecond per text input doesn't sound like much until you multiply it by a real resource form, the kind you end up with on any serious admin dashboard. Thirty fields at ~0.5 ms each was 15 ms of pure framework rendering overhead before your queries, your Livewire round trip, or your validation ran at all. That's now about 1.5 ms. And every Livewire interaction that re-renders the form pays this cost again, so the win compounds across a session, not just on first load.

The Repeater row is the one that matters most in practice. Repeaters are where Filament forms get heavy: line items on an invoice, variants on a product, questions on a quiz. Going from 28 ms to under 3 ms for a ten-item repeater changes the feel of exactly the forms people complain about.

Tables got a second pass too (the team already did a big tables performance round in an earlier version):

Scenario Previous Now Change
50 rows, 5 TextColumns, 3 row Actions 27.53 ms 13.11 ms ~52% faster
50 rows, 5 columns, 1 ActionGroup with 3 Actions 33.09 ms 16.73 ms ~49% faster

One honest caveat the team includes and most coverage will drop: these are internal development benchmarks, and your results will vary. Component-level medians are a fair way to measure framework overhead, but your panel's bottleneck might still be an N+1 query the renderer can't save you from.

How they did it, and why it's a little funny

The forms speedup comes from ripping out Blade component rendering paths and replacing them with direct PHP rendering. The pull request is refreshingly blunt about the technique: large portions of repeated Blade component calls were replaced with, in the team's own words, our dear friend the old <?php tag.

There's a real lesson in that. Blade components are a beautiful authoring experience, and every single one carries framework overhead: resolving the component class, building the data array, rendering the view. That cost is invisible until you're rendering hundreds of them per request, which is exactly what a Filament form does. The fastest Blade component is the one you don't render, and the Filament team just applied that at framework scale. If you've ever profiled a slow Filament page and wondered why so much time sat inside view rendering rather than your own code, this release is the answer arriving.

The tables work is subtler: lighter rendering paths for common actions, more efficient attribute handling, and per-record caching of visibility and authorization decisions. That last one deserves a highlight. If your table calls a policy or a visibility closure per action, per record, those decisions were being recomputed repeatedly within a single render. Now they're cached per record. Tables with lots of conditional visibility and authorization logic, which describes most serious multi-user panels, benefit the most. If your panel gates actions by role or tenant the way I set up in the SaaS panel guide, this is the part of the release working for you.

The security half, sorted by what actually happens when you update

This is where the release notes needed a second read. Sorted by what you get automatically versus what you have to do:

Automatic when you update: the patched CVEs. The release resolves several vulnerabilities. The team hasn't itemized them in the announcement beyond "a handful of CVEs", which is normal for coordinated disclosure, and it's also the entire argument for updating now rather than during next month's maintenance window.

Also already in if you're current: the MFA ordering fix. A week before this release, v4.12.5 and v5.7.5 quietly shipped a fix titled "Check panel access before presenting MFA challenge." Before that patch, the MFA challenge screen could be presented before panel authorization ran. If you use Filament's multi-factor authentication, that ordering fix alone justified the update, and it rode in with no announcement at all.

Opt-in: CSV formula-injection protection. When a spreadsheet app opens a CSV, cell values starting with =, -, +, or a tab character can execute as formulas. An attacker who controls a value that ends up in your admin export (a display name, a note field) can plant a formula that fires on the machine of whoever opens the file. Filament now ships protection that prefixes dangerous cells with a " so they stay text.

It's off by default, and for a defensible reason: legitimate values like international phone numbers start with +, and silently rewriting them would corrupt real exports. The team made the right call. But that means the protection only exists in panels where someone consciously enabled it, and "someone" is you, this week, for every exporter that includes user-controlled text.

Manual: CSS color sanitization. There's a new Str::sanitizeCssColor() helper for the case where user input ends up inside a style="" attribute. A malicious "color" value can break out of the attribute and inject extra CSS or attributes. The helper closes that, but it's a helper. It sanitizes nothing until you call it at your injection points. Grep your custom columns, entries, and blade views for style= interpolations before deciding you don't have any.

Configure it: query builder limits. New maxRules() and maxNestingDepth() methods bound how many rules and how much nesting the Query Builder accepts, enforced in the UI and against tampered payloads. The team files this under performance, but read the failure mode: a hand-crafted payload with an enormous rule tree could previously burn CPU and memory until response times cratered or the server fell over. That's a denial-of-service vector through a form, and if you expose the Query Builder to any non-admin user tier, setting these limits is a security decision, not a tuning knob.

So the accurate summary of this release is: the performance is free, the patched CVEs are free, and the three new defenses are tools you now own but haven't picked up. Update first, then budget fifteen minutes for the checklist below.

The fifteen-minute audit after updating

  1. Grep for CSV exporters. Anywhere you export tables containing user-controlled text, enable the formula-injection protection, then check whether any legitimate values (phone numbers, negative amounts) get mangled and handle those columns explicitly.
  2. Grep for style= interpolations. Custom columns, infolist entries, and blade views that build inline styles from stored values get wrapped in Str::sanitizeCssColor().
  3. Bound your query builders. If non-admin users can touch a Query Builder, set maxRules() and maxNestingDepth() to the most restrictive values your real use cases allow.
  4. Confirm you're on at least .5 of your branch. That's the MFA ordering fix. The current .6 includes it.
  5. Re-run your slowest panel page and enjoy. No action needed, this one's the reward.

The quality-of-life additions worth knowing

The release also carries a set of smaller changes, a few of which solve real irritations. User and tenant menu items can now be registered in groups instead of one flat list, and the menu actions get memoized once per request as a bonus. Nested modals get modalDismissesParentActions(), so closing an inner modal can abandon a whole multi-step flow instead of forcing users to close each layer individually. Chart widgets can define proper empty states, which finally distinguishes "no data yet" from "broken". And a scattering of dynamic configuration wins: panel content width, sidebar width, dark mode availability, and the theme switcher can all take closures at runtime now, and navigation children can reference parents by a stable key instead of the displayed label, which stops translations from silently breaking your nav hierarchy.

None of these changes the argument for updating, but the grouped menus and the stable navigation keys are the kind of small fixes that let you delete workarounds from real codebases.

Should you update today?

Yes, and this is an easier call than most minor releases.

The case is unusually clean: it's a non-breaking minor on both branches, the beta ran in community applications for over a month before promotion, there's security content, and the performance work requires zero code changes to benefit from. The team explicitly designed the release so the upgrade is nothing more than bumping to the next minor version.

Two groups should look slightly closer before hitting update in production. If you maintain a panel with heavy custom theming or custom field components, the rendering path changed underneath you, so click through your custom components in staging first; direct PHP rendering should be visually identical, but "should" is doing work in that sentence when your CSS targets Blade component markup. And if you maintain or depend on plugins, check them against the new version before rolling out, since anything that hooked into the old rendering paths is the most likely thing to notice the refactor. Maintaining a Filament billing plugin myself, running the plugin test suite against both new branches is the first item on my list before shipping the bump to clients.

If you're still on v3, this release doesn't reach you, and that's the quiet message in it: the performance investment is going into v4 and v5 only. The earlier security round in June patched v3.3 alongside v4 and v5, so v3 still gets security fixes, but the gap between the branches just got wider. If you've been deferring the upgrade decision, the v5 breakdown I wrote at release covers what the jump involves, and this release just added 92% faster forms to the "upgrade" side of the ledger.

FAQ

Do I get the performance improvements without changing any code?

Yes. The rendering optimizations are internal to Filament. Update to v4.12.6 or v5.7.6 and every form, schema component, and table renders through the faster paths automatically.

Is the CSV formula-injection protection enabled by default?

No, it's deliberately opt-in, because prefixing cells that start with characters like + would corrupt legitimate values such as international phone numbers. You need to enable it for your exports and verify your real data survives it.

Which versions contain the MFA fix?

The "check panel access before presenting MFA challenge" fix shipped in v4.12.5 and v5.7.5 on July 31. The current v4.12.6 and v5.7.6 include it. If you're on any earlier patch of these branches and use Filament's MFA, update now.

Does this release affect Filament v3?

No. The performance work and the new security features target v4.12 and v5.7 only. The June security round was the last one to include a v3 patch (v3.3.52). If you're on v3, the case for planning the v4/v5 upgrade keeps getting stronger.

Will the update break my custom theme or plugin?

The release is designed as a non-breaking minor, and it went through a month-long community beta. That said, the forms refactor replaced Blade component rendering with direct PHP rendering, so custom components and CSS that target Filament's internal markup deserve a staging pass before production.

Wrapping up

This is what a good maintenance release looks like: a real performance refactor, security content, and no breaking changes, shipped through a public beta rather than straight to stable. The one improvement I'd ask of the announcement is honesty of emphasis. "Update to keep your application secure" is true for the CVEs and incomplete for the rest, because the most interesting defenses in this release are ones you have to reach for.

So do both halves. Run the update today, then spend the fifteen minutes on the audit. The panels that get the full value of this release are the ones where someone read past the benchmark tables.

Top comments (0)