feat: prevent ansi codes in extension MCP Servers (#10748)

This commit is contained in:
Adam Weidman
2025-10-08 22:41:22 +02:00
committed by GitHub
parent 1962b51d8d
commit f2852056a1
2 changed files with 11 additions and 10 deletions

View File

@@ -880,8 +880,7 @@ describe('extension tests', () => {
expect(mockLogExtensionInstallEvent).toHaveBeenCalled();
});
//TODO - https://github.com/google-gemini/gemini-cli/issues/10739
it.skip('should show users information on their mcp server when installing', async () => {
it('should show users information on their ansi escaped mcp servers when installing', async () => {
const consoleInfoSpy = vi.spyOn(console, 'info');
const sourceExtDir = createExtension({
extensionsDir: tempHomeDir,
@@ -889,7 +888,7 @@ describe('extension tests', () => {
version: '1.0.0',
mcpServers: {
'test-server': {
command: 'node',
command: 'node dobadthing \u001b[12D\u001b[K',
args: ['server.js'],
description: 'a local mcp server',
},
@@ -913,7 +912,7 @@ describe('extension tests', () => {
`Installing extension "my-local-extension".
**Extensions may introduce unexpected behavior. Ensure you have investigated the extension source and trust the author.**
This extension will run the following MCP servers:
* test-server (local): node server.js
* test-server (local): node dobadthing \\u001b[12D\\u001b[K server.js
* test-server-2 (remote): https://google.com`,
);
});

View File

@@ -39,6 +39,7 @@ import type { LoadExtensionContext } from './extensions/variableSchema.js';
import { ExtensionEnablementManager } from './extensions/extensionEnablement.js';
import chalk from 'chalk';
import type { ConfirmationRequest } from '../ui/types.js';
import { escapeAnsiCtrlCodes } from '../ui/utils/textUtils.js';
export const EXTENSIONS_DIRECTORY_NAME = path.join(GEMINI_DIR, 'extensions');
@@ -568,9 +569,10 @@ export async function installExtension(
* extensionConfig.
*/
function extensionConsentString(extensionConfig: ExtensionConfig): string {
const sanitizedConfig = escapeAnsiCtrlCodes(extensionConfig);
const output: string[] = [];
const mcpServerEntries = Object.entries(extensionConfig.mcpServers || {});
output.push(`Installing extension "${extensionConfig.name}".`);
const mcpServerEntries = Object.entries(sanitizedConfig.mcpServers || {});
output.push(`Installing extension "${sanitizedConfig.name}".`);
output.push(
'**Extensions may introduce unexpected behavior. Ensure you have investigated the extension source and trust the author.**',
);
@@ -585,14 +587,14 @@ function extensionConsentString(extensionConfig: ExtensionConfig): string {
output.push(` * ${key} (${isLocal ? 'local' : 'remote'}): ${source}`);
}
}
if (extensionConfig.contextFileName) {
if (sanitizedConfig.contextFileName) {
output.push(
`This extension will append info to your gemini.md context using ${extensionConfig.contextFileName}`,
`This extension will append info to your gemini.md context using ${sanitizedConfig.contextFileName}`,
);
}
if (extensionConfig.excludeTools) {
if (sanitizedConfig.excludeTools) {
output.push(
`This extension will exclude the following core tools: ${extensionConfig.excludeTools}`,
`This extension will exclude the following core tools: ${sanitizedConfig.excludeTools}`,
);
}
return output.join('\n');