CVE-2025-65017
Executive Summary
CVE-2025-65017 is a vulnerability in the Decidim participatory democracy framework, affecting versions from 0.30.0 to before 0.30.4 and from 0.31.0.rc1 to before 0.31.0. The core issue lies in the generation of UUIDs for private data exports. Due to a weak or flawed UUID generation algorithm, collisions can occur, meaning two different data exports could be assigned the same UUID. This can lead to a data leak where a user or process accessing a private export by its UUID might inadvertently retrieve a different user's private data. The vulnerability has been patched in versions 0.30.4 and 0.31.0.
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
Decidim is a Ruby on Rails-based framework distributed as a Ruby gem. The vulnerability exists within the core framework's export functionality. Users of the Decidim gem are affected if they are running a vulnerable version. The supply chain risk is moderate, as the vulnerability is in the application logic itself, not in a third-party dependency. However, any application built on a vulnerable Decidim version is at risk. The patch is available in the official Decidim repository and gem releases.
CVSS Breakdown & Threat Level
The CVSS score is listed as 0.0, which is likely a placeholder or uncalculated. Based on the description, a reasonable assessment would be:
- Attack Vector (AV): Network (N) - The export functionality is typically accessed over the network.
- Attack Complexity (AC): Low (L) - Exploiting a UUID collision does not require special conditions.
- Privileges Required (PR): Low (L) - An attacker would need a valid user account to trigger an export and then attempt to access another user's data.
- User Interaction (UI): None (N) - The attack does not require another user to perform an action.
- Scope (S): Changed (C) - The vulnerability can allow an attacker to access data outside their intended authorization scope.
- Confidentiality (C): High (H) - Private data of other users can be exposed.
- Integrity (I): None (N) - The vulnerability does not allow data modification.
- Availability (A): None (N) - The vulnerability does not affect system availability.
Estimated CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Estimated Base Score: 7.7 (High)
Threat Level: High. While the EPSS score is 0.0% (indicating no active exploitation in the wild), the potential impact of leaking private data from a participatory democracy platform is severe, involving privacy violations and potential legal ramifications.
Deep Dive & Mechanics
The vulnerability is rooted in the UUID generation logic used for naming or identifying private data export files. In a typical Decidim system, users can request exports of their personal data (e.g., comments, proposals, account data). These exports are stored with a UUID as a filename or identifier to make them unique and hard to guess.
The flaw is that the UUID generation algorithm is not sufficiently random or unique. This could be due to:
- Using a weak pseudo-random number generator (PRNG) seeded with a predictable value (e.g., time-based seed).
- Using a hash of predictable data (e.g., user ID + timestamp) without enough entropy.
- A bug in the UUID generation code that causes it to produce duplicate values under certain conditions (e.g., concurrent requests, specific server states).
When a collision occurs, two different export files (belonging to different users) end up with the same UUID. When a user or an automated process tries to download their export using that UUID, the system might serve the wrong file, exposing another user's private data.
The attack scenario:
- An attacker (User A) requests a private data export.
- The system generates a UUID for User A's export.
- Another user (User B) requests an export, and due to the collision, the system generates the same UUID.
- User A, or an attacker who can predict or brute-force UUIDs, accesses the export URL containing the collided UUID.
- The system serves User B's private data to User A.
Vulnerable vs. Patched Code
The exact code change is not publicly available in the provided data, but the fix is described as improving UUID generation. A typical vulnerable pattern might look like:
Vulnerable Code (Ruby - Decidim):
# app/services/decidim/export_service.rb
class ExportService
def generate_export_filename(user)
# Weak UUID generation using SecureRandom but with a predictable seed or limited range
uuid = SecureRandom.uuid # This is actually secure, but the vulnerability might be elsewhere
# Or a custom implementation:
# uuid = Digest::SHA256.hexdigest("#{user.id}#{Time.now.to_i}")[0..31]
# This is predictable if you know the user ID and approximate time.
"export_#{uuid}.zip"
end
end
Patched Code (Ruby - Decidim):
# app/services/decidim/export_service.rb
class ExportService
def generate_export_filename(user)
# Use a cryptographically secure random UUID
uuid = SecureRandom.uuid
# Ensure uniqueness by combining with a unique counter or database sequence
# Or use a dedicated UUID library that guarantees uniqueness
"export_#{uuid}_#{Time.now.to_f}_#{user.id}.zip"
end
end
The patched version likely ensures that the UUID is generated using a cryptographically secure random number generator and that additional entropy (like a timestamp with microseconds, a counter, or a database sequence) is added to prevent collisions.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Objective: Exploit UUID collision to access another user's private data export.
Prerequisites:
- A valid user account on a Decidim instance running a vulnerable version (e.g., 0.30.0).
- Knowledge of the export endpoint and UUID format.
Steps:
- Identify Export Endpoint: Use browser developer tools or proxy (e.g., Burp Suite) to intercept the request when a user requests a private data export. The endpoint might be something like
/users/sign_inor/account/export. - Request Export: As User A, request a private data export. Note the response, which may include a download link containing a UUID.
- Analyze UUID Pattern: Collect multiple UUIDs from your own exports. Look for patterns (e.g., time-based, sequential, limited range).
- Brute-Force or Predict UUIDs: If the UUID is predictable (e.g., based on user ID and timestamp), generate a list of potential UUIDs for other users. If it's random but collides, you may need to trigger many exports to cause a collision.
- Access Export: Use the predicted or collided UUID to construct the download URL. For example:
https://decidim.example.com/exports/export_<uuid>.zip. - Verify Data Leak: If successful, the downloaded file will contain another user's private data (e.g., comments, proposals, personal information).
Automation Script (Python - Conceptual):
import requests
import uuid
import time
# This is a conceptual script for a predictable UUID scenario
target_url = "https://decidim.example.com"
session = requests.Session()
# Login as User A
login_data = {"user[email]": "attacker@example.com", "user[password]": "password123"}
session.post(f"{target_url}/users/sign_in", data=login_data)
# Request export
export_response = session.post(f"{target_url}/account/export")
# Assume the UUID is returned in the response or a redirect URL
# For demonstration, we simulate a predictable UUID based on user ID
user_id = 1 # Target user ID
timestamp = int(time.time())
predicted_uuid = str(uuid.UUID(int=user_id * timestamp)) # Weak example
# Attempt to download
download_url = f"{target_url}/exports/export_{predicted_uuid}.zip"
response = session.get(download_url)
if response.status_code == 200:
print("Data leak successful!")
with open("leaked_data.zip", "wb") as f:
f.write(response.content)
else:
print("Failed to access export.")
Blue Team (Defense & Detection)
Objective: Detect and prevent exploitation of UUID collisions.
Steps:
- Patch Immediately: Upgrade Decidim to version 0.30.4 or 0.31.0.
- Monitor Export Logs: Enable detailed logging for export requests and downloads. Look for:
- Multiple downloads of the same export UUID by different users.
- Failed download attempts (404 errors) for export UUIDs that were never generated.
- Unusual patterns in export request frequency.
- Implement Rate Limiting: Limit the number of export requests per user per hour to reduce the chance of brute-forcing.
- Use Strong UUIDs: Ensure the application uses
SecureRandom.uuid(Ruby) or equivalent cryptographically secure random UUID generation. - Add Uniqueness Constraints: In the database, add a unique index on the export UUID column to prevent two exports from having the same UUID. This will cause an error if a collision occurs, alerting administrators.
- User Notification: If a collision is detected, notify affected users and force them to regenerate their exports.
Indicators of Compromise (IOCs)
- Network Traffic:
- Multiple requests to
/exports/export_<uuid>.zipwith different UUIDs in a short period. - Requests to export endpoints from a single user account at an unusually high frequency.
- Multiple requests to
- Log Entries:
- Application logs showing
ActiveRecord::RecordNotUniqueerrors related to the exports table. - Web server logs showing 404 errors for export UUIDs that were never generated.
- Logs showing the same export UUID being downloaded by different user sessions.
- Application logs showing
- File System:
- Export files with identical names (UUIDs) in the storage directory (if not using a database).
- User Reports:
- Users reporting that they downloaded an export and saw data that does not belong to them.
Detection Engineering
YARA Rule
rule Detect_Decidim_UUID_Collision_Exploit {
meta:
description = "Detects attempts to exploit CVE-2025-65017 by accessing export files with predictable or collided UUIDs"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-65017"
hash = "d41d8cd98f00b204e9800998ecf8427e"
strings:
$export_path = /\/exports\/export_[a-f0-9\-]{36}\.zip/i
$uuid_pattern = /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/
$decidim_cookie = "decidim_session"
condition:
$export_path and #uuid_pattern > 5 and $decidim_cookie
}
Sigma Rule
title: Decidim Private Data Export UUID Collision Exploit
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects multiple downloads of the same export UUID by different users, indicating a potential UUID collision exploit (CVE-2025-65017).
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-65017
logsource:
category: application
product: decidim
detection:
selection:
event: "export_download"
export_uuid:
- "*"
condition:
| unique_count(export_uuid) > 1 and distinct_count(user_id) > 1
falsepositives:
- Legitimate users downloading the same export file (if sharing is allowed)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-65017 Decidim UUID Collision Exploit - Multiple Export Downloads"; flow:to_server,established; content:"/exports/export_"; http_uri; pcre:"/\/exports\/export_[a-f0-9\-]{36}\.zip/i"; threshold: type both, track by_src, count 10, seconds 60; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Patch: Upgrade Decidim to version 0.30.4 or 0.31.0 immediately. This is the only complete fix.
- Invalidate Existing Exports: After patching, delete all existing private data export files and force users to regenerate them. This ensures that any collided UUIDs are no longer valid.
- Audit Logs: Review application and web server logs for any signs of exploitation (see IOCs).
Long-Term Mitigations:
- Code Review: Conduct a security code review of the UUID generation logic to ensure it uses a cryptographically secure random number generator and includes sufficient entropy.
- Database Constraints: Add a unique constraint on the export UUID column in the database to prevent duplicates.
- Monitoring: Implement monitoring for database constraint violations and unusual export download patterns.
- User Education: Inform users about the importance of reporting any suspicious activity related to their data exports.
Workarounds (if patching is not immediately possible):
- Disable the private data export feature temporarily.
- Implement a manual approval process for export requests.
- Use a web application firewall (WAF) to block requests with suspicious UUID patterns.
Valters IT
DevSecOps & Cyber Threat Intelligence