mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-17 23:32:43 -07:00
fix(cli): escape npm script names in shell autocompletion to prevent command injection
This commit is contained in:
@@ -44,7 +44,9 @@ describe('npmProvider', () => {
|
||||
|
||||
expect(result.exclusive).toBe(true);
|
||||
expect(result.suggestions).toHaveLength(2);
|
||||
expect(result.suggestions[0].label).toBe('build');
|
||||
expect(result.suggestions[0].value).toBe('build');
|
||||
expect(result.suggestions[1].label).toBe('build:dev');
|
||||
expect(result.suggestions[1].value).toBe('build:dev');
|
||||
expect(fs.readFile).toHaveBeenCalledWith(
|
||||
expect.stringContaining('package.json'),
|
||||
@@ -52,6 +54,32 @@ describe('npmProvider', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('escapes script names with shell metacharacters', async () => {
|
||||
const mockPackageJson = {
|
||||
scripts: {
|
||||
'build(prod)': 'tsc',
|
||||
'test:watch': 'vitest',
|
||||
},
|
||||
};
|
||||
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockPackageJson));
|
||||
|
||||
const result = await npmProvider.getCompletions(
|
||||
['npm', 'run', 'bu'],
|
||||
2,
|
||||
'/tmp',
|
||||
);
|
||||
|
||||
expect(result.exclusive).toBe(true);
|
||||
expect(result.suggestions).toHaveLength(1);
|
||||
expect(result.suggestions[0].label).toBe('build(prod)');
|
||||
|
||||
// Windows does not escape spaces/parens in cmds by default in our function, but Unix does.
|
||||
const isWin = process.platform === 'win32';
|
||||
expect(result.suggestions[0].value).toBe(
|
||||
isWin ? 'build(prod)' : 'build\\(prod\\)',
|
||||
);
|
||||
});
|
||||
|
||||
it('handles missing package.json gracefully', async () => {
|
||||
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT'));
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import type { ShellCompletionProvider, CompletionResult } from './types.js';
|
||||
import { escapeShellPath } from '../useShellCompletion.js';
|
||||
|
||||
const NPM_SUBCOMMANDS = [
|
||||
'build',
|
||||
@@ -64,7 +65,7 @@ export const npmProvider: ShellCompletionProvider = {
|
||||
.filter((s) => s.startsWith(partial))
|
||||
.map((s) => ({
|
||||
label: s,
|
||||
value: s,
|
||||
value: escapeShellPath(s),
|
||||
description: 'npm script',
|
||||
})),
|
||||
exclusive: true,
|
||||
|
||||
Reference in New Issue
Block a user