Security
Security architecture
Implementation snapshot of the XOBIT security model: trust boundaries, stored secrets, transport rules, and operator settings.
This is not a third-party audit or security certification.
System Layers
| Layer | Mechanism | Security Rule |
|---|---|---|
| Browser workspace | Static browser app plus local storage | The browser profile is trusted. Projects, revisions, chat history, specifications, API keys, connection history, MQTT settings, and online sign-in keys can be stored locally. Anyone with access to the same browser profile may be able to inspect or remove them. |
| USB transport | Web Serial and esptool-js | USB access requires the browser permission picker. Once granted, the browser can install firmware, configure the board, upload scripts, and read logs. USB is the recovery and first-install authority. |
| Board storage | LittleFS /config.json, script files, and NVS state | The ESP32 stores WiFi credentials, MQTT settings, online auth keys, guest flags, guest key, device identity, and scripts locally. This storage is not presented as encrypted-at-rest. |
| MQTT broker | MQTT.js in the browser, Arduino MQTT on firmware | Broker username/password only controls broker access. XOBIT protocol authorization is separate and happens inside the MQTT payload layer. |
| XOBIT online protocol | MessagePack frames, challenge auth, AES-CTR, and HMAC-SHA256 | Full MQTT control requires a named online user by default. Full unauthenticated online control is only available when its dedicated setting is deliberately enabled. Guest UI and guest script access are separate limited permissions. After sign-in, MQTT command/response payloads are encrypted and authenticated by the XOBIT session layer. |
| AI service | OpenAI API over browser HTTPS requests | The OpenAI API key is stored in the browser and sent to OpenAI when AI features are used. XOBIT does not proxy the key through its own server. |
| Firmware update | USB install and optional SafeBoot OTA path | USB remains the recovery path. OTA is configuration-dependent and validates requested source/target update metadata; it should not be treated as the only recovery mechanism. |
Browser Storage
- Project data. Projects, revisions, chat transcript, specification text, editor state, UI preferences, connection history, and circuit preferences are stored in browser local storage or related browser storage.
- OpenAI key. The API key is stored directly in local storage under the editor's chat API key setting. It is available to JavaScript running in the page and should be cleared on shared machines.
- MQTT settings. Broker host, port, topic root, username, and password can be stored in the browser. These are transport credentials, not XOBIT control credentials.
- Online sign-in cache. After a user signs in to a board, the browser stores the derived online auth key for that board id in local storage so reconnect can happen without retyping the password.
- Rule. Treat the browser profile as sensitive. Use a separate profile for demonstrations, public machines, or shared workstations.
Board Storage
- Configuration file. Firmware writes device configuration to LittleFS
/config.json. This includes WiFi network entries, MQTT settings, guest access flags, guest key, and stored online auth users. - Online users. The board stores usernames and 32-byte keys derived from device id, username, and password. It does not need the original password after the key has been stored.
- Scripts. Current and stored scripts live on the board filesystem. Upload integrity checks use script byte counts and hashes, but this is transport/storage integrity, not source secrecy.
- NVS state. Non-volatile storage is used for persistent firmware/update state such as SafeBoot OTA requests and script autorun latches.
- Rule. Physical access to the board is a privileged condition. Do not assume secrets on the ESP32 are protected against a determined local attacker.
USB Layer
USB is intentionally powerful. The model assumes that a user who selects the ESP32 in the Web Serial picker intends to administer the board.
| Operation | Rule |
|---|---|
| Firmware install | Uses Web Serial plus esptool-js. The browser can erase/install firmware according to the selected manifest and options. |
| Post-install setup | After flashing, the browser can reconnect and apply initial device name, WiFi, MQTT, timezone, and access settings. |
| Direct development | USB can send commands, upload scripts, read status, and inspect logs without involving MQTT. |
| Recovery | USB is the expected recovery route when online transport, OTA, WiFi, or script behavior fails. |
MQTT Layer
MQTT has two distinct security levels: broker access and XOBIT protocol access. A broker password alone does not define who is allowed to control the board.
- Broker connection. The browser and board connect to the configured MQTT host and port using the configured broker username and password. The browser chooses
wss://when the page is served over HTTPS andws://otherwise. - Topic root. The configured topic root is the complete XOBIT MQTT base prefix, for example
xobit/my-board. Commands, responses, events, and hello messages live below that root. - Device hello. The board publishes a hello message that states whether XOBIT auth is required, whether guest UI/script access is enabled, and whether a guest UI key exists.
- Default closed condition. On fresh firmware,
allowUnauthenticatedAccess,mqttAllowAnonymousUi, andmqttAllowAnonymousScriptare false. With no online users, the board does not start MQTT control even if WiFi and broker settings are present. - Auth required condition. When one or more online users are configured and unauthenticated access is off, the board reports
auth: "required"and requires XOBIT sign-in for normal MQTT control traffic. - Full anonymous condition. If
allowUnauthenticatedAccessis enabled, MQTT accepts normal command frames without online sign-in. Any MQTT client that can publish valid command frames to the board command topic through the broker namespace can control the board except for operations that still require USB or authenticated MQTT. - Challenge response. The browser sends an auth-start frame with client id, username, and client nonce. The board replies with a server nonce. The browser proves the shared key with HMAC-SHA256 over a versioned auth string, ids, and both nonces.
- Secure session. After success, the board assigns a session id. Payloads are wrapped in secure MessagePack frames. The browser encrypts/decrypts with AES-CTR and signs/verifies with HMAC-SHA256. Counters reject replayed or stale frames.
Operational baseline
Configure at least one named online user for administrative MQTT control. Keep full unauthenticated online control off unless the object is intentionally public. Use guest UI or guest script only for deliberately limited public surfaces.
Guest Access
| Mode | Allowed Surface | Rule |
|---|---|---|
| Guest UI | Status light, system info, WiFi status, and script input command frames | Requires Guest UI. Frames must include the generated guest key. This permission is independent of full unauthenticated online control. |
| Guest script | MQTT script inbox text topic | Requires Guest script. This permission is independent of full unauthenticated online control. Keep disabled unless the script treats incoming messages as untrusted public input. |
| Full online user | Normal XOBIT command channel | Use for administrative script upload, device configuration, and control workflows. |
ChatGPT Key Handling
- Storage. The OpenAI API key is stored in browser local storage when saved in Settings > AI.
- Use. The browser sends the key directly to OpenAI in HTTPS API requests when chat/model features are used.
- Sharing token. The editor can create an encrypted key-share token using WebCrypto PBKDF2-SHA256 and AES-GCM, with salt, IV, iteration count, ciphertext, and expiry metadata.
- Decryption limit. The token is encrypted at rest/in transit as a token, but importing it requires the browser to decrypt the API key into browser memory and then store it locally if accepted. It is not a hardware-backed secret.
- Rule. Share encrypted API-key tokens only with people you would allow to use the API key, choose a separate sharing password, set short expirations, and clear the stored key after shared sessions.
Firmware And Setup Rules
| Setting or Path | Behavior | Technical Rule |
|---|---|---|
| WiFi settings | Stored on the board and configured over USB or existing protocol connection. | Use a network intended for experimental devices. Changing WiFi does not itself create online authorization. |
| MQTT enabled | Board connects online only when MQTT is enabled and at least one online path is configured: named online users, full unauthenticated control, Guest UI, or Guest script. | Disable MQTT for USB-only projects. |
| Allow full unauthenticated online control | Default off. When on, normal MQTT command frames can be accepted without online sign-in. | Enable only for deliberate public or lab setups where any broker client in the namespace may be treated as allowed. |
| MQTT topic root | The complete base topic prefix used by the board and browser. | Use a unique project/device-specific root such as xobit/my-board. Treat predictable roots on public brokers as discoverable. |
| Online users | Usernames plus derived 32-byte keys are stored on the board. | Add individual users; remove users that should no longer control the object. |
| Guest UI | Generates/stores a guest UI key if needed and enables the guest UI allowlist. | Enable only for deliberately limited interfaces. |
| Guest script | Accepts unauthenticated text on the script inbox topic. | Default to off. Treat incoming messages as hostile input. |
| Home Assistant bridge | Uses the compatibility layer without ESPHome Noise encryption. | Treat as LAN-trusted until encrypted HA native API support is implemented. |
| HTTP from scripts | Firmware includes HTTP/TLS support, with defaults allowing insecure TLS behavior for script HTTP fetches. | Do not treat script-level HTTP fetch as a high-assurance data channel without reviewing firmware build flags and endpoint validation. |
| OTA | SafeBoot OTA support is build/configuration dependent and USB remains recovery. | OTA prepare, boot, and clear require USB or an authenticated MQTT secure session. Keep physical access during updates. |
Deployment Position
- Acceptable for: studio prototypes, installations under operator control, lab deployments, and networked objects where the operator controls the browser profile, board, broker, and physical recovery path.
- Use caution for: public networks, unattended public interaction, shared computers, untrusted MQTT brokers, or projects where API keys and WiFi credentials are sensitive assets.
- Not positioned as: a hardened multi-tenant platform, audited remote administration system, encrypted-at-rest device vault, or substitute for product security review.
- Minimum serious setup: private broker or broker credentials, unique MQTT topic root, named online users, full unauthenticated control off, guest script disabled, guest UI only when intentionally public, separate browser profile, exported backups, and USB recovery available.