fix(safety): unify add-account typed risk phrase

- change required acknowledgement phrase to "I ACCEPT RISK"

- apply typed phrase requirement to Gemini and Antigravity add-account flows

- keep CLI/server and UI phrase validation aligned

- update antigravity responsibility unit test
This commit is contained in:
Tam Nhu Tran
2026-02-24 18:32:07 +07:00
parent e22d331bf1
commit c0eb786127
5 changed files with 44 additions and 30 deletions
+2 -1
View File
@@ -14,7 +14,8 @@ import { getCliproxySafetyConfig } from '../config/unified-config-loader';
export const ANTIGRAVITY_RISK_ISSUE_URL = 'https://github.com/kaitranntt/ccs/issues/509';
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
export const ANTIGRAVITY_ACK_PHRASE = 'I ACCEPT AGY RISK';
export const RISK_ACK_PHRASE = 'I ACCEPT RISK';
export const ANTIGRAVITY_ACK_PHRASE = RISK_ACK_PHRASE;
export const ANTIGRAVITY_ACCEPT_RISK_FLAGS = ['--accept-agr-risk', '--accept-antigravity-risk'];
type AgyRiskContext = 'oauth' | 'run';
@@ -57,7 +57,7 @@ describe('antigravity-responsibility', () => {
reviewedIssue509: true,
understandsBanRisk: true,
acceptsFullResponsibility: true,
typedPhrase: ' i accept agy risk ',
typedPhrase: ' i accept risk ',
});
expect(result.valid).toBeTrue();
@@ -1,14 +1,16 @@
import { AlertTriangle, ExternalLink, Settings2 } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { cn } from '@/lib/utils';
import { RISK_ACK_PHRASE } from '@/components/account/antigravity-responsibility-constants';
interface AccountSafetyWarningCardProps {
className?: string;
showAcknowledgement?: boolean;
acknowledged?: boolean;
onAcknowledgedChange?: (value: boolean) => void;
acknowledgementPhrase?: string;
acknowledgementText?: string;
onAcknowledgementTextChange?: (value: string) => void;
disabled?: boolean;
showProxySettingsLink?: boolean;
}
@@ -16,8 +18,9 @@ interface AccountSafetyWarningCardProps {
export function AccountSafetyWarningCard({
className,
showAcknowledgement = false,
acknowledged = false,
onAcknowledgedChange,
acknowledgementPhrase = RISK_ACK_PHRASE,
acknowledgementText = '',
onAcknowledgementTextChange,
disabled = false,
showProxySettingsLink = false,
}: AccountSafetyWarningCardProps) {
@@ -99,20 +102,22 @@ export function AccountSafetyWarningCard({
</span>
</div>
{showAcknowledgement && onAcknowledgedChange && (
{showAcknowledgement && onAcknowledgementTextChange && (
<div className="rounded-lg border border-amber-500/25 bg-amber-500/5 p-2.5">
<div className="flex items-start gap-2">
<Checkbox
id="account-risk-ack"
checked={acknowledged}
onCheckedChange={(checked) => onAcknowledgedChange(Boolean(checked))}
disabled={disabled}
/>
<Label htmlFor="account-risk-ack" className="text-xs leading-5">
I understand this risk and that CCS takes no responsibility if I continue this
setup.
</Label>
</div>
<Label htmlFor="account-risk-ack-text" className="text-xs leading-5">
Type exact phrase to continue:{' '}
<code className="rounded bg-muted px-1 py-0.5 font-mono">
{acknowledgementPhrase}
</code>
</Label>
<Input
id="account-risk-ack-text"
value={acknowledgementText}
onChange={(e) => onAcknowledgementTextChange(e.target.value)}
placeholder={acknowledgementPhrase}
disabled={disabled}
className="mt-2 font-mono text-xs"
/>
</div>
)}
</div>
@@ -34,6 +34,7 @@ import { AntigravityResponsibilityChecklist } from '@/components/account/antigra
import {
ANTIGRAVITY_ACK_VERSION,
DEFAULT_ANTIGRAVITY_RISK_CHECKLIST,
RISK_ACK_PHRASE,
isAntigravityRiskChecklistComplete,
} from '@/components/account/antigravity-responsibility-constants';
import {
@@ -55,6 +56,10 @@ interface AddAccountDialogProps {
isFirstAccount?: boolean;
}
function normalizeRiskPhrase(value: string): string {
return value.trim().replace(/\s+/g, ' ').toUpperCase();
}
export function AddAccountDialog({
open,
onClose,
@@ -66,7 +71,7 @@ export function AddAccountDialog({
const [callbackUrl, setCallbackUrl] = useState('');
const [copied, setCopied] = useState(false);
const [localError, setLocalError] = useState<string | null>(null);
const [acknowledgedRisk, setAcknowledgedRisk] = useState(false);
const [riskAcknowledgementText, setRiskAcknowledgementText] = useState('');
const [agyRiskChecklist, setAgyRiskChecklist] = useState(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
const [agyAckBypassEnabled, setAgyAckBypassEnabled] = useState(false);
const [agyAckBypassLoading, setAgyAckBypassLoading] = useState(false);
@@ -80,6 +85,7 @@ export function AddAccountDialog({
const requiresAgyResponsibilityFlow = provider === 'agy' && !agyAckBypassEnabled;
const isAgyBypassStatePending = provider === 'agy' && agyAckBypassLoading;
const isAgyRiskChecklistComplete = isAntigravityRiskChecklistComplete(agyRiskChecklist);
const isGeminiRiskAcknowledged = normalizeRiskPhrase(riskAcknowledgementText) === RISK_ACK_PHRASE;
const defaultDeviceCode = isDeviceCodeProvider(provider);
const requiresNickname = isNicknameRequiredProvider(provider);
const kiroMethodOption = getKiroAuthMethodOption(kiroAuthMethod);
@@ -102,7 +108,7 @@ export function AddAccountDialog({
setCallbackUrl('');
setCopied(false);
setLocalError(null);
setAcknowledgedRisk(false);
setRiskAcknowledgementText('');
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
setAgyAckBypassEnabled(false);
setAgyAckBypassLoading(false);
@@ -113,7 +119,7 @@ export function AddAccountDialog({
useEffect(() => {
if (open) {
setAcknowledgedRisk(false);
setRiskAcknowledgementText('');
setAgyRiskChecklist(DEFAULT_ANTIGRAVITY_RISK_CHECKLIST);
setLocalError(null);
}
@@ -252,9 +258,9 @@ export function AddAccountDialog({
);
return;
}
if (requiresSafetyAcknowledgement && !acknowledgedRisk) {
if (requiresSafetyAcknowledgement && !isGeminiRiskAcknowledged) {
setLocalError(
'Please acknowledge the account safety warning before authenticating this provider.'
`Type "${RISK_ACK_PHRASE}" to acknowledge the account safety warning before authenticating this provider.`
);
return;
}
@@ -348,9 +354,10 @@ export function AddAccountDialog({
{requiresSafetyAcknowledgement && !showAuthUI && (
<AccountSafetyWarningCard
showAcknowledgement
acknowledged={acknowledgedRisk}
onAcknowledgedChange={(value) => {
setAcknowledgedRisk(value);
acknowledgementPhrase={RISK_ACK_PHRASE}
acknowledgementText={riskAcknowledgementText}
onAcknowledgementTextChange={(value) => {
setRiskAcknowledgementText(value);
setLocalError(null);
}}
disabled={isPending}
@@ -549,7 +556,7 @@ export function AddAccountDialog({
isAgyBypassStatePending ||
(requiresNickname && !nicknameTrimmed) ||
(requiresAgyResponsibilityFlow && !isAgyRiskChecklistComplete) ||
(requiresSafetyAcknowledgement && !acknowledgedRisk)
(requiresSafetyAcknowledgement && !isGeminiRiskAcknowledged)
}
>
<ExternalLink className="w-4 h-4 mr-2" />
@@ -1,5 +1,6 @@
export const ANTIGRAVITY_ACK_VERSION = '2026-02-24-antigravity-oauth-v2';
export const ANTIGRAVITY_ACK_PHRASE = 'I ACCEPT AGY RISK';
export const RISK_ACK_PHRASE = 'I ACCEPT RISK';
export const ANTIGRAVITY_ACK_PHRASE = RISK_ACK_PHRASE;
export interface AntigravityRiskChecklistValue {
reviewedIssue509: boolean;