Security checklist
What an app built on the SDK must get right. Token storage, content security policy, what never to log, server-side checks, untrusted text from posts, and what to do after a leak.
The SDK keeps the sign-in protocol safe for you: PKCE, state checks, one-time codes, a pinned issuer. What it cannot do is protect the rest of your page. This is a checklist of what is left to your app, in order of how often it goes wrong.
Tokens
- Choose
sessionstorage unless you need more. It lives only in the tab.localkeeps tokens across restarts but exposes them to any script on your origin. See Sessions and storage. - Never put a token in an address. Not in a query string, not in a link, not in a redirect. Addresses end up in logs, history and referrer headers. The SDK sends tokens only in headers.
- Never log tokens.
onTraceshortens tokens, codes and verifiers, but your own code does not. Do not loggetAccessToken()results,Authorizationheaders or whole requests of your own. - Do not copy tokens into other storage, cookies of your own or analytics. Ask
getAccessToken()when you need one. - Keep the App Secret out of the browser. A website app's secret is for servers. A page that needs no secret is a single-page app: it has none.
Transport and policy
- Serve over HTTPS only. Sign-in cannot work on plain
httpoutsidelocalhost, and the SDK refuses anhttpissuer. Redirecthttptohttpsfor the whole site. - Set a content security policy. A strict one is the best protection for tokens in web storage. Allow only what you use, and let the SDK reach UNET:
Content-Security-Policy: default-src 'self'; script-src 'self'; connect-src 'self' https://api.unet.ovh; img-src 'self' https://api.unet.ovh data:; frame-ancestors 'none'Add blob: to media-src if you play audio through unet.api.media(). Avoid 'unsafe-inline' and 'unsafe-eval' in script-src.
- Pin the SDK version and use a lockfile. The package has no dependencies of its own, which keeps the supply chain short.
Your server
- Verify on the server whatever the browser claims. A button that is hidden in the browser is not access control. See Verify on your server.
- Check that the token is for your app. Use
verifyAccessToken(website apps) orverifyIdToken(apps without a secret), never only the profile endpoint. - Key your users by
sub. It is the person's id for your app and cannot be used to recognise them on other sites. Do not useusername, which can change. - Do not store more than you need. UNET gives you no email address; do not ask for one to link accounts across sites.
Text and links from UNET are untrusted
Anything another person wrote can be hostile: post text, display names, bios, hashtags, profile links, image descriptions, and the title and description of a link preview.
- Render text as text. Use
textContentor your framework's escaping. Never build HTML from these values with string concatenation orinnerHTML. - Check the scheme of every link you build from UNET data.
profile.website,profile.links[].urlandpreview.urlcan be anything the person typed. Onlyhttp:andhttps:addresses belong in anhref:
function safeHref(value: string | null | undefined): string | undefined {
try {
const url = new URL(value ?? "");
return url.protocol === "https:" || url.protocol === "http:" ? url.href : undefined;
} catch {
return undefined; // not an absolute address: no link
}
}splitLinkPreview already passes only http(s) addresses for the preview, but the other link fields are your responsibility.
- Open outside links with
rel="noopener noreferrer". - Treat
returnTofrom the address bar as untrusted. Accept only paths on your own site. See The sign-in flow.
Permissions
- Ask for the least. Each permission is one more thing a stolen token can do. See Permissions.
- Do not request
offline_accessby habit. It creates a refresh token that outlives the tab. - Treat write permissions with care.
posts:write,follows:writeandsafety:manageact in the person's name; ask for them at the moment they are needed.
If you suspect a leak
- Sign out the affected sessions:
unet.signOut()revokes the tokens at UNET. - Website apps: rotate the App Secret in the console. The old one stops working at once.
- Turn the app off in the console if the leak is severe. Every token of the app stops working immediately, and every person must sign in again once you turn it back on with a fixed build.
- Tell the people affected. They can also remove your app themselves under Connected apps in their UNET settings, which revokes it for their account.
- Report a vulnerability in UNET or in the SDK to the address in the security policy.