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 # 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) (https://github.com/hanzoai/gui/security/advisories/new)
2. Describe the issue, affected versions, and a proof-of-concept if you have one. 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 If you can't use GitHub advisories, email **security@hanzo.ai** with the details.
natewienert@gmail.com) with the details.
We aim to acknowledge reports within 3 business days and to ship a fix or 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. 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: In scope:
- The published `@hanzogui/*` / `hanzogui` npm packages. - 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). account/team management).
- This repository's CI/CD and release/publish pipeline. - This repository's CI/CD and release/publish pipeline.
@@ -40,7 +39,7 @@ Out of scope:
(please report those upstream; Dependabot tracks them here). (please report those upstream; Dependabot tracks them here).
- Findings that require a compromised developer machine, social engineering, or - Findings that require a compromised developer machine, social engineering, or
physical access. physical access.
- Volumetric / denial-of-service testing against hanzogui.dev. - Volumetric / denial-of-service testing against gui.hanzo.ai.
## Handling secrets ## 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 { export function isAdminEmail(email: string | null | undefined): boolean {
if (!email) return false 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' import { Link } from '~/components/Link'
const SPONSOR_URL = 'https://github.com/sponsors/hanzoai'
export const SponsorButton = (props: { tiny?: boolean }) => { export const SponsorButton = (props: { tiny?: boolean }) => {
const el = ( const el = (
<Button <Button
@@ -28,7 +30,7 @@ export const SponsorButton = (props: { tiny?: boolean }) => {
</Button> </Button>
) )
return ( return (
<Link target="_blank" href="https://github.com/sponsors/natew"> <Link target="_blank" href={SPONSOR_URL}>
<YStack> <YStack>
{props.tiny ? ( {props.tiny ? (
<TooltipSimple delay={0} restMs={25} label="Support OSS development of Gui"> <TooltipSimple delay={0} restMs={25} label="Support OSS development of Gui">
@@ -945,7 +945,7 @@ const HeaderMenuMoreContents = () => {
<HeadAnchor grid>Blog</HeadAnchor> <HeadAnchor grid>Blog</HeadAnchor>
</Link> </Link>
<Link asChild href="https://github.com/sponsors/natew"> <Link asChild href="https://github.com/sponsors/hanzoai">
<HeadAnchor grid target="_blank"> <HeadAnchor grid target="_blank">
Sponsor Sponsor
<YStack display={'inline-block' as any} y={0} my={-20} ml={12} opacity={0.8}> <YStack display={'inline-block' as any} y={0} my={-20} ml={12} opacity={0.8}>
@@ -10,13 +10,12 @@ import {
} from '~/shared/types/subscription' } from '~/shared/types/subscription'
/** /**
* GitHub usernames that are allowed to test the purchase flow even if they already have Pro. * GitHub usernames allowed to test the purchase flow while holding Pro. These
* These users can: * users bypass the active-subscription check, unlock the DEV_TEST_99 coupon
* - See the checkout flow even with an active subscription * (99% off), and may repurchase the same domain. Empty, so no account
* - Use the DEV_TEST_99 coupon for 99% off test purchases * qualifies.
* - Purchase multiple times to the same domain (for testing)
*/ */
export const DEVELOPER_GITHUB_USERNAMES = ['natew'] as const export const DEVELOPER_GITHUB_USERNAMES: readonly string[] = []
/** /**
* Check if a subscription has specific product access * Check if a subscription has specific product access
@@ -100,9 +99,7 @@ const calculateTeamSeats = (subscriptions: UserContextType['subscriptions']): nu
*/ */
const isDeveloperUser = (userData?: UserContextType): boolean => { const isDeveloperUser = (userData?: UserContextType): boolean => {
if (!userData?.githubUsername) return false if (!userData?.githubUsername) return false
return DEVELOPER_GITHUB_USERNAMES.includes( return DEVELOPER_GITHUB_USERNAMES.includes(userData.githubUsername.toLowerCase())
userData.githubUsername.toLowerCase() as (typeof DEVELOPER_GITHUB_USERNAMES)[number]
)
} }
/** /**