T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/snapmaker.py:428
- Finding
- Undocumented Arbitrary G-code Execution Exceeds the Skill's Declared Privileges<![CDATA[ ## Vulnerability Details **File Location**: `scripts/snapmaker.py:428-436` and `scripts/snapmaker.py:457-458` **Vulnerability Type**: Unrestricted printer command execution **Risk Level**: High ### Vulnerable Code ```python def cmd_gcode(command): """Send G-code command.""" print(f"📤 Sending: {command}") body = json.dumps({"script": command}) result = http_request("POST", "/printer/gcode/script", body) if result: print("✅ Command sent") return 0 print("❌ Failed to send command") return 1 ``` ```python if cmd == "gcode" and len(sys.argv) > 2: return cmd_gcode(" ".join(sys.argv[2:])) ``` ### Technical Analysis The command-line handler accepts arbitrary text following the `gcode` argument, joins it without validation, serializes it as the `script` property, and submits it directly to Moonraker's `/printer/gcode/script` endpoint. No command allowlist, parameter validation, safety boundary, authorization check, or interactive confirmation is applied. The capability is also absent from `SKILL.md`, which advertises status inspection, temperature and filament monitoring, and limited print controls such as pause, resume, and cancel. Arbitrary G-code execution grants substantially broader control than those declared operations and violates least-privilege expectations. The ultimate effect depends on the G-code commands and Klipper macros installed on the target printer. Commands may control heaters, move toolheads, alter printer state, or invoke privileged macros exposed by the printer configuration. ### Attack Path 1. An attacker, untrusted caller, or manipulated Agent gains the ability to invoke the Skill's command-line script. 2. The caller supplies an unsafe printer command through the undocumented interface: ```bash scripts/snapmaker.py gcode "ATTACKER_CONTROLLED_COMMAND" ``` 3. `main()` joins all remaining command-line arguments into a single unrestricted command string. 4. `cmd_gcode()` pl ...[truncated 941 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the generic `gcode` command if arbitrary printer control is not an explicit requirement. 2. If command execution is necessary, replace unrestricted input with a strict allowlist of required commands. 3. Parse commands structurally and validate every parameter: - Reject unknown commands and custom macros. - Enforce safe numeric ranges. - Reject multiline input and command chaining. - Restrict heater temperatures, movement coordinates, speeds, and other safety-critical values. 4. Require explicit interactive confirmation for commands that move hardware, activate heaters, or alter persistent state. 5. Check the current printer state before executing a command and reject operations that are unsafe while printing, paused, faulted, or unhomed. 6. Separate read-only monitoring from write-capable control, using credentials and API permissions with the minimum necessary privileges where supported. 7. If the capability is intentionally retained, clearly document it in `SKILL.md`, including its physical risks and authorization requirements. 8. Add security tests confirming that unknown commands, custom macros, multiline payloads, and out-of-range parameters are rejected. ]]>
