Skip to content

[Duplicate Code] docker-manager.ts: env-var forwarding uses 15 manual if-statements instead of a loop pattern #2429

Description

@github-actions

Duplicate Code Opportunity

Summary

  • Pattern: In src/docker-manager.ts, ~15 environment variables are forwarded from process.env to the agent container's environment object using individual if-guard lines. A separate dockerClientEnvVars array + loop is already used for the Docker-client subset, but the rest of the variables (GitHub tokens, API keys, CI/CD vars) use the verbose per-line pattern.
  • Locations: src/docker-manager.ts lines 943–993
  • Impact: Adding/removing a forwarded env var requires careful copy-paste; the inconsistency between the loop style and the manual style makes it easy to miss the !config.enableApiProxy guard on new API-key variables

Evidence

// lines 943–973: 15+ manual if-statements
if (process.env.GITHUB_TOKEN) environment.GITHUB_TOKEN = process.env.GITHUB_TOKEN;
if (process.env.GH_TOKEN) environment.GH_TOKEN = process.env.GH_TOKEN;
if (process.env.GITHUB_PERSONAL_ACCESS_TOKEN) environment.GITHUB_PERSONAL_ACCESS_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN;
if (process.env.OPENAI_API_KEY && !config.enableApiProxy) environment.OPENAI_API_KEY = process.env.OPENAI_API_KEY;
if (process.env.CODEX_API_KEY && !config.enableApiProxy) environment.CODEX_API_KEY = process.env.CODEX_API_KEY;
if (process.env.ANTHROPIC_API_KEY && !config.enableApiProxy) environment.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
if (process.env.COPILOT_GITHUB_TOKEN && !config.enableApiProxy) environment.COPILOT_GITHUB_TOKEN = process.env.COPILOT_GITHUB_TOKEN;
if (process.env.COPILOT_API_KEY && !config.enableApiProxy) environment.COPILOT_API_KEY = process.env.COPILOT_API_KEY;
if (process.env.USER) environment.USER = process.env.USER;
if (process.env.TERM && !config.tty) environment.TERM = process.env.TERM;
if (process.env.XDG_CONFIG_HOME) environment.XDG_CONFIG_HOME = process.env.XDG_CONFIG_HOME;
if (process.env.GITHUB_SERVER_URL) environment.GITHUB_SERVER_URL = process.env.GITHUB_SERVER_URL;
if (process.env.GITHUB_API_URL) environment.GITHUB_API_URL = process.env.GITHUB_API_URL;
if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL) environment.ACTIONS_ID_TOKEN_REQUEST_URL = process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
if (process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN) environment.ACTIONS_ID_TOKEN_REQUEST_TOKEN = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;

// lines 979–991: already uses the loop pattern for Docker vars
const dockerClientEnvVars = ['DOCKER_HOST', 'DOCKER_TLS', ...] as const;
for (const dockerEnvVar of dockerClientEnvVars) {
  if (process.env[dockerEnvVar]) environment[dockerEnvVar] = process.env[dockerEnvVar]!;
}

Suggested Refactoring

Consolidate into typed tables that make the guard condition explicit:

// Always-forward vars
const alwaysForward = [
  'GITHUB_TOKEN', 'GH_TOKEN', 'GITHUB_PERSONAL_ACCESS_TOKEN',
  'USER', 'XDG_CONFIG_HOME', 'GITHUB_SERVER_URL', 'GITHUB_API_URL',
  'ACTIONS_ID_TOKEN_REQUEST_URL', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN',
  ...dockerClientEnvVars,
] as const;
for (const v of alwaysForward) {
  if (process.env[v]) environment[v] = process.env[v]!;
}

// API-key vars: skip when api-proxy holds the real credentials
if (!config.enableApiProxy) {
  for (const v of ['OPENAI_API_KEY', 'CODEX_API_KEY', 'ANTHROPIC_API_KEY',
                   'COPILOT_GITHUB_TOKEN', 'COPILOT_API_KEY'] as const) {
    if (process.env[v]) environment[v] = process.env[v]!;
  }
}

// Special cases with additional guards
if (process.env.TERM && !config.tty) environment.TERM = process.env.TERM;

This approach:

  • Makes the security boundary (api-proxy credential isolation) structurally visible
  • Eliminates repetition when adding new forwarded variables
  • Reduces the risk of accidentally omitting the !config.enableApiProxy guard on new API-key vars

Affected Files

  • src/docker-manager.ts — lines 943–993

Effort Estimate

Low


Detected by Duplicate Code Detector workflow. Run date: 2026-05-03

Generated by Duplicate Code Detector · ● 744.5K ·

  • expires on Jun 2, 2026, 12:59 PM UTC

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions