segfault labs

Security model

User modules are third-party code. readout contains them with defense-in-depth, so even a malicious module is tightly bounded.

  • Isolated iframe. Each surface renders in an iframe with sandbox="allow-scripts" and no allow-same-origin, giving it an opaque origin. It cannot script the overlay, read its auth token, or touch host APIs. The only channel is postMessage, mediated by the broker.
  • Locked-down CSP. Module assets are served with connect-src 'none', so a module cannot reach the network directly — every request must go through ps.host.fetch.
  • The host is the trust boundary. Read-only data streams and playback actions are permission-checked; the privileged capabilities — storage, notifications, net.fetch — are handled by the host, which re-checks the manifest's permissions on every call. A tampered frontend can't grant a module anything its manifest didn't declare.
  • Physical storage namespacing. Each module's storage is stored under its own id, so a module can't read another's data even if it lies about a key.

net.fetch hardening

When a module calls ps.host.fetch, the host:

  • allows http(s) only, and requires the host to match the module's allowedDomains;
  • runs an SSRF guard that re-validates the actually-connected IP — private, loopback, link-local, CGNAT, and multicast ranges are blocked, which also defeats DNS-rebinding;
  • sends no cookies and follows no redirects;
  • allow-lists request headers and strips Set-Cookie from the response;
  • caps the response (≈5 MB / 15 s); and
  • applies a per-module rate limit.

Even sandboxed, users should only install modules they trust. The consent prompt shows exactly what each module can do before it runs.