Treat the frontend as an UX layer, not an authorization or confidentiality enforcement boundary. Any access control (licensing, revoke/re-auth, hidden-content guarantees, RBAC) must be enforced by the backend/data layer; the UI may be redundant or fail-open without granting access. Separately, whenever the UI must render untrusted values into security-sensitive contexts (e.g., hyperlinks), validate/allow-list before using them.
Apply this as a standard:
href (or other executable/sensitive contexts), apply an allow-list policy and fall back to safe rendering (e.g., plain text).Example pattern (safe URL rendering):
const uri = deviceState.verificationUri;
const safe = /^https:\/\/([a-z0-9-]+\.)*github\.com(\/|$)/i.test(uri);
return safe ? (
<a href={uri} target="_blank" rel="noopener noreferrer">Open link</a>
) : (
<code>{uri}</code>
);
If you’re tempted to add a UI-only if (shouldHide) return null, confirm the backend/storage already prevents the underlying data/action; otherwise, move or add the enforcement where it can’t be bypassed.
Enter the URL of a public GitHub repository