From 65ce21ee8bbdbb1e79a13ef632cb0ea74d337542 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Wed, 25 Feb 2026 20:14:00 +0000 Subject: [PATCH 1/2] test: add --env-all integration tests (#1042) Add envAll and cliEnv options to AwfRunner for testing --env-all and -e CLI flags. Add integration tests verifying: - --env-all passes host env vars into container - Proxy env vars (HTTP_PROXY, HTTPS_PROXY) are correctly set - JAVA_TOOL_OPTIONS has JVM proxy properties - --env-all combined with -e flags - -e overrides --env-all for same variable - PATH excluded from passthrough Closes #1042 Co-Authored-By: Claude Opus 4.6 --- tests/fixtures/awf-runner.ts | 26 ++++ .../integration/environment-variables.test.ts | 113 ++++++++++++++++++ 2 files changed, 139 insertions(+) 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..5a074dce 100644 --- a/tests/integration/environment-variables.test.ts +++ b/tests/integration/environment-variables.test.ts @@ -159,4 +159,117 @@ 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 result = await runner.runWithSudo( + 'echo $PATH', + { + allowDomains: ['github.com'], + logLevel: 'debug', + timeout: 60000, + envAll: true, + } + ); + + expect(result).toSucceed(); + expect(result.stdout).toContain('/usr/local/bin'); + }, 120000); + }); }); From cb042b29b3a9c2da0c9e0cebba0e723a3ae4ee16 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Wed, 25 Feb 2026 21:05:01 +0000 Subject: [PATCH 2/2] test: strengthen PATH exclusion test with sentinel value Address Copilot review: the previous test only checked that the container PATH contains /usr/local/bin, which is always true. Now prepend a sentinel to the host PATH and verify it does NOT appear in the container, proving --env-all correctly excludes PATH. Co-Authored-By: Claude Opus 4.6 --- tests/integration/environment-variables.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/integration/environment-variables.test.ts b/tests/integration/environment-variables.test.ts index 5a074dce..749b1bab 100644 --- a/tests/integration/environment-variables.test.ts +++ b/tests/integration/environment-variables.test.ts @@ -258,6 +258,7 @@ describe('Environment Variable Handling', () => { }, 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', { @@ -265,11 +266,18 @@ describe('Environment Variable Handling', () => { 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); }); });