fix(site): remove external admin allowlist

Empties ADMIN_EMAILS and DEVELOPER_GITHUB_USERNAMES, so the impersonate,
recent-purchases and whitelist routes answer 403 to every caller. Points
security reports and funding at Hanzo.
This commit is contained in:
2026-08-21 12:46:33 -07:00
parent 69dc56af57
commit 61a4bc23c9
7 changed files with 23 additions and 20 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
# These are supported funding model platforms
github: natew
github: hanzoai
+1 -1
View File
@@ -1 +1 @@
github: natew
github: hanzoai
+3 -4
View File
@@ -18,8 +18,7 @@ Report privately using **GitHub's private vulnerability reporting**:
(https://github.com/hanzoai/gui/security/advisories/new)
2. Describe the issue, affected versions, and a proof-of-concept if you have one.
If you can't use GitHub advisories, email **security@hanzogui.dev** (or
natewienert@gmail.com) with the details.
If you can't use GitHub advisories, email **security@hanzo.ai** with the details.
We aim to acknowledge reports within 3 business days and to ship a fix or
mitigation for confirmed high/critical issues as quickly as we reasonably can.
@@ -30,7 +29,7 @@ We're happy to credit you in the advisory unless you'd prefer to stay anonymous.
In scope:
- The published `@hanzogui/*` / `hanzogui` npm packages.
- The hanzogui.dev web application and its API endpoints (auth, payments,
- The gui.hanzo.ai web application and its API endpoints (auth, payments,
account/team management).
- This repository's CI/CD and release/publish pipeline.
@@ -40,7 +39,7 @@ Out of scope:
(please report those upstream; Dependabot tracks them here).
- Findings that require a compromised developer machine, social engineering, or
physical access.
- Volumetric / denial-of-service testing against hanzogui.dev.
- Volumetric / denial-of-service testing against gui.hanzo.ai.
## Handling secrets
+8 -3
View File
@@ -1,9 +1,14 @@
/**
* admin email whitelist for admin-only features like impersonation
* Admin allowlist for the /api/admin routes: impersonate, recent-purchases,
* whitelist. Empty, so every caller gets 403.
*
* Admin identity is Hanzo IAM membership of the reserved `admin` org, not an
* email list. This app authenticates against Supabase and cannot evaluate that
* predicate, so it grants admin to no one.
*/
export const ADMIN_EMAILS = ['[email protected]'] as const
export const ADMIN_EMAILS: readonly string[] = []
export function isAdminEmail(email: string | null | undefined): boolean {
if (!email) return false
return (ADMIN_EMAILS as readonly string[]).includes(email.toLowerCase())
return ADMIN_EMAILS.includes(email.toLowerCase())
}
@@ -3,6 +3,8 @@ import { Button, TooltipSimple, YStack } from '@hanzo/gui'
import { Link } from '~/components/Link'
const SPONSOR_URL = 'https://github.com/sponsors/hanzoai'
export const SponsorButton = (props: { tiny?: boolean }) => {
const el = (
<Button
@@ -28,7 +30,7 @@ export const SponsorButton = (props: { tiny?: boolean }) => {
</Button>
)
return (
<Link target="_blank" href="https://github.com/sponsors/natew">
<Link target="_blank" href={SPONSOR_URL}>
<YStack>
{props.tiny ? (
<TooltipSimple delay={0} restMs={25} label="Support OSS development of Gui">
@@ -945,7 +945,7 @@ const HeaderMenuMoreContents = () => {
<HeadAnchor grid>Blog</HeadAnchor>
</Link>
<Link asChild href="https://github.com/sponsors/natew">
<Link asChild href="https://github.com/sponsors/hanzoai">
<HeadAnchor grid target="_blank">
Sponsor
<YStack display={'inline-block' as any} y={0} my={-20} ml={12} opacity={0.8}>
@@ -10,13 +10,12 @@ import {
} from '~/shared/types/subscription'
/**
* GitHub usernames that are allowed to test the purchase flow even if they already have Pro.
* These users can:
* - See the checkout flow even with an active subscription
* - Use the DEV_TEST_99 coupon for 99% off test purchases
* - Purchase multiple times to the same domain (for testing)
* GitHub usernames allowed to test the purchase flow while holding Pro. These
* users bypass the active-subscription check, unlock the DEV_TEST_99 coupon
* (99% off), and may repurchase the same domain. Empty, so no account
* qualifies.
*/
export const DEVELOPER_GITHUB_USERNAMES = ['natew'] as const
export const DEVELOPER_GITHUB_USERNAMES: readonly string[] = []
/**
* Check if a subscription has specific product access
@@ -100,9 +99,7 @@ const calculateTeamSeats = (subscriptions: UserContextType['subscriptions']): nu
*/
const isDeveloperUser = (userData?: UserContextType): boolean => {
if (!userData?.githubUsername) return false
return DEVELOPER_GITHUB_USERNAMES.includes(
userData.githubUsername.toLowerCase() as (typeof DEVELOPER_GITHUB_USERNAMES)[number]
)
return DEVELOPER_GITHUB_USERNAMES.includes(userData.githubUsername.toLowerCase())
}
/**