mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
Add implementation for setting to disable Github extensions (#12838)
This commit is contained in:
@@ -490,6 +490,11 @@ their corresponding top-level category object in your `settings.json` file.
|
|||||||
- **Default:** `false`
|
- **Default:** `false`
|
||||||
- **Requires restart:** Yes
|
- **Requires restart:** Yes
|
||||||
|
|
||||||
|
- **`security.blockGitExtensions`** (boolean):
|
||||||
|
- **Description:** Blocks installing and loading extensions from Git.
|
||||||
|
- **Default:** `false`
|
||||||
|
- **Requires restart:** Yes
|
||||||
|
|
||||||
- **`security.folderTrust.enabled`** (boolean):
|
- **`security.folderTrust.enabled`** (boolean):
|
||||||
- **Description:** Setting to track whether Folder trust is enabled.
|
- **Description:** Setting to track whether Folder trust is enabled.
|
||||||
- **Default:** `false`
|
- **Default:** `false`
|
||||||
|
|||||||
@@ -128,6 +128,15 @@ export class ExtensionManager extends ExtensionLoader {
|
|||||||
installMetadata: ExtensionInstallMetadata,
|
installMetadata: ExtensionInstallMetadata,
|
||||||
previousExtensionConfig?: ExtensionConfig,
|
previousExtensionConfig?: ExtensionConfig,
|
||||||
): Promise<GeminiCLIExtension> {
|
): Promise<GeminiCLIExtension> {
|
||||||
|
if (
|
||||||
|
(installMetadata.type === 'git' ||
|
||||||
|
installMetadata.type === 'github-release') &&
|
||||||
|
this.settings.security?.blockGitExtensions
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'Installing extensions from remote sources is disallowed by your current settings.',
|
||||||
|
);
|
||||||
|
}
|
||||||
const isUpdate = !!previousExtensionConfig;
|
const isUpdate = !!previousExtensionConfig;
|
||||||
let newExtensionConfig: ExtensionConfig | null = null;
|
let newExtensionConfig: ExtensionConfig | null = null;
|
||||||
let localSourcePath: string | undefined;
|
let localSourcePath: string | undefined;
|
||||||
@@ -449,6 +458,13 @@ export class ExtensionManager extends ExtensionLoader {
|
|||||||
|
|
||||||
const installMetadata = loadInstallMetadata(extensionDir);
|
const installMetadata = loadInstallMetadata(extensionDir);
|
||||||
let effectiveExtensionPath = extensionDir;
|
let effectiveExtensionPath = extensionDir;
|
||||||
|
if (
|
||||||
|
(installMetadata?.type === 'git' ||
|
||||||
|
installMetadata?.type === 'github-release') &&
|
||||||
|
this.settings.security?.blockGitExtensions
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (installMetadata?.type === 'link') {
|
if (installMetadata?.type === 'link') {
|
||||||
effectiveExtensionPath = installMetadata.source;
|
effectiveExtensionPath = installMetadata.source;
|
||||||
|
|||||||
@@ -594,6 +594,34 @@ describe('extension tests', () => {
|
|||||||
consoleSpy.mockRestore();
|
consoleSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not load github extensions if blockGitExtensions is set', async () => {
|
||||||
|
createExtension({
|
||||||
|
extensionsDir: userExtensionsDir,
|
||||||
|
name: 'my-ext',
|
||||||
|
version: '1.0.0',
|
||||||
|
installMetadata: {
|
||||||
|
type: 'git',
|
||||||
|
source: 'http://somehost.com/foo/bar',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const blockGitExtensionsSetting = {
|
||||||
|
security: {
|
||||||
|
blockGitExtensions: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
extensionManager = new ExtensionManager({
|
||||||
|
workspaceDir: tempWorkspaceDir,
|
||||||
|
requestConsent: mockRequestConsent,
|
||||||
|
requestSetting: mockPromptForSettings,
|
||||||
|
settings: blockGitExtensionsSetting,
|
||||||
|
});
|
||||||
|
const extensions = await extensionManager.loadExtensions();
|
||||||
|
const extension = extensions.find((e) => e.name === 'my-ext');
|
||||||
|
|
||||||
|
expect(extension).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
describe('id generation', () => {
|
describe('id generation', () => {
|
||||||
it('should generate id from source for non-github git urls', async () => {
|
it('should generate id from source for non-github git urls', async () => {
|
||||||
createExtension({
|
createExtension({
|
||||||
@@ -876,6 +904,30 @@ describe('extension tests', () => {
|
|||||||
fs.rmSync(targetExtDir, { recursive: true, force: true });
|
fs.rmSync(targetExtDir, { recursive: true, force: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not install a github extension if blockGitExtensions is set', async () => {
|
||||||
|
const gitUrl = 'https://somehost.com/somerepo.git';
|
||||||
|
const blockGitExtensionsSetting = {
|
||||||
|
security: {
|
||||||
|
blockGitExtensions: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
extensionManager = new ExtensionManager({
|
||||||
|
workspaceDir: tempWorkspaceDir,
|
||||||
|
requestConsent: mockRequestConsent,
|
||||||
|
requestSetting: mockPromptForSettings,
|
||||||
|
settings: blockGitExtensionsSetting,
|
||||||
|
});
|
||||||
|
await extensionManager.loadExtensions();
|
||||||
|
await expect(
|
||||||
|
extensionManager.installOrUpdateExtension({
|
||||||
|
source: gitUrl,
|
||||||
|
type: 'git',
|
||||||
|
}),
|
||||||
|
).rejects.toThrow(
|
||||||
|
'Installing extensions from remote sources is disallowed by your current settings.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should prompt for trust if workspace is not trusted', async () => {
|
it('should prompt for trust if workspace is not trusted', async () => {
|
||||||
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
vi.mocked(isWorkspaceTrusted).mockReturnValue({
|
||||||
isTrusted: false,
|
isTrusted: false,
|
||||||
|
|||||||
@@ -1102,6 +1102,15 @@ const SETTINGS_SCHEMA = {
|
|||||||
description: 'Disable YOLO mode, even if enabled by a flag.',
|
description: 'Disable YOLO mode, even if enabled by a flag.',
|
||||||
showInDialog: true,
|
showInDialog: true,
|
||||||
},
|
},
|
||||||
|
blockGitExtensions: {
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'Blocks extensions from Git',
|
||||||
|
category: 'Security',
|
||||||
|
requiresRestart: true,
|
||||||
|
default: false,
|
||||||
|
description: 'Blocks installing and loading extensions from Git.',
|
||||||
|
showInDialog: true,
|
||||||
|
},
|
||||||
folderTrust: {
|
folderTrust: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
label: 'Folder Trust',
|
label: 'Folder Trust',
|
||||||
|
|||||||
@@ -997,6 +997,13 @@
|
|||||||
"default": false,
|
"default": false,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"blockGitExtensions": {
|
||||||
|
"title": "Blocks extensions from Git",
|
||||||
|
"description": "Blocks installing and loading extensions from Git.",
|
||||||
|
"markdownDescription": "Blocks installing and loading extensions from Git.\n\n- Category: `Security`\n- Requires restart: `yes`\n- Default: `false`",
|
||||||
|
"default": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"folderTrust": {
|
"folderTrust": {
|
||||||
"title": "Folder Trust",
|
"title": "Folder Trust",
|
||||||
"description": "Settings for folder trust.",
|
"description": "Settings for folder trust.",
|
||||||
|
|||||||
Reference in New Issue
Block a user