T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/install.sh:9
- Finding
- Root System Service Executes User-Writable JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `scripts/install.sh:9-10, 37-62` **Vulnerability Type**: Privilege escalation through a root service executing user-controlled code; persistent system service **Risk Level**: Critical ### Vulnerable Code ```bash ROUTER_DIR="$HOME/.openclaw/workspace/router" SERVICE_NAME="iblai-router" mkdir -p "$ROUTER_DIR" cp "$SKILL_DIR/server.js" "$ROUTER_DIR/server.js" NODE_BIN=$(which node) sudo tee /etc/systemd/system/$SERVICE_NAME.service > /dev/null << EOF [Unit] Description=iblai-router - Cost-optimizing Claude model routing After=network.target [Service] Type=simple ExecStart=$NODE_BIN $ROUTER_DIR/server.js Environment=ANTHROPIC_API_KEY=$API_KEY Environment=ROUTER_CONFIG=$ROUTER_DIR/config.json Environment=ROUTER_PORT=$PORT Environment=ROUTER_LOG=1 Restart=always RestartSec=3 [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now "$SERVICE_NAME" ``` ### Technical Analysis The installer creates a system-wide systemd unit but does not define a `User=` or `Group=` directive. System services run as root by default. The service therefore launches Node.js with root privileges. The executed `server.js` file is stored under the installing user's home directory at `~/.openclaw/workspace/router/server.js`. That location remains writable by the unprivileged user. This violates a fundamental privilege-boundary requirement: a privileged service must not execute code that a less-privileged user can modify. The router only needs to listen on `127.0.0.1:8402`, an unprivileged port, read its configuration, and make outbound HTTPS requests. Root access is not necessary for its declared functionality. Although persistent execution is relevant to operating a proxy, system-wide root persistence exceeds the minimum privileges required. ### Attack Path 1. A user runs `scripts/install.sh`, which copies `server.js` into the user's writable home directory. 2. The installer registers and ...[truncated 983 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Run the router as a dedicated unprivileged account using explicit `User=` and `Group=` directives. - Prefer a user-level systemd service under `~/.config/systemd/user/`, because binding to port 8402 does not require root. - If a system service is required, install executable code in a root-owned location such as `/opt/iblai-router/` or `/usr/local/lib/iblai-router/`. - Ensure the service account and ordinary users cannot modify the executable. - Add systemd hardening controls, including: - `NoNewPrivileges=true` - `ProtectSystem=strict` - `ProtectHome=true` - `PrivateTmp=true` - `PrivateDevices=true` - `RestrictSUIDSGID=true` - `RestrictAddressFamilies=AF_INET AF_INET6` - `CapabilityBoundingSet=` - Permit writes only to narrowly scoped paths if runtime writes are required. - Resolve and validate the Node.js executable using `command -v node`, and ensure it is root-owned before placing it in a privileged service definition. ]]>
