diff --git a/src/docker-manager.test.ts b/src/docker-manager.test.ts index 9ef80eff0..0a8d86acd 100644 --- a/src/docker-manager.test.ts +++ b/src/docker-manager.test.ts @@ -509,6 +509,76 @@ describe('docker-manager', () => { expect(volumes.some((v: string) => v.includes('/dev/null') && v.includes('.docker/config.json'))).toBe(true); }); + it('should hide GitHub Actions runner credentials in normal mode', () => { + const result = generateDockerCompose(mockConfig, mockNetworkConfig); + const agent = result.services.agent; + const volumes = agent.volumes as string[]; + const home = process.env.HOME || '/root'; + + // Runner credential files + expect(volumes).toContain(`/dev/null:${home}/actions-runner/.credentials:ro`); + expect(volumes).toContain(`/dev/null:${home}/actions-runner/.credentials_rsaparams:ro`); + expect(volumes).toContain(`/dev/null:${home}/actions-runner/cached/.credentials:ro`); + expect(volumes).toContain(`/dev/null:${home}/actions-runner/cached/.credentials_rsaparams:ro`); + }); + + it('should hide MCP config in normal mode', () => { + const result = generateDockerCompose(mockConfig, mockNetworkConfig); + const agent = result.services.agent; + const volumes = agent.volumes as string[]; + const home = process.env.HOME || '/root'; + + expect(volumes).toContain(`/dev/null:${home}/.copilot/mcp-config.json:ro`); + }); + + it('should hide GitHub Actions runner credentials in chroot mode', () => { + const configWithChroot = { + ...mockConfig, + enableChroot: true, + }; + const result = generateDockerCompose(configWithChroot, mockNetworkConfig); + const agent = result.services.agent; + const volumes = agent.volumes as string[]; + const home = process.env.HOME || '/root'; + + expect(volumes).toContain(`/dev/null:/host${home}/actions-runner/.credentials:ro`); + expect(volumes).toContain(`/dev/null:/host${home}/actions-runner/.credentials_rsaparams:ro`); + expect(volumes).toContain(`/dev/null:/host${home}/actions-runner/cached/.credentials:ro`); + expect(volumes).toContain(`/dev/null:/host${home}/actions-runner/cached/.credentials_rsaparams:ro`); + }); + + it('should hide MCP config in chroot mode', () => { + const configWithChroot = { + ...mockConfig, + enableChroot: true, + }; + const result = generateDockerCompose(configWithChroot, mockNetworkConfig); + const agent = result.services.agent; + const volumes = agent.volumes as string[]; + const home = process.env.HOME || '/root'; + + expect(volumes).toContain(`/dev/null:/host${home}/.copilot/mcp-config.json:ro`); + }); + + it('should exclude GH_AW_MCP_CONFIG from env-all passthrough', () => { + const originalVal = process.env.GH_AW_MCP_CONFIG; + process.env.GH_AW_MCP_CONFIG = '/home/runner/.copilot/mcp-config.json'; + + try { + const configWithEnvAll = { ...mockConfig, envAll: true }; + const result = generateDockerCompose(configWithEnvAll, mockNetworkConfig); + const env = result.services.agent.environment as Record; + + expect(env.GH_AW_MCP_CONFIG).toBeUndefined(); + } finally { + if (originalVal !== undefined) { + process.env.GH_AW_MCP_CONFIG = originalVal; + } else { + delete process.env.GH_AW_MCP_CONFIG; + } + } + }); + it('should use custom volume mounts when specified', () => { const configWithMounts = { ...mockConfig, diff --git a/src/docker-manager.ts b/src/docker-manager.ts index 22f517ea1..10e85d59c 100644 --- a/src/docker-manager.ts +++ b/src/docker-manager.ts @@ -318,6 +318,7 @@ export function generateDockerCompose( 'SUDO_USER', // Sudo metadata 'SUDO_UID', // Sudo metadata 'SUDO_GID', // Sudo metadata + 'GH_AW_MCP_CONFIG', // Points to MCP config path containing auth tokens ]); // Start with required/overridden environment variables @@ -666,6 +667,13 @@ export function generateDockerCompose( `${effectiveHome}/.kube/config`, `${effectiveHome}/.azure/credentials`, `${effectiveHome}/.config/gcloud/credentials.db`, + // GitHub Actions runner credentials (JWT tokens, RSA keys) + `${effectiveHome}/actions-runner/.credentials`, + `${effectiveHome}/actions-runner/.credentials_rsaparams`, + `${effectiveHome}/actions-runner/cached/.credentials`, + `${effectiveHome}/actions-runner/cached/.credentials_rsaparams`, + // MCP configuration (contains authorization tokens) + `${effectiveHome}/.copilot/mcp-config.json`, ]; credentialFiles.forEach(credFile => { @@ -697,6 +705,13 @@ export function generateDockerCompose( `/dev/null:/host${userHome}/.kube/config:ro`, `/dev/null:/host${userHome}/.azure/credentials:ro`, `/dev/null:/host${userHome}/.config/gcloud/credentials.db:ro`, + // GitHub Actions runner credentials (JWT tokens, RSA keys) + `/dev/null:/host${userHome}/actions-runner/.credentials:ro`, + `/dev/null:/host${userHome}/actions-runner/.credentials_rsaparams:ro`, + `/dev/null:/host${userHome}/actions-runner/cached/.credentials:ro`, + `/dev/null:/host${userHome}/actions-runner/cached/.credentials_rsaparams:ro`, + // MCP configuration (contains authorization tokens) + `/dev/null:/host${userHome}/.copilot/mcp-config.json:ro`, ]; chrootCredentialFiles.forEach(mount => {