fix(cli): show specific macOS seatbelt profile in footer

This PR improves the sandbox indicator in the CLI footer to display the specific macOS seatbelt profile when active, instead of the generic "current process" string. This provides clearer feedback to the user about which security policy is currently applied.

The implementation refactors the sandbox display logic into a reusable helper function and updates it to check for `SEATBELT_PROFILE` when `SANDBOX` is set to `sandbox-exec`.

Fixes: #26697

cc @NTaylorMullen @gundermanc
This commit is contained in:
gemini-cli[bot]
2026-05-18 22:18:20 +00:00
parent 792654c88b
commit fb1d8194f9
2 changed files with 39 additions and 18 deletions
@@ -366,7 +366,7 @@ describe('<Footer />', () => {
unmount();
});
it('should display "current process" for macOS Seatbelt when SANDBOX is sandbox-exec', async () => {
it('should display "macOS seatbelt (test-profile)" for macOS Seatbelt when SANDBOX is sandbox-exec', async () => {
vi.stubEnv('SANDBOX', 'sandbox-exec');
vi.stubEnv('SEATBELT_PROFILE', 'test-profile');
const { lastFrame, unmount } = await renderWithProviders(<Footer />, {
@@ -374,7 +374,7 @@ describe('<Footer />', () => {
width: 120,
uiState: { isTrustedFolder: true, sessionStats: mockSessionStats },
});
expect(lastFrame()).toContain('current process');
expect(lastFrame()).toContain('macOS seatbelt (test-profile)');
vi.unstubAllEnvs();
unmount();
});
+37 -16
View File
@@ -69,25 +69,46 @@ interface SandboxIndicatorProps {
isTrustedFolder: boolean | undefined;
}
function getSandboxDisplayString(
sandbox: string | undefined,
sandboxEnabled: boolean,
isTrustedFolder: boolean | undefined,
): string {
if (isTrustedFolder === false) {
return 'untrusted';
}
if (sandbox) {
if (sandbox === 'sandbox-exec') {
const profile = process.env['SEATBELT_PROFILE'] || 'permissive-open';
return `macOS seatbelt (${profile})`;
}
return 'current process';
}
if (sandboxEnabled) {
return 'all tools';
}
return 'no sandbox';
}
const SandboxIndicator: React.FC<SandboxIndicatorProps> = ({
isTrustedFolder,
}) => {
const config = useConfig();
const sandboxEnabled = config.getSandboxEnabled();
if (isTrustedFolder === false) {
return <Text color={theme.status.warning}>untrusted</Text>;
}
const sandbox = process.env['SANDBOX'];
if (sandbox) {
return <Text color={theme.status.warning}>current process</Text>;
}
const displayString = getSandboxDisplayString(
sandbox,
sandboxEnabled,
isTrustedFolder,
);
if (sandboxEnabled) {
return <Text color={theme.status.warning}>all tools</Text>;
}
const color =
displayString === 'no sandbox' ? theme.status.error : theme.status.warning;
return <Text color={theme.status.error}>no sandbox</Text>;
return <Text color={color}>{displayString}</Text>;
};
const CorgiIndicator: React.FC = () => (
@@ -308,11 +329,11 @@ export const Footer: React.FC = () => {
break;
}
case 'sandbox': {
let str = 'no sandbox';
const sandbox = process.env['SANDBOX'];
if (isTrustedFolder === false) str = 'untrusted';
else if (sandbox) str = 'current process';
else if (config.getSandboxEnabled()) str = 'all tools';
const str = getSandboxDisplayString(
process.env['SANDBOX'],
config.getSandboxEnabled(),
isTrustedFolder,
);
addCol(
id,