Docs · Widget

Security & allowlist

ShowKit is built around a simple principle: changelogs are public, so the widget is built for public distribution. Anything you publish is meant to be indexed, embedded, and shared — but only you can write to it, and only your allowlisted domains can embed it.

Public by design

The content the widget loads — your changelog — is the same content that lives at showkit.dev/c/<slug>, gets indexed by Google, ships as RSS / Atom / JSON, and goes out to your email subscribers. There is no hidden tier of "private changelog entries" behind the embed. If you can see it in the widget, you can see it on the public page.

This is intentional. We want your launches to spread. We want search engines to find them. We want feed readers to subscribe. The widget is one of several distribution surfaces over the same public dataset.

The workspace slug is an identifier, not a credential

data-workspace="acme" is just an identifier — like a Twitter handle, a Substack URL, or a Plausible data-domain. It tells the widget which workspace's changelog to display. It does not grant any kind of access. Treat it the way you'd treat your public username: visible to everyone, useless to attackers on its own.

Writes are gated by auth + row-level security

Publishing entries, editing the roadmap, importing testimonials, and changing workspace settings all happen through the dashboard, behind a magic-link sign-in. Every database write is protected by Postgres row-level security policies keyed to the workspace owner — even if someone had your slug, they could not write to your workspace without your auth cookie.

Domain allowlist

Because the slug is public and the data is public, nothing structurally stops a third party from putting data-workspace="acme" on their site to display your changelog as if it were theirs. The same is true of any embeddable content (someone could embed your tweets, your Substack RSS, your YouTube videos). It is not a data breach — every byte they show is already public — but it is a brand-trust problem.

The domain allowlist is our defense. When configured, the widget's data-fetch endpoint checks the embedding page's Origin header against your allowed-domains list and refuses to serve to origins outside it.

Configure your allowed domains

Open your dashboard → Settings → Allowed domains. Add the hostnames where your widget is allowed to load. Wildcards on the leftmost label are supported.

# exact hosts
acme.com
app.acme.com

# wildcard subdomains
*.staging.acme.com

# localhost is always allowed for dev
localhost
127.0.0.1

Wildcards match one label only: *.acme.com matches app.acme.com and staging.acme.com, but not acme.com.evil.com (that would be a different domain entirely).

Save with an empty list and the widget serves to any origin (the default for new workspaces). This is fine while you're trying things out — add domains the moment your embed is on a public page.

What the allowlist does not restrict

The allowlist gates the embed only — your SEO surfaces stay open. These endpoints remain reachable from any origin or crawler, regardless of your allowed-domains setting:
  • The public page at showkit.dev/c/<slug> — Google and Bing index it
  • /changelog.rss, .atom, .json — feed readers and integrations
  • The widget script file itself — needed to bootstrap on any allowed page
We will not gate SEO surfaces. That would defeat the whole point of publishing.

What an outside embed sees

When an origin is not on your list, the data endpoint returns a 403 with { error: "origin_not_allowed" }. The widget logs one clear console warning and renders nothing. No partial state, no broken bell.

Other anti-impersonation defenses

The allowlist is the primary defense. We pair it with several smaller signals:

Customer-side CSP

The widget runs inside a Shadow DOM with its own scoped stylesheet, so it cannot leak styles into — or read styles from — your site. It makes outbound requests only to https://showkit.dev. See Troubleshooting → CSP for the exact headers.

Reporting a vulnerability

If you find a security issue, please email security@showkit.dev. We respond within one business day and credit reporters in the changelog (with permission).