Skip to content

Commit 9505fe6

Browse files
authored
Resolve error thrown for sensitive values (#17826)
1 parent f8baf04 commit 9505fe6

2 files changed

Lines changed: 76 additions & 2 deletions

File tree

packages/cli/src/config/extensions/extensionSettings.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,35 @@ describe('extensionSettings', () => {
398398
expect(actualContent).toBe('VAR1="a value with spaces"\n');
399399
});
400400

401+
it('should not set sensitive settings if the value is empty during initial setup', async () => {
402+
const config: ExtensionConfig = {
403+
name: 'test-ext',
404+
version: '1.0.0',
405+
settings: [
406+
{
407+
name: 's1',
408+
description: 'd1',
409+
envVar: 'SENSITIVE_VAR',
410+
sensitive: true,
411+
},
412+
],
413+
};
414+
mockRequestSetting.mockResolvedValue('');
415+
416+
await maybePromptForSettings(
417+
config,
418+
'12345',
419+
mockRequestSetting,
420+
undefined,
421+
undefined,
422+
);
423+
424+
const userKeychain = new KeychainTokenStorage(
425+
`Gemini CLI Extensions test-ext 12345`,
426+
);
427+
expect(await userKeychain.getSecret('SENSITIVE_VAR')).toBeNull();
428+
});
429+
401430
it('should not attempt to clear secrets if keychain is unavailable', async () => {
402431
// Arrange
403432
const mockIsAvailable = vi.fn().mockResolvedValue(false);
@@ -738,5 +767,42 @@ describe('extensionSettings', () => {
738767
const lines = actualContent.split('\n').filter((line) => line.length > 0);
739768
expect(lines).toHaveLength(3); // Should only have the three variables
740769
});
770+
771+
it('should delete a sensitive setting if the new value is empty', async () => {
772+
mockRequestSetting.mockResolvedValue('');
773+
774+
await updateSetting(
775+
config,
776+
'12345',
777+
'VAR2',
778+
mockRequestSetting,
779+
ExtensionSettingScope.USER,
780+
tempWorkspaceDir,
781+
);
782+
783+
const userKeychain = new KeychainTokenStorage(
784+
`Gemini CLI Extensions test-ext 12345`,
785+
);
786+
expect(await userKeychain.getSecret('VAR2')).toBeNull();
787+
});
788+
789+
it('should not throw if deleting a non-existent sensitive setting with empty value', async () => {
790+
mockRequestSetting.mockResolvedValue('');
791+
// Ensure it doesn't exist first
792+
const userKeychain = new KeychainTokenStorage(
793+
`Gemini CLI Extensions test-ext 12345`,
794+
);
795+
await userKeychain.deleteSecret('VAR2');
796+
797+
await updateSetting(
798+
config,
799+
'12345',
800+
'VAR2',
801+
mockRequestSetting,
802+
ExtensionSettingScope.USER,
803+
tempWorkspaceDir,
804+
);
805+
// Should complete without error
806+
});
741807
});
742808
});

packages/cli/src/config/extensions/extensionSettings.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export async function maybePromptForSettings(
112112
const nonSensitiveSettings: Record<string, string> = {};
113113
for (const setting of settings) {
114114
const value = allSettings[setting.envVar];
115-
if (value === undefined) {
115+
if (value === undefined || value === '') {
116116
continue;
117117
}
118118
if (setting.sensitive) {
@@ -230,7 +230,15 @@ export async function updateSetting(
230230
);
231231

232232
if (settingToUpdate.sensitive) {
233-
await keychain.setSecret(settingToUpdate.envVar, newValue);
233+
if (newValue) {
234+
await keychain.setSecret(settingToUpdate.envVar, newValue);
235+
} else {
236+
try {
237+
await keychain.deleteSecret(settingToUpdate.envVar);
238+
} catch {
239+
// Ignore if secret does not exist
240+
}
241+
}
234242
return;
235243
}
236244

0 commit comments

Comments
 (0)