← Back to PRs

#21173: fix(config): support envFiles option in resolveConfigEnvVars for gateway-only secrets

by Mellowambience open 2026-02-19 19:03 View on GitHub →
size: S
## Summary Fixes #21130. When a secret is injected into the `openclaw-gateway` systemd service via `EnvironmentFile=`, the CLI process does **not** inherit that variable — so every CLI command that reads `openclaw.json` throws `MissingEnvVarError`, even though the gateway itself works fine. ## Root cause `resolveConfigEnvVars` always substitutes against `process.env`. There is no way to pass additional env sources, so gateway-only secrets are invisible to the CLI. ## Fix Adds two exports to `src/config/env-substitution.ts`: ### `parseEnvFile(content: string): Record<string, string>` Parses systemd-style `KEY=VALUE` env files: - Skips comment lines (`#`) - Handles quoted values (`"val"` / `'val'`) - Strips optional `export` prefix - Only accepts uppercase variable names (same pattern as existing substitution) ### `ResolveConfigEnvVarsOptions` ```ts interface ResolveConfigEnvVarsOptions { env?: NodeJS.ProcessEnv; // base env (defaults to process.env) envFiles?: string[]; // additional env-file contents to merge } ``` ### Updated `resolveConfigEnvVars` signature (fully backward compatible) ```ts // Legacy call — unchanged behaviour resolveConfigEnvVars(obj, process.env) // New call — merge gateway secrets file before substitution const fileContent = fs.readFileSync('/etc/openclaw/secrets/ai-assistant.env', 'utf8'); resolveConfigEnvVars(obj, { envFiles: [fileContent] }); ``` Values in `envFiles` override `env`; later entries override earlier ones. The existing `NodeJS.ProcessEnv` overload is detected by the absence of `env`/`envFiles` keys and routes to the old code path unchanged. ## What did NOT change - `substituteString` / `substituteAny` internals are unchanged - All existing tests continue to pass - `MissingEnvVarError` still throws for truly absent vars - No new dependencies ## Test coverage Existing 30+ tests in `env-substitution.test.ts` cover all existing paths. New `parseEnvFile` is self-contained and can be tested with: ```ts parseEnvFile('GITHUB_PAT=ghp_xxx\n# comment\nFOO="bar baz"') // → { GITHUB_PAT: 'ghp_xxx', FOO: 'bar baz' } ``` <!-- greptile_comment --> <h3>Greptile Summary</h3> Extends config substitution to support systemd file content parsing via new `parseEnvFile()` function and `envFiles` option. **Changes** - `parseEnvFile()` handles systemd format with comments and quotes - New `ResolveConfigEnvVarsOptions` interface for flexible sources - Maintains backward compatible signature **Issues** - Quote stripping bug for single-character values - Type detection breaks with certain object keys <h3>Confidence Score: 2/5</h3> - This PR has critical bugs that will cause incorrect behavior in edge cases - Two logic bugs found: (1) `parseEnvFile` incorrectly handles single-character quoted values, producing empty strings instead of the literal character, (2) backward compatibility check fails when legacy env objects contain `env` or `envFiles` keys, misidentifying them as new options format - src/config/env-substitution.ts requires fixes for quote handling and type detection <sub>Last reviewed commit: db6805e</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs