Security¶
What this changes on a TV¶
CleanYourTV runs a service as root on a rooted TV. It listens on 127.0.0.1:8765 only. A few short-lived pages open on the
local network on request, and an optional notification endpoint is off by default.
| Port | What | When it is open |
|---|---|---|
8765 (127.0.0.1 only) |
The service API | Always; see Service API |
| 8766 | Live TV pairing page | While you set up Live TV: a 6-digit code shown on the TV, ten minutes |
| 8767 | Network notifications | Only when you switch it on in the manager app; needs a token |
| 8768 and up | Share-log page | Ten minutes, at a random address, with a masked report |
| 8769 | Voice setup page | Ten minutes, at a random 128-bit address, closed after saving |
| 8791 | Wallpapers page | While the QR screen is open in the manager app: a 6-digit code shown on the TV, at most an hour; see Wallpapers |
What the setup changes on the TV is listed in What it changes on the TV.
Network notifications¶
Off until switched on in the manager app. It then listens on port 8767 for POST /notify with Authorization: Bearer <token>
(a random 192-bit token kept in config.json, readable by root only). It exposes only the notification call. Wrong tokens lock
an address out for ten minutes, requests are limited to 20 a minute and 32 KB, and an optional allow list restricts addresses.
It is plain HTTP: the token can be read by anyone who can watch the traffic on your network.
Show as QR code in the manager makes the same port serve one more page, GET /t/<24 random characters>, for ten minutes: it shows the address and the
token so a phone can copy them. The address is created when the code is shown (96 bits of randomness), follows the same allow list, and stops
working after ten minutes, when notifications are switched off or the service restarts. Anyone who sees the code on the screen, or can read
the traffic, can read the token while it is open; New token replaces it.
Themes¶
The manager downloads the theme list, screenshots, theme files and wallpapers from raw.githubusercontent.com (the main branch of this
repository) over HTTPS, when you open Theme or choose a theme. They are data only: the service checks every value against its list,
limits the sizes (theme 32 KB, wallpaper 1.5 MB, screenshot 600 KB), checks that images are images and refuses anything else. There is
no script or CSS in a theme. Anything merged into main becomes available to every TV, which is the same trust you place in the
releases of this repository; there is no signature.
Voice¶
Optional and off by default. Installing it downloads files over HTTPS from PyPI, Ubuntu's archive and Moonshine's model server; each file is checked against a SHA-256 value written in the code, and a mismatch stops the install. The recogniser is a 64-bit program started by the root service with its own copy of the C library; it reads audio from a pipe and prints text.
- Audio from the remote's microphone is held in memory only while recognising.
- Only the recognised text is sent, and only to the address you set (plain
http://is possible: the token is then visible on your network) and, if you switch on AI chat, toopenrouter.aiover HTTPS with your OpenRouter key and the model you chose. OpenRouter and that model's provider see the text. - The phone setup page is a short-lived page on the local network (port 8769, a random 128-bit address, ten minutes, closed after saving, plain HTTP: the key is visible on the network while it is typed).
- With Home Assistant set up, the recognised text goes to the address you set, with your long-lived access token (plain
http://is possible: the token is then visible on your network; a self-signed certificate is accepted only when you switch that on). - The keys and the token are kept in
config.json(readable by root only) and are never returned by the service. - Pausing LG's voice assistant sends it SIGSTOP; nothing of LG's is modified.
Trust¶
Everything it installs comes from this repository's GitHub releases and runs as root. Releases carry a SHA-256 file, which detects corruption but not a compromised repository. Download only from the release page of this repository.
Dev builds¶
The manager's Update channel can follow the dev builds: the pre-release named dev that GitHub Actions publishes for each
push to the dev branch. It is opt-in and off by default; the stable updater only reads the latest non-pre-release. A dev build is
downloaded over HTTPS from the repository the TV already updates from and checked against the .sha256 file in the same release,
so the check protects against a damaged download, not against someone who can publish to the repository (the same is true of
stable releases, which are not signed yet). The only pre-release the updater reads is the one tagged dev, and the files must be
the package and launcher names the updater already expects.
Limits to know about¶
- Any app on the TV can already run root commands through the Homebrew Channel; apps are not a security boundary on a rooted TV.
/media/developeris world-writable on webOS. The setup removes group and other write access from this project's files and keeps the playlist and settings files owner-only, but the parent folder remains writable.- The service API refuses requests from web pages (any
http(s)origin); local apps and scripts are accepted.
Move from telnet to SSH
A rooted TV often has an unauthenticated telnet server open on the local network. Turn telnet off and SSH on in the Homebrew Channel's settings.
Reporting¶
Open a private security advisory on the GitHub repository, or an issue that does not include exploit details.