Severity by source
AV:A/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Adjacent vector and low privileges reflect MQTT broker publish access; full CIA follows from arbitrary code execution in the application process.
Primary rating from Vendor (TuranSec).
CVSS VectorVendor: TuranSec
Lifecycle Timeline
3DescriptionCVE.org
Zigbee2MQTT's ExternalJSExtension.getFilePath() (lib/extension/externalJS.ts) joins a name parameter received via an MQTT message (topic zigbee2mqtt/bridge/request/extension/save) into the extensions base path using path.join(basePath, name) with no sanitization. Because path.join() resolves ../ sequences, a name such as ../../tmp/evil.js escapes the intended extensions directory. The extension handler only validates that the name ends in .js/.mjs/.cjs, writes the file, and then dynamically imports it via Node.js import(), achieving remote code execution. Requires the enable_external_js config option (off by default, but commonly enabled in legacy installs) and MQTT broker access, which is frequently unauthenticated in real deployments. The identical unsanitized getFilePath() is also used by the extension-removal handler, enabling arbitrary file deletion.
Articles & Coverage 1
AnalysisAI
Remote code execution and arbitrary file deletion in Zigbee2MQTT stem from an unsanitized path.join() call in ExternalJSExtension.getFilePath() (lib/extension/externalJS.ts), allowing any MQTT client with publish access to escape the extensions directory via traversal sequences and write arbitrary files to the host filesystem. Once the malicious .js file is written, Zigbee2MQTT immediately imports it via Node.js import(), executing attacker-controlled code in the application process context. The same vulnerable code path also backs the extension-removal handler, yielding a second primitive for arbitrary file deletion. No public exploit or KEV listing was identified at time of analysis, but the exploitation path is mechanically straightforward given the detailed description.
Technical ContextAI
Zigbee2MQTT (cpe:2.3:a:koenkk:zigbee2mqtt:*:*:*:*:*:*:*:*) is an open-source Node.js bridge that connects Zigbee devices to an MQTT broker, most commonly deployed on Raspberry Pi or Linux single-board computers in home automation environments. The root cause is CWE-22 (Path Traversal) in lib/extension/externalJS.ts: the getFilePath() method constructs a filesystem path with path.join(basePath, name), where name is taken directly from the MQTT message payload on topic zigbee2mqtt/bridge/request/extension/save. While path.join() normalizes the resulting path, it does not strip or reject ../ sequences - a name value of ../../tmp/evil.js resolves cleanly to a path outside the intended extensions directory. The only server-side guard is a suffix check enforcing .js, .mjs, or .cjs extensions, which is trivially bypassed by the traversal payload itself (../../tmp/evil.js satisfies the check). After writing the file, the handler invokes Node.js dynamic import() on the resolved path, converting a write-to-disk primitive directly into code execution. The getFilePath() function is shared verbatim with the extension-deletion handler, making the same traversal available as an arbitrary file deletion primitive.
RemediationAI
No vendor-released patched version was confirmed from the provided references at time of analysis; operators should monitor the Zigbee2MQTT GitHub repository at https://github.com/Koenkk/zigbee2mqtt for an official fix and upgrade immediately upon release. The most impactful compensating control is to set enable_external_js to false (its default) in the Zigbee2MQTT configuration - this removes the extension save and delete MQTT handlers entirely, eliminating the attack surface with no functional impact for deployments that do not use external JS extensions. If enable_external_js cannot be disabled, enforce MQTT broker authentication (username/password or mutual TLS) so that only trusted clients can publish to any topic; this raises the attacker's required access from adjacent-unauthenticated to adjacent-authenticated. Additionally, configure MQTT broker ACLs to restrict publish rights on zigbee2mqtt/bridge/request/extension/save to only the Zigbee2MQTT service account itself, preventing lateral abuse from other broker clients. Note that ACL-only mitigations without disabling enable_external_js leave the path traversal logic reachable from any client that can escalate MQTT privileges.
A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic
The AES-NI implementation in OpenSSL before 1.0.1t and 1.0.2 before 1.0.2h does not consider memory allocation during a
Same weakness CWE-22 – Path Traversal
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-53364
GHSA-77vh-g47p-vh46