feat(security): add disableAlwaysAllow setting to disable auto-approvals (#21941)

This commit is contained in:
Gal Zahavi
2026-03-13 16:02:09 -07:00
committed by GitHub
parent b0d151bd65
commit b49fc8122d
20 changed files with 352 additions and 63 deletions

View File

@@ -42,6 +42,7 @@ describe('ToolConfirmationQueue', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
getModel: () => 'gemini-pro',
getDebugMode: () => false,
getTargetDir: () => '/mock/target/dir',

View File

@@ -21,6 +21,7 @@ describe('ToolConfirmationMessage Redirection', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
it('should display redirection warning and tip for redirected commands', async () => {

View File

@@ -37,6 +37,7 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
it('should not display urls if prompt and url are the same', async () => {
@@ -331,8 +332,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
@@ -353,6 +354,7 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => false,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
@@ -388,8 +390,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
@@ -415,8 +417,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<ToolConfirmationMessage
callId="test-call-id"
@@ -457,8 +459,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => false,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
vi.mocked(useToolActions).mockReturnValue({
confirm: vi.fn(),
cancel: vi.fn(),
@@ -485,8 +487,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => true,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
vi.mocked(useToolActions).mockReturnValue({
confirm: vi.fn(),
cancel: vi.fn(),
@@ -513,8 +515,8 @@ describe('ToolConfirmationMessage', () => {
const mockConfig = {
isTrustedFolder: () => true,
getIdeMode: () => true,
getDisableAlwaysAllow: () => false,
} as unknown as Config;
vi.mocked(useToolActions).mockReturnValue({
confirm: vi.fn(),
cancel: vi.fn(),

View File

@@ -86,12 +86,14 @@ export const ToolConfirmationMessage: React.FC<
const settings = useSettings();
const allowPermanentApproval =
settings.merged.security.enablePermanentToolApproval;
settings.merged.security.enablePermanentToolApproval &&
!config.getDisableAlwaysAllow();
const handlesOwnUI =
confirmationDetails.type === 'ask_user' ||
confirmationDetails.type === 'exit_plan_mode';
const isTrustedFolder = config.isTrustedFolder();
const isTrustedFolder =
config.isTrustedFolder() && !config.getDisableAlwaysAllow();
const handleConfirm = useCallback(
(outcome: ToolConfirmationOutcome, payload?: ToolConfirmationPayload) => {