diff --git a/tests/fixtures/awf-runner.ts b/tests/fixtures/awf-runner.ts index 8efe42ab..b2d23afd 100644 --- a/tests/fixtures/awf-runner.ts +++ b/tests/fixtures/awf-runner.ts @@ -19,6 +19,8 @@ export interface AwfOptions { allowHostPorts?: string; // Ports or port ranges to allow for host access (e.g., '3000' or '3000-8000') allowFullFilesystemAccess?: boolean; // Allow full filesystem access (disables selective mounting security) enableApiProxy?: boolean; // Enable API proxy sidecar for LLM credential management + envAll?: boolean; // Pass all host environment variables to container (--env-all) + cliEnv?: Record; // Explicit -e KEY=VALUE flags passed to AWF CLI } export interface AwfResult { @@ -110,6 +112,18 @@ export class AwfRunner { args.push('--enable-api-proxy'); } + // Add --env-all flag + if (options.envAll) { + args.push('--env-all'); + } + + // Add explicit -e KEY=VALUE flags + if (options.cliEnv) { + for (const [key, value] of Object.entries(options.cliEnv)) { + args.push('-e', `${key}=${value}`); + } + } + // Add -- separator before command args.push('--'); @@ -264,6 +278,18 @@ export class AwfRunner { args.push('--enable-api-proxy'); } + // Add --env-all flag + if (options.envAll) { + args.push('--env-all'); + } + + // Add explicit -e KEY=VALUE flags + if (options.cliEnv) { + for (const [key, value] of Object.entries(options.cliEnv)) { + args.push('-e', `${key}=${value}`); + } + } + // Add -- separator before command args.push('--'); diff --git a/tests/integration/environment-variables.test.ts b/tests/integration/environment-variables.test.ts index 33119c7f..749b1bab 100644 --- a/tests/integration/environment-variables.test.ts +++ b/tests/integration/environment-variables.test.ts @@ -159,4 +159,125 @@ describe('Environment Variable Handling', () => { expect(result).toSucceed(); expect(result.stdout).toContain('12345'); }, 120000); + + describe('--env-all flag', () => { + test('should pass host environment variables into container', async () => { + const result = await runner.runWithSudo( + 'echo $AWF_TEST_CUSTOM_VAR', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + env: { + AWF_TEST_CUSTOM_VAR: 'env_all_works', + }, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toContain('env_all_works'); + }, 120000); + + test('should set proxy environment variables inside container', async () => { + const result = await runner.runWithSudo( + 'bash -c "echo HTTP_PROXY=$HTTP_PROXY && echo HTTPS_PROXY=$HTTPS_PROXY"', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toMatch(/HTTP_PROXY=http:\/\/172\.30\.0\.10:3128/); + expect(result.stdout).toMatch(/HTTPS_PROXY=http:\/\/172\.30\.0\.10:3128/); + }, 120000); + + test('should set JAVA_TOOL_OPTIONS with JVM proxy properties', async () => { + const result = await runner.runWithSudo( + 'bash -c "echo $JAVA_TOOL_OPTIONS"', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toContain('-Dhttp.proxyHost='); + expect(result.stdout).toContain('-Dhttp.proxyPort='); + expect(result.stdout).toContain('-Dhttps.proxyHost='); + expect(result.stdout).toContain('-Dhttps.proxyPort='); + }, 120000); + + test('should work together with explicit -e flags', async () => { + const result = await runner.runWithSudo( + 'bash -c "echo HOST_VAR=$AWF_TEST_HOST_VAR && echo CLI_VAR=$AWF_TEST_CLI_VAR"', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + env: { + AWF_TEST_HOST_VAR: 'from_host', + }, + cliEnv: { + AWF_TEST_CLI_VAR: 'from_cli_flag', + }, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toContain('HOST_VAR=from_host'); + expect(result.stdout).toContain('CLI_VAR=from_cli_flag'); + }, 120000); + + test('explicit -e should override --env-all for same variable', async () => { + const result = await runner.runWithSudo( + 'echo $AWF_TEST_OVERRIDE_VAR', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + env: { + AWF_TEST_OVERRIDE_VAR: 'original_value', + }, + cliEnv: { + AWF_TEST_OVERRIDE_VAR: 'overridden_value', + }, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toContain('overridden_value'); + expect(result.stdout).not.toContain('original_value'); + }, 120000); + + test('should exclude system variables like PATH from passthrough', async () => { + const sentinel = '/tmp/awf-sentinel-path-marker'; + const result = await runner.runWithSudo( + 'echo $PATH', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + env: { + // Prepend sentinel to host PATH so sudo/node still work + PATH: `${sentinel}:${process.env.PATH}`, + }, + } + ); + + expect(result).toSucceed(); + // Container PATH should include its own default entries + expect(result.stdout).toContain('/usr/local/bin'); + // Host PATH sentinel must NOT leak into the container + expect(result.stdout).not.toContain(sentinel); + }, 120000); + }); });