mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 09:08:38 +00:00
Security: sanitize inherited host exec env
This commit is contained in:
committed by
Peter Steinberger
parent
9514201fb9
commit
48b052322b
@@ -29,6 +29,23 @@ import {
|
|||||||
import { buildCursorPositionResponse, stripDsrRequests } from "./pty-dsr.js";
|
import { buildCursorPositionResponse, stripDsrRequests } from "./pty-dsr.js";
|
||||||
import { getShellConfig, sanitizeBinaryOutput } from "./shell-utils.js";
|
import { getShellConfig, sanitizeBinaryOutput } from "./shell-utils.js";
|
||||||
|
|
||||||
|
// Sanitize inherited host env before merge so dangerous variables from process.env
|
||||||
|
// are not propagated into non-sandboxed executions.
|
||||||
|
export function sanitizeHostBaseEnv(env: Record<string, string>): Record<string, string> {
|
||||||
|
const sanitized: Record<string, string> = {};
|
||||||
|
for (const [key, value] of Object.entries(env)) {
|
||||||
|
const upperKey = key.toUpperCase();
|
||||||
|
if (upperKey === "PATH") {
|
||||||
|
sanitized[key] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isDangerousHostEnvVarName(upperKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sanitized[key] = value;
|
||||||
|
}
|
||||||
|
return sanitized;
|
||||||
|
}
|
||||||
// Centralized sanitization helper.
|
// Centralized sanitization helper.
|
||||||
// Throws an error if dangerous variables or PATH modifications are detected on the host.
|
// Throws an error if dangerous variables or PATH modifications are detected on the host.
|
||||||
export function validateHostEnv(env: Record<string, string>): void {
|
export function validateHostEnv(env: Record<string, string>): void {
|
||||||
|
|||||||
@@ -166,6 +166,29 @@ describe("exec host env validation", () => {
|
|||||||
).rejects.toThrow(/Security Violation: Environment variable 'LD_DEBUG' is forbidden/);
|
).rejects.toThrow(/Security Violation: Environment variable 'LD_DEBUG' is forbidden/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("strips dangerous inherited env vars from host execution", async () => {
|
||||||
|
if (isWin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const original = process.env.SSLKEYLOGFILE;
|
||||||
|
process.env.SSLKEYLOGFILE = "/tmp/openclaw-ssl-keys.log";
|
||||||
|
try {
|
||||||
|
const { createExecTool } = await import("./bash-tools.exec.js");
|
||||||
|
const tool = createExecTool({ host: "gateway", security: "full", ask: "off" });
|
||||||
|
const result = await tool.execute("call1", {
|
||||||
|
command: "printf '%s' \"${SSLKEYLOGFILE:-}\"",
|
||||||
|
});
|
||||||
|
const output = normalizeText(result.content.find((c) => c.type === "text")?.text);
|
||||||
|
expect(output).not.toContain("/tmp/openclaw-ssl-keys.log");
|
||||||
|
} finally {
|
||||||
|
if (original === undefined) {
|
||||||
|
delete process.env.SSLKEYLOGFILE;
|
||||||
|
} else {
|
||||||
|
process.env.SSLKEYLOGFILE = original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("defaults to sandbox when sandbox runtime is unavailable", async () => {
|
it("defaults to sandbox when sandbox runtime is unavailable", async () => {
|
||||||
const tool = createExecTool({ security: "full", ask: "off" });
|
const tool = createExecTool({ security: "full", ask: "off" });
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
renderExecHostLabel,
|
renderExecHostLabel,
|
||||||
resolveApprovalRunningNoticeMs,
|
resolveApprovalRunningNoticeMs,
|
||||||
runExecProcess,
|
runExecProcess,
|
||||||
|
sanitizeHostBaseEnv,
|
||||||
execSchema,
|
execSchema,
|
||||||
validateHostEnv,
|
validateHostEnv,
|
||||||
} from "./bash-tools.exec-runtime.js";
|
} from "./bash-tools.exec-runtime.js";
|
||||||
@@ -359,7 +360,8 @@ export function createExecTool(
|
|||||||
workdir = resolveWorkdir(rawWorkdir, warnings);
|
workdir = resolveWorkdir(rawWorkdir, warnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseEnv = coerceEnv(process.env);
|
const inheritedBaseEnv = coerceEnv(process.env);
|
||||||
|
const baseEnv = host === "sandbox" ? inheritedBaseEnv : sanitizeHostBaseEnv(inheritedBaseEnv);
|
||||||
|
|
||||||
// Logic: Sandbox gets raw env. Host (gateway/node) must pass validation.
|
// Logic: Sandbox gets raw env. Host (gateway/node) must pass validation.
|
||||||
// We validate BEFORE merging to prevent any dangerous vars from entering the stream.
|
// We validate BEFORE merging to prevent any dangerous vars from entering the stream.
|
||||||
|
|||||||
Reference in New Issue
Block a user