Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions docs/tools/mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -733,16 +733,27 @@ The MCP integration tracks several states:

## Important notes

### Security sonsiderations
### Security considerations

- **Trust settings:** The `trust` option bypasses all confirmation dialogs. Use
cautiously and only for servers you completely control
- **Access tokens:** Be security-aware when configuring environment variables
containing API keys or tokens
- **Environment variable redaction:** By default, the Gemini CLI redacts
sensitive environment variables (such as `GEMINI_API_KEY`, `GOOGLE_API_KEY`,
and variables matching patterns like `*TOKEN*`, `*SECRET*`, `*PASSWORD*`) when
spawning MCP servers using the `stdio` transport. This prevents unintended
exposure of your credentials to third-party servers.
- **Explicit environment variables:** If you need to pass a specific environment
variable to an MCP server, you should define it explicitly in the `env`
property of the server configuration in `settings.json`.
- **Sandbox compatibility:** When using sandboxing, ensure MCP servers are
available within the sandbox environment
available within the sandbox environment.
- **Private data:** Using broadly scoped personal access tokens can lead to
information leakage between repositories
information leakage between repositories.
- **Untrusted servers:** Be extremely cautious when adding MCP servers from
untrusted or third-party sources. Malicious servers could attempt to
exfiltrate data or perform unauthorized actions through the tools they expose.

### Performance and resource management

Expand Down
7 changes: 7 additions & 0 deletions packages/cli/src/commands/mcp/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ async function addMcpServer(

settings.setValue(settingsScope, 'mcpServers', mcpServers);

if (transport === 'stdio') {
debugLogger.warn(
'Security Warning: Running MCP servers with stdio transport can expose inherited environment variables. ' +
'While the Gemini CLI redacts common API keys and secrets by default, you should only run servers from trusted sources.',
);
}

if (isExistingServer) {
debugLogger.log(`MCP server "${name}" updated in ${scope} settings.`);
} else {
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/services/environmentSanitization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ describe('sanitizeEnvironment', () => {
CLIENT_ID: 'sensitive-id',
DB_URI: 'sensitive-uri',
DATABASE_URL: 'sensitive-url',
GEMINI_API_KEY: 'sensitive-gemini-key',
GOOGLE_API_KEY: 'sensitive-google-key',
GOOGLE_APPLICATION_CREDENTIALS: '/path/to/creds.json',
SAFE_VAR: 'is-safe',
};
const sanitized = sanitizeEnvironment(env, EMPTY_OPTIONS);
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/services/environmentSanitization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export const NEVER_ALLOWED_ENVIRONMENT_VARIABLES: ReadonlySet<string> = new Set(
'GOOGLE_CLOUD_PROJECT',
'GOOGLE_CLOUD_ACCOUNT',
'FIREBASE_PROJECT_ID',
'GEMINI_API_KEY',
'GOOGLE_API_KEY',
'GOOGLE_APPLICATION_CREDENTIALS',
],
);

Expand Down
66 changes: 66 additions & 0 deletions packages/core/src/tools/mcp-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,72 @@ describe('mcp-client', () => {
});
});

it('should redact sensitive environment variables for command transport', async () => {
const mockedTransport = vi
.spyOn(SdkClientStdioLib, 'StdioClientTransport')
.mockReturnValue({} as SdkClientStdioLib.StdioClientTransport);

const originalEnv = process.env;
process.env = {
...originalEnv,
GEMINI_API_KEY: 'sensitive-key',
SAFE_VAR: 'safe-value',
};

try {
await createTransport(
'test-server',
{
command: 'test-command',
},
false,
EMPTY_CONFIG,
);

const callArgs = mockedTransport.mock.calls[0][0];
expect(callArgs.env).toBeDefined();
expect(callArgs.env!['SAFE_VAR']).toBe('safe-value');
expect(callArgs.env!['GEMINI_API_KEY']).toBeUndefined();
} finally {
process.env = originalEnv;
}
});

it('should include extension settings in environment', async () => {
const mockedTransport = vi
.spyOn(SdkClientStdioLib, 'StdioClientTransport')
.mockReturnValue({} as SdkClientStdioLib.StdioClientTransport);

await createTransport(
'test-server',
{
command: 'test-command',
extension: {
name: 'test-ext',
resolvedSettings: [
{
envVar: 'EXT_VAR',
value: 'ext-value',
sensitive: false,
name: 'ext-setting',
},
],
version: '',
isActive: false,
path: '',
contextFiles: [],
id: '',
},
},
false,
EMPTY_CONFIG,
);

const callArgs = mockedTransport.mock.calls[0][0];
expect(callArgs.env).toBeDefined();
expect(callArgs.env!['EXT_VAR']).toBe('ext-value');
});

describe('useGoogleCredentialProvider', () => {
beforeEach(() => {
// Mock GoogleAuth client
Expand Down
24 changes: 22 additions & 2 deletions packages/core/src/tools/mcp-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ import {
type Tool as McpTool,
} from '@modelcontextprotocol/sdk/types.js';
import { parse } from 'shell-quote';
import type { Config, MCPServerConfig } from '../config/config.js';
import type {
Config,
GeminiCLIExtension,
MCPServerConfig,
} from '../config/config.js';
import { AuthProviderType } from '../config/config.js';
import { GoogleCredentialProvider } from '../mcp/google-auth-provider.js';
import { ServiceAccountImpersonationProvider } from '../mcp/sa-impersonation-provider.js';
Expand Down Expand Up @@ -1798,7 +1802,11 @@ export async function createTransport(
command: mcpServerConfig.command,
args: mcpServerConfig.args || [],
env: {
...sanitizeEnvironment(process.env, sanitizationConfig),
...sanitizeEnvironment(process.env, {
...sanitizationConfig,
enableEnvironmentVariableRedaction: true,
}),
...getExtensionEnvironment(mcpServerConfig.extension),
...(mcpServerConfig.env || {}),
} as Record<string, string>,
cwd: mcpServerConfig.cwd,
Expand Down Expand Up @@ -1851,3 +1859,15 @@ export function isEnabled(
)
);
}

function getExtensionEnvironment(
extension?: GeminiCLIExtension,
): Record<string, string> {
const env: Record<string, string> = {};
if (extension?.resolvedSettings) {
for (const setting of extension.resolvedSettings) {
env[setting.envVar] = setting.value;
}
}
return env;
}
Loading