The console label (from ?title=) was substituted into HTML via str.format with no
escaping, and the iframe src was built from the raw query string — a reflected-XSS
vector on the loopback console. html.escape the label, and rebuild kbd_src from only
the known keys (title/app) re-encoded + escaped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Owns the box-side services for the lilith screening tools (Mr. Number, WhatsApp),
extracted from the duplicated cloud/ dirs in @mr-number / @whatsapp:
- cloud/adb-keyboard, cloud/ocr-service (mrnumber-ocr systemd unit), cloud/terraform
(read-only IaC reference; droplet owned by uvlava).
- deploy/deploy-droplet.sh — push + (re)start the box services.
The screening apps drive this box over adb; they no longer carry their own copies.
Shared client code lives in @lilith/redroid-client (PyPI) + @lilith/redroid-mcp (Verdaccio).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>