Skip to main content
Vulnerability Database/CVE-2025-54962

CVE-2025-54962: OpenPLC Runtime File Upload Vulnerability

CVE-2025-54962 is a file upload vulnerability in OpenPLC Runtime that allows authenticated users to upload arbitrary files through /edit-user endpoint. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2025-54962 Overview

CVE-2025-54962 is an arbitrary file upload vulnerability in the OpenPLC Runtime 3 webserver through commit 9cd8f1b. The /edit-user endpoint accepts uploaded files from authenticated users without validating file type or content. Uploaded files, including .html and .svg payloads, become publicly accessible under the /static URI. This creates a vector for stored cross-site scripting and content injection against other users of the web interface. The weakness is tracked as CWE-434: Unrestricted Upload of File with Dangerous Type.

Critical Impact

Any authenticated OpenPLC user can upload attacker-controlled HTML or SVG files that execute in the browsers of other users accessing the /static path.

Affected Products

  • OpenPLC Runtime 3 (through commit 9cd8f1b53a50f9d38708096bfc72bcbb1ef47343)
  • OpenPLC webserver component (webserver/pages.py)
  • Deployments exposing the OpenPLC web management interface

Discovery Timeline

  • 2025-08-04 - CVE-2025-54962 published to the National Vulnerability Database (NVD)
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-54962

Vulnerability Analysis

OpenPLC Runtime 3 ships a Flask-based web management interface that lets authenticated operators administer users through the /edit-user route. The handler processes a file upload field intended for user profile images but does not restrict the uploaded MIME type, extension, or content.

The runtime writes the uploaded file into the webserver's static directory, which Flask serves directly to any client that requests the matching /static/<filename> URL. An attacker with any valid account can therefore place arbitrary HTML, SVG, or JavaScript-bearing content inside the application's served static namespace.

Because the file is hosted on the same origin as the OpenPLC web interface, retrieving it executes script in the application's security context. This enables session theft, forced actions against the PLC runtime, and pivoting to control logic that drives industrial processes.

Root Cause

The root cause is missing allow-list validation in the /edit-user handler at webserver/pages.py (see the OpenPLC source reference). The route trusts the client-provided filename and content, then stores the file under a publicly served path without sanitization.

Attack Vector

Exploitation requires network access to the OpenPLC web interface and a low-privilege authenticated session. The attacker submits a crafted multipart POST to /edit-user containing a malicious .html or .svg file. Any user who later loads the resulting /static/<file> URL triggers execution of the attacker's payload. Technical reproduction steps are documented in the public OpenPLC Insecure File Upload repository.

Detection Methods for CVE-2025-54962

Indicators of Compromise

  • Unexpected .html, .htm, .svg, .js, or .xml files inside the OpenPLC webserver/static/ directory.
  • Access log entries showing POST requests to /edit-user from low-privilege accounts followed by GET requests to new /static/ paths.
  • Outbound HTTP requests from administrator browsers to attacker-controlled domains shortly after visiting an OpenPLC /static/ URL.

Detection Strategies

  • Monitor filesystem changes under the OpenPLC static directory and alert on write events for non-image extensions.
  • Inspect webserver access logs for POST requests to /edit-user paired with uploads of unusual content types.
  • Hunt for stored XSS artifacts by scanning files in webserver/static/ for <script>, onload=, or javascript: substrings.

Monitoring Recommendations

  • Forward OpenPLC webserver logs and host telemetry to a centralized SIEM for correlation across upload, access, and process events.
  • Baseline the normal contents of the static directory and alert on deviations.
  • Track authentication activity for OpenPLC accounts and flag new or dormant users that interact with /edit-user.

How to Mitigate CVE-2025-54962

Immediate Actions Required

  • Remove network exposure of the OpenPLC web interface from untrusted segments and restrict it to engineering workstations.
  • Rotate credentials for all OpenPLC accounts and remove unused users.
  • Audit the webserver/static/ directory and delete any files not placed there by legitimate administration.

Patch Information

No vendor-released fixed version is referenced in the NVD entry at the time of publication. Operators should track the upstream OpenPLC_v3 repository for commits that add server-side validation to the /edit-user handler and apply those changes once available.

Workarounds

  • Place OpenPLC behind a reverse proxy that blocks POST requests to /edit-user or strips uploads of non-image content types.
  • Serve the static path with a Content-Security-Policy and X-Content-Type-Options: nosniff header to limit script execution from uploaded files.
  • Restrict account creation and limit the admin role to a minimal set of operators who require it.
bash
# Example nginx reverse-proxy rule to block uploads to /edit-user
location = /edit-user {
    limit_except GET { deny all; }
    proxy_pass http://127.0.0.1:8080;
}

# Enforce safe handling of files served from /static
location /static/ {
    add_header X-Content-Type-Options "nosniff" always;
    add_header Content-Security-Policy "default-src 'none'; img-src 'self'; style-src 'self'" always;
    proxy_pass http://127.0.0.1:8080;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.