fix(ui): suppress privacy mode account title leaks

This commit is contained in:
Tam Nhu Tran committed 2026-05-30 15:37:47 -04:00
1 parent dd62027d3f
commit f592260049
2 files changed
+54 -4

No files matched your search

@@ -172,6 +172,8 @@ export function AccountSurfaceCard({
const { t } = useTranslation(); const { t } = useTranslation();
const identity = getAccountIdentityPresentation(accountId, email, tokenFile); const identity = getAccountIdentityPresentation(accountId, email, tokenFile);
const title = displayEmail || identity.email || accountId; const title = displayEmail || identity.email || accountId;
const sensitiveTitle = (value: string | null | undefined) =>
privacyMode ? undefined : (value ?? undefined);
const normalizedProvider = provider.toLowerCase(); const normalizedProvider = provider.toLowerCase();
const effectiveTier = resolveEffectiveTier(tier, quota); const effectiveTier = resolveEffectiveTier(tier, quota);
const effectiveCodexBadge = const effectiveCodexBadge =
@@ -202,7 +204,7 @@ export function AccountSurfaceCard({
{normalizedProvider === 'codex' {normalizedProvider === 'codex'
? effectiveCodexBadge?.label && ( ? effectiveCodexBadge?.label && (
<span <span
title={effectiveCodexBadge.label} title={sensitiveTitle(effectiveCodexBadge.label)}
className={cn( className={cn(
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0', 'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
privacyMode && PRIVACY_BLUR_CLASS, privacyMode && PRIVACY_BLUR_CLASS,
@@ -214,7 +216,7 @@ export function AccountSurfaceCard({
) )
: identity.audienceLabel && ( : identity.audienceLabel && (
<span <span
title={identity.audienceLabel} title={sensitiveTitle(identity.audienceLabel)}
className={cn( className={cn(
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0', 'text-[8px] font-semibold px-1.5 py-0.5 rounded-md shrink-0',
privacyMode && PRIVACY_BLUR_CLASS, privacyMode && PRIVACY_BLUR_CLASS,
@@ -226,7 +228,7 @@ export function AccountSurfaceCard({
)} )}
{normalizedProvider !== 'codex' && identity.compactDetailLabel && ( {normalizedProvider !== 'codex' && identity.compactDetailLabel && (
<span <span
title={identity.detailLabel ?? identity.compactDetailLabel} title={sensitiveTitle(identity.detailLabel ?? identity.compactDetailLabel)}
className={cn( className={cn(
'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0', 'text-[8px] font-semibold px-1.5 py-0.5 rounded-md border shrink-0',
privacyMode && PRIVACY_BLUR_CLASS, privacyMode && PRIVACY_BLUR_CLASS,
@@ -281,7 +283,7 @@ export function AccountSurfaceCard({
className={cn('flex items-center min-w-0', isCompact ? 'gap-1.5' : 'gap-2 flex-wrap')} className={cn('flex items-center min-w-0', isCompact ? 'gap-1.5' : 'gap-2 flex-wrap')}
> >
<span <span
title={title} title={sensitiveTitle(title)}
className={cn( className={cn(
isCompact isCompact
? 'flex-1 min-w-0 text-xs font-semibold tracking-tight truncate leading-none' ? 'flex-1 min-w-0 text-xs font-semibold tracking-tight truncate leading-none'
@@ -0,0 +1,48 @@
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { AccountSurfaceCard } from '@/components/account/shared/account-surface-card';
describe('AccountSurfaceCard privacy titles', () => {
it('keeps sensitive account title attributes available outside privacy mode', () => {
const { container } = render(
<AccountSurfaceCard
mode="compact"
provider="gemini"
accountId="person@example.com#abcdef12-team"
email="person@example.com"
/>
);
expect(screen.getByText('person@example.com')).toHaveAttribute('title', 'person@example.com');
expect(container.querySelector('[title="Business"]')).toBeInTheDocument();
expect(container.querySelector('[title="Workspace abcdef12"]')).toBeInTheDocument();
});
it('removes sensitive account title attributes in privacy mode', () => {
const { container } = render(
<>
<AccountSurfaceCard
mode="compact"
provider="gemini"
accountId="person@example.com#abcdef12-team"
email="person@example.com"
privacyMode
/>
<AccountSurfaceCard
mode="compact"
provider="codex"
accountId="codex@example.com#enterprise-pro"
email="codex@example.com"
privacyMode
/>
</>
);
expect(screen.getByText('person@example.com')).not.toHaveAttribute('title');
expect(screen.getByText('codex@example.com')).not.toHaveAttribute('title');
expect(container.querySelector('[title="Business"]')).not.toBeInTheDocument();
expect(container.querySelector('[title="Workspace abcdef12"]')).not.toBeInTheDocument();
expect(container.querySelector('[title*="Enterprise"]')).not.toBeInTheDocument();
});
});