Widget Security
Community widgets are code other people wrote, running on your dashboard. GlassHome is built so that even a malicious widget cannot quietly leak your home’s data or control devices you did not approve.
The short version
- A widget cannot send your home’s data to the internet. Your browser only lets widgets talk to your Home Assistant and to GlassHome.
- A widget can only control the devices you approve when you install it. A weather widget never gets the keys to unlock your door.
- The widget you run is exactly the one I published. It is checked byte-for-byte before it loads.
Why not iframes?
The common way to sandbox third-party code is an iframe per widget. GlassHome skips them, because a dashboard full of iframes is slow, janky, and clunky. It enforces the rules about what a widget is allowed to do for every widget, so a malicious widget in a fast, native-feeling widget still cannot phone home or touch unapproved devices.
The layers
Each layer stops a different thing. The first two are hard guarantees enforced by your browser or GlassHome; the rest raise the bar on top.
Layer 1: The network lock (stops data leaving)
Your browser is told, up front, the only places a widget may send anything: your Home Assistant and GlassHome. Requests to any other server are refused, so a widget that reads your dashboard has nowhere to post it. It cannot ask Home Assistant to reach one either: GlassHome refuses any request from a widget that names a web address, like a speaker told to play a stranger’s link. Video calls are the one exception, named below. Protects against: exfiltrating your presence, camera, lock, or sensor data to a stranger’s server.
Layer 2: The locked-away keys (stops unapproved control)
Your Home Assistant login token never reaches the app at all. GlassHome’s own server holds it and talks to Home Assistant on the app’s behalf, so neither a widget nor the rest of the page can read a key that is not there. To control something, a widget asks GlassHome, which first checks the request against what you approved at install. A grant holds even when a widget asks for a whole floor or an area: GlassHome works out which devices that covers and refuses any you did not approve. Protects against: reading your Home Assistant login, and a widget controlling a device you did not grant it, with one gap named below.
Layer 3: Isolation and no hidden code (extra hardening)
Each widget renders in its own sealed space: it cannot reach into GlassHome or other widgets, and its styling cannot bleed out. Widgets also cannot run code generated or downloaded on the fly. Protects against: one widget tampering with another or with the dashboard, and hidden behavior smuggled in after publish. Layers 1 and 2 are guarantees. Layer 3 is defense in depth, and makes no such promise.
The permission prompt
When you install a widget that uses your devices, GlassHome shows exactly what it is asking for, in plain language:
“Climate” wants permission to: Control your thermostat
You approve that list, and only that list. If a later update wants more, GlassHome asks you again before it can run, never silently. If a widget tries something outside what you approved, the attempt is blocked and you get a notification.
What a widget can and cannot do
| A widget can… | A widget cannot… |
|---|---|
| Show the entities you give it | Send your data to any other website |
| Control the devices you approve at install | Control devices you did not approve |
| Render inside its own widget | Read your Home Assistant login |
| Use your theme and styling | Reach into GlassHome or other widgets’ data |
| Run hidden, downloaded-on-the-fly code |
Not yet covered
Here are the edges.
- A widget can still read what is already on your dashboard. It can see the entity values shown there; the protection is that Layer 1 leaves it almost nowhere to send them.
- A widget written to get around the permission check can act as you. Widgets run inside the dashboard page, so one built to abuse that could open its own connection to Home Assistant with your sign-in and control things you did not grant. The permission check stops honest widgets and mistakes; moving widgets into a sandbox outside the page is planned for 1.5. Install widgets from authors you trust.
- Video calls are outside the network lock. Browsers do not apply the lock to video calls (WebRTC), which the camera widget uses for live video, so a widget written to abuse them could reach a server of its choosing. Install widgets from authors you trust.
- Layer 3 is hardening. A determined attacker who found a browser-level escape could in theory get around it. That is exactly why the guarantees that matter most, Layers 1 and 2, do not depend on it.
- No human review of every widget yet. Today the safety comes from the layers above plus the permissions you grant at install. Nobody reads each widget’s code before it is published. A review or signing step for the public catalog may come later.
For the technically curious
Layer 1 is a strict Content-Security-Policy egress allowlist. Layer 2: the Home Assistant access token lives only on the GlassHome server, which authenticates the relayed WebSocket itself; the app and its Web Worker hold no token. Widgets send permission-checked requests to the worker (validated with the same capability definition the consent screen showed you), and never talk to Home Assistant directly. Layer 3: each widget renders in a closed shadow root, intrinsics are frozen, and eval/Function are disabled by CSP. Separately, every published bundle is SHA-256 verified server-side before it is served.
Reporting a security issue
Found a way around any of this? Email [email protected] with steps to reproduce, or reach me on the GlassHome Discord. I review every report and gladly credit researchers who report responsibly.