Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
16 changes: 16 additions & 0 deletions packages/gcloud-mcp/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ test('should start the McpServer if gcloud is available', async () => {
expect(serverInstance?.connect).toHaveBeenCalledWith(expect.any(StdioServerTransport));
});

test('default denylist includes local credential-printing commands', async () => {
process.argv = ['node', 'index.js'];
vi.stubGlobal('process', { ...process, exit: vi.fn(), on: vi.fn() });

const { default_deny } = await import('./index.js');

expect(default_deny).toEqual(
expect.arrayContaining([
'auth print-access-token',
'auth print-identity-token',
'auth application-default print-access-token',
'config config-helper',
]),
);
});

test('should exit if load deny and allow from config file', async () => {
process.argv = ['node', 'index.js', '--config', 'test-config.json'];
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
Expand Down
4 changes: 4 additions & 0 deletions packages/gcloud-mcp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export const default_deny: string[] = [
'cloud-shell ssh',
'workstations ssh',
'app instances ssh',
'auth print-access-token',
'auth print-identity-token',
'auth application-default print-access-token',
'config config-helper',
'interactive',
'meta',
];
Expand Down
13 changes: 13 additions & 0 deletions packages/gcloud-mcp/src/tools/run_gcloud_command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ describe('createRunGcloudCommand', () => {
expect(result.isError).toBe(true);
});

test('does not return stdout for denylisted credential-printing commands', async () => {
const tool = createTool({ deny: ['auth print-access-token'] });
const inputArgs = ['auth', 'print-access-token'];
mockGcloudInvoke('FAKE_ACCESS_TOKEN_SHOULD_NOT_BE_RETURNED');

const result = await tool({ args: inputArgs });

expect(mockedGcloud.invoke).not.toHaveBeenCalled();
expect(result.content[0].text).toContain('Execution denied:');
expect(result.content[0].text).not.toContain('FAKE_ACCESS_TOKEN_SHOULD_NOT_BE_RETURNED');
expect(result.isError).toBe(true);
});

test('invokes gcloud for non-denylisted command', async () => {
const tool = createTool({ deny: ['compute list'] });
const inputArgs = ['compute', 'create'];
Expand Down