fix: normalize env var keys and isolate tests from real .env

- Apply normalizeEnvVarKey({ portable: true }) before security
  filtering, matching the established pattern in env-vars.ts.
  Rejects non-portable key names (spaces, special chars) that
  would produce invalid plist/systemd syntax.

- Isolate existing tests from the developer's real ~/.openclaw/.env
  by providing a temp HOME directory, preventing flaky failures
  when the test machine has a populated .env file.
This commit is contained in:
Kevin ONeill
2026-03-22 17:27:16 -05:00
committed by Peter Steinberger
parent 77ec7b4adf
commit dd860e76aa
2 changed files with 20 additions and 5 deletions

View File

@@ -86,11 +86,21 @@ function mockNodeGatewayPlanFixture(
}
describe("buildGatewayInstallPlan", () => {
// Prevent tests from reading the developer's real ~/.openclaw/.env when
// passing `env: {}` (which falls back to os.homedir for state-dir resolution).
let isolatedHome: string;
beforeEach(() => {
isolatedHome = fs.mkdtempSync(path.join(os.tmpdir(), "oc-plan-test-"));
});
afterEach(() => {
fs.rmSync(isolatedHome, { recursive: true, force: true });
});
it("uses provided nodePath and returns plan", async () => {
mockNodeGatewayPlanFixture();
const plan = await buildGatewayInstallPlan({
env: {},
env: { HOME: isolatedHome },
port: 3000,
runtime: "node",
nodePath: "/custom/node",
@@ -102,7 +112,7 @@ describe("buildGatewayInstallPlan", () => {
expect(mocks.resolvePreferredNodePath).not.toHaveBeenCalled();
expect(mocks.buildServiceEnvironment).toHaveBeenCalledWith(
expect.objectContaining({
env: {},
env: { HOME: isolatedHome },
port: 3000,
extraPathDirs: ["/custom"],
}),
@@ -113,7 +123,7 @@ describe("buildGatewayInstallPlan", () => {
mockNodeGatewayPlanFixture();
await buildGatewayInstallPlan({
env: {},
env: { HOME: isolatedHome },
port: 3000,
runtime: "node",
nodePath: "node",

View File

@@ -15,6 +15,7 @@ import { buildServiceEnvironment } from "../daemon/service-env.js";
import {
isDangerousHostEnvOverrideVarName,
isDangerousHostEnvVarName,
normalizeEnvVarKey,
} from "../infra/host-env-security.js";
import {
emitDaemonInstallRuntimeWarning,
@@ -49,8 +50,12 @@ export function readStateDirDotEnvVars(
const parsed = dotenv.parse(content);
const entries: Record<string, string> = {};
for (const [key, value] of Object.entries(parsed)) {
if (!key || !value?.trim()) {
for (const [rawKey, value] of Object.entries(parsed)) {
if (!value?.trim()) {
continue;
}
const key = normalizeEnvVarKey(rawKey, { portable: true });
if (!key) {
continue;
}
if (isDangerousHostEnvVarName(key) || isDangerousHostEnvOverrideVarName(key)) {