mariowOS ← All bulletins

🍯 mariowOS Honeypot (1.2.0)

The mariowOS kernel was lacking authentication across almost its entire API surface and was listening on all network interfaces. This combination meant that a device on the same local network can control system functions on the user's PC without credentials. Multiple endpoints allow command execution; the existing access controls can be bypassed.

Severity Count
Critical 6
High 7
Medium 6
Low 3

What we found

πŸ”΄ CRITICAL

C-01 β€” Command execution via /api/recovery/debug without password

system/server.js:982-998

The route passes req.body.command directly to exec(). The only check is the config.allowFlashing flag; no password is required. Since the flag can be modified by another unprotected route (see C-03) and defaults to true in the distributed config.json, this check offers no real protection.

C-02 β€” Bypassable guard on /api/remote/exec

system/server.js:2615-2631

The check is if (!match && currentConfig.passwordHash). When passwordHash is null/empty (first boot, after a factory reset, or after /clear-password), the condition evaluates to false and the command is executed without verification.

C-03 β€” Privilege escalation via /save-settings

system/server.js:1084-1103

save-settings copies every key not present in the PROTECTED list (passwordHash, verified, quickSettings) into the config. Security flags like allowFlashing, frpLock, rules, and installedApps are not protected and can be set by an unauthenticated request.

C-04 β€” Complete config overwrite via /api/system/frp-unlock

system/server.js:957-977

With type:"file", the route executes config = { ...payload, frpLock:false } and overwrites config.json from unauthenticated input: this allows injecting an arbitrary passwordHash and bypassing the FRP lock.

C-05 β€” Unauthenticated factory reset and wipe

system/server.js:1136+ (/api/system/factory-reset) and :938 (/api/recovery/wipe)

Both routes delete files and clear the config without any authentication. Aside from direct damage (data loss), they bring the state to "no password," reopening C-02.

C-06 β€” Path traversal in sandbox β†’ out-of-bounds write/execution

system/server.js:1434-1470 (/api/sandbox/upload, /api/sandbox/start)

The vmId from the request is concatenated into paths (path.join(sandboxBaseDir, vmId, "disk")) without validation. Then, /api/sandbox/start writes a wrapper and executes node in the resulting directory.


🟠 HIGH

A-01 β€” Server listens on all interfaces

system/server.js:2887 β€” app.listen(PORT) lacks a host parameter (though the log prints 127.0.0.1).

A-02 β€” No session authentication on the API

All /api/* routes except /api/remote/exec lack any verification; /login only returns the desktop HTML and does not establish a session.

A-03 β€” Arbitrary host filesystem read via /device

resolveDevicePath :2655 + GET /api/system/files/content

/device exposes the entire host filesystem for reading via HTTP; sensitive user files (keys, configs, saved credentials) can be read by a network caller.

A-04 β€” Command injection in system helpers

:594/790 (Wi-Fi), :831/886 (Bluetooth), :1837 (extractCmd), :491 (volume)

Request inputs (SSID, MAC, device name, zip path) are interpolated into strings passed to exec().

A-05 β€” Access-Control-Allow-Origin: * on update streams

:2392, :2464 β€” Any website opened by the user can interact with these streams.

A-06 β€” Rules engine executes arbitrary commands (persistence)

:1729 case 'run': exec(params.command) β€” Rules are saved via /api/rules/save (:1673) without authentication and triggered by node-cron.

A-07 β€” Supply chain: Remote code executed without verification

:1454 git clone of arbitrary URLs, :1296/1318 git pull, OTA/SOTA updates, respawn :2300

Remote code and zip files are downloaded and executed without signature or checksum verification.


🟑 MEDIUM


πŸ”΅ LOW


What we patched

Implemented in this batch (system/server.js unless noted):

Implemented β€” Second Batch:

New Features:

Implemented β€” Third Batch (User-Side Hardening):

Implemented β€” Fourth Batch: