CVE-2026-71268 Overview
CVE-2026-71268 is a path traversal vulnerability [CWE-22] in OpenPLC Runtime v3 that leads to remote code execution. The compile_program() function in webserver/openplc.py parses (*FILE:path content*) directives inside uploaded Structured Text (.st) files and writes referenced content to os.path.join('./core', file_path) without validating that file_path remains inside the ./core directory. Authenticated attackers can write arbitrary files anywhere the runtime process can reach. OpenPLC also ships with hardcoded default credentials (openplc:openplc), which lowers the barrier to authenticated access.
Critical Impact
Authenticated attackers can achieve remote code execution as the OpenPLC runtime user by writing attacker-controlled files to sensitive locations such as /etc/cron.d/ or ~/.ssh/authorized_keys.
Affected Products
- OpenPLC Runtime v3 (webserver/openplc.py)
- Deployments relying on the default openplc:openplc credentials
- Environments where the runtime process has write access outside ./core
Discovery Timeline
- 2026-08-05 - CVE-2026-71268 published to NVD
- 2026-08-05 - Last updated in NVD database
Technical Details for CVE-2026-71268
Vulnerability Analysis
OpenPLC's web interface accepts Structured Text program uploads for compilation. During processing, compile_program() scans the file for (*FILE:path content*) directives, treats the first token as a destination path, and writes the remaining content to disk. The join is performed with os.path.join('./core', file_path), which does not neutralize traversal sequences. When file_path begins with ../ or an absolute path, Python's os.path.join discards the base directory or lets the traversal escape it.
The codebase already contains a defensive helper, validate_file_path(), in webserver/credentials.py, but compile_program() never calls it. The sink is therefore reachable directly from any authenticated upload. Because OpenPLC ships with the hardcoded operator account openplc:openplc, exploitation frequently requires no prior credential compromise on installations left at defaults.
Root Cause
The root cause is missing path canonicalization and containment checking before a filesystem write. The developer-supplied path is trusted verbatim, and the existing validator is not wired into the compilation pipeline.
Attack Vector
An authenticated user uploads a crafted .st file containing a directive such as (*FILE:../../../etc/cron.d/x * * * * root <command>*). The runtime writes the payload to /etc/cron.d/x, and cron executes the embedded command on its next schedule. Attackers can alternatively target authorized_keys, systemd unit files, or Python module paths loaded by the runtime to obtain code execution.
No verified proof-of-concept code has been published. See the OpenPLC webserver script for the vulnerable sink.
Detection Methods for CVE-2026-71268
Indicators of Compromise
- Newly created files in /etc/cron.d/, /etc/cron.hourly/, or user .ssh/authorized_keys written by the OpenPLC runtime process
- .st uploads containing the substring (*FILE: combined with ../ or absolute paths
- Unexpected child processes spawned by cron or sshd shortly after an OpenPLC upload event
- OpenPLC web sessions authenticated with the default openplc account from unfamiliar source addresses
Detection Strategies
- Inspect uploaded Structured Text files for (*FILE: directives whose path contains .., /, or references outside the intended project directory.
- Baseline the OpenPLC installation directory and alert on writes performed by the runtime process outside ./core.
- Correlate authentication events for the OpenPLC web interface with subsequent filesystem changes in privileged directories.
Monitoring Recommendations
- Enable Linux audit rules (auditd) on /etc/cron.d, /etc/cron.hourly, and SSH key directories, filtering by the OpenPLC service UID.
- Forward OpenPLC web server logs and host process telemetry to a centralized SIEM for correlation of upload, compile, and post-compile execution events.
- Track use of the default openplc:openplc credentials and alert on any successful login using that account.
How to Mitigate CVE-2026-71268
Immediate Actions Required
- Remove the default openplc:openplc account or rotate its password to a strong, unique value before exposing the interface.
- Restrict network access to the OpenPLC web interface to trusted management networks using firewall rules or a reverse proxy with authentication.
- Run the OpenPLC runtime under a dedicated, unprivileged service account that cannot write to /etc/cron.d, SSH key directories, or system binaries.
- Audit recent .st uploads and the filesystem for unexpected files created by the runtime process.
Patch Information
At the time of publication, no vendor patch is referenced in NVD. Track the OpenPLC project repository for fixes that route compile_program() through validate_file_path() or an equivalent containment check.
Workarounds
- Apply a local patch that rejects any (*FILE:...*) directive whose resolved path escapes the ./core directory using os.path.realpath comparison.
- Deploy the runtime inside a container or chroot with a read-only root filesystem and a writable path limited to ./core.
- Use mandatory access controls (AppArmor or SELinux) to constrain the OpenPLC process to its installation directory.
# Example AppArmor-style containment for the OpenPLC runtime
# Allow writes only inside the OpenPLC install path
/opt/openplc/core/** rw,
deny /etc/** w,
deny /root/** w,
deny /home/*/.ssh/** w,
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

