Skip to content

[Bug]: Potential Denial of Service in script mirror synchronization due to incomplete RegExp escaping #2239

@WiiiiillYeng

Description

@WiiiiillYeng

I'm sure that

  • This issue is still present in the current beta version of this adapter
  • There is no other (open) issue with the same topic (use the search!)
  • This issue is not described in the adapter documentation / FAQ (read the docs!)

Script type

JavaScript

The problem

Hi, I would like to report a potential denial-of-service issue in the script filesystem mirror feature.

In build/lib/mirror.js, the mirror synchronization code builds dynamic regular expressions from DB and filesystem path segments while only escaping . characters:

const reg = new RegExp(`${pathDB.replace(/\./g, '\\.')}\\.[^.]+$`);

A similar pattern also exists in _getFilesInPath(). Because other RegExp metacharacters are not escaped, a crafted path segment such as ( can make new RegExp(...) throw a SyntaxError. The exception is not caught around the recursive mirror synchronization flow, so initialization/synchronization can be interrupted.

Preconditions

The issue requires all of the following conditions:

  • The iobroker.javascript script filesystem mirror feature is enabled via mirrorPath.
  • The active instance is javascript.0, since mirror synchronization is only enabled for that namespace.
  • An attacker or lower-privileged process can create files/directories under the configured mirror path, or can create crafted script.js.* objects through another trusted integration path.

Impact

An attacker who can create a crafted directory name under the mirror path can cause mirror startup/synchronization to fail with an uncaught SyntaxError. This can result in a denial of service for the script mirror functionality: the synchronization process is interrupted before it can complete, and the same failure can be triggered again as long as the crafted path remains present.

In a real deployment this may prevent script mirroring from completing and may affect adapter startup or availability of the mirror feature. Depending on how the adapter process is supervised, the uncaught exception may also lead to a crash/restart loop until the malicious directory or object is removed.

Other RegExp metacharacters such as | or [ may also alter matching semantics and cause incorrect object/file selection during synchronization.

Proof of Concept

I verified this against the installed package by calling the real Mirror class from iobroker.javascript, not by reimplementing the vulnerable code.

The test harness creates two mirror directories:

  • A normal comparison path: demo_mirror_normal/safe/a.js
  • A malicious path: demo_mirror_malicious/(/a.js

The harness provides a minimal ioBroker adapter stub and instantiates the real package code from:

require("node_modules/iobroker.javascript/build/lib/mirror.js")

The normal path initializes successfully. The malicious path is mapped by the package to:

script.js.(.a
script.js.(

When mirror synchronization recurses into script.js.(, the package constructs an invalid regular expression and throws.

Observed output:

[normal] setup complete
[normal] mirrorRoot: E:\Vulnerability_bypass_Verify\verify_iobrokerjavascript\demo_mirror_normal
[normal] payload file: E:\Vulnerability_bypass_Verify\verify_iobrokerjavascript\demo_mirror_normal\safe\a.js
[normal] Starting real Mirror initialization...
[normal info] Watch E:/Vulnerability_bypass_Verify/verify_iobrokerjavascript/demo_mirror_normal/safe/
[normal info] Watch E:/PythonProject/Project_sunyc/Vulnerability_bypass_Verify/verify_iobrokerjavascript/demo_mirror_normal/
[normal] Result: OK, Mirror initialized without regex failure.

[malicious] setup complete
[malicious] mirrorRoot: E:\Vulnerability_bypass_Verify\verify_iobrokerjavascript\demo_mirror_malicious
[malicious] payload file: E:\Vulnerability_bypass_Verify\verify_iobrokerjavascript\demo_mirror_malicious\(\a.js
[malicious] Starting real Mirror initialization...

[DoS observed] Mirror initialization threw an uncaught exception.
SyntaxError: Invalid regular expression: /script\.js.(\.[^.]+$/: Unterminated group

Result: VULNERABLE
The real package built a dynamic RegExp from an unescaped mirror path segment.

Suggested Fix

Escape all RegExp metacharacters before interpolating path-derived values into new RegExp(...).
Then use the escaped value in both _getObjectsInPath() and _getFilesInPath().

It may also be useful to add regression tests for path segments containing characters such as (, ), [, |, and +.

iobroker.current.log (in debug mode!)

No response

Version of nodejs

v24.11.0

Version of ioBroker js-controller

xxx

Version of adapter

9.2.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions