mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-21 01:54:58 +00:00
fix(exec): harden inherited host env sanitization (#25755) (thanks @bmendonca3)
This commit is contained in:
@@ -597,7 +597,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Security/Media: harden local media ingestion against TOCTOU/symlink swap attacks by pinning reads to a single file descriptor with symlink rejection and inode/device verification in `saveMediaSource`. Thanks @dorjoos for reporting.
|
||||
- Security/Lobster (Windows): for the next npm release, remove shell-based fallback when launching Lobster wrappers (`.cmd`/`.bat`) and switch to explicit argv execution with wrapper entrypoint resolution, preventing command injection while preserving Windows wrapper compatibility. Thanks @allsmog for reporting.
|
||||
- Security/Exec: require `tools.exec.safeBins` binaries to resolve from trusted bin directories (system defaults plus gateway startup `PATH`) so PATH-hijacked trojan binaries cannot bypass allowlist checks. Thanks @jackhax for reporting.
|
||||
- Security/Exec: sanitize inherited host execution environment before merge and strip dangerous keys (`LD_*`, `DYLD_*`, `SSLKEYLOGFILE`, and related injection vectors) from non-sandboxed exec runs. (#9792)
|
||||
- Security/Exec: sanitize inherited host execution environment before merge, canonicalize inherited PATH handling, and strip dangerous keys (`LD_*`, `DYLD_*`, `SSLKEYLOGFILE`, and related injection vectors) from non-sandboxed exec runs. (#25755) Thanks @bmendonca3.
|
||||
- Security/Exec: remove file-existence oracle behavior from `tools.exec.safeBins` by using deterministic argv-only stdin-safe validation and blocking file-oriented flags (for example `sort -o`, `jq -f`, `grep -f`) so allow/deny results no longer disclose host file presence. Thanks @nedlir for reporting.
|
||||
- Security/Browser: route browser URL navigation through one SSRF-guarded validation path for tab-open/CDP-target/Playwright navigation flows and block private/metadata destinations by default (configurable via `browser.ssrfPolicy`). Thanks @dorjoos for reporting.
|
||||
- Security/Exec: for the next npm release, harden safe-bin stdin-only enforcement by blocking output/recursive flags (`sort -o/--output`, grep recursion) and tightening default safe bins to remove `sort`/`grep`, preventing safe-bin allowlist bypass for file writes/recursive reads. Thanks @nedlir for reporting.
|
||||
|
||||
@@ -33,10 +33,12 @@ import { getShellConfig, sanitizeBinaryOutput } from "./shell-utils.js";
|
||||
// are not propagated into non-sandboxed executions.
|
||||
export function sanitizeHostBaseEnv(env: Record<string, string>): Record<string, string> {
|
||||
const sanitized: Record<string, string> = {};
|
||||
let hostPath: string | undefined;
|
||||
for (const [key, value] of Object.entries(env)) {
|
||||
const upperKey = key.toUpperCase();
|
||||
if (upperKey === "PATH") {
|
||||
sanitized[key] = value;
|
||||
// Canonicalize PATH casing so downstream PATH merges always hit one key.
|
||||
hostPath ??= value;
|
||||
continue;
|
||||
}
|
||||
if (isDangerousHostEnvVarName(upperKey)) {
|
||||
@@ -44,6 +46,9 @@ export function sanitizeHostBaseEnv(env: Record<string, string>): Record<string,
|
||||
}
|
||||
sanitized[key] = value;
|
||||
}
|
||||
if (hostPath !== undefined) {
|
||||
sanitized.PATH = hostPath;
|
||||
}
|
||||
return sanitized;
|
||||
}
|
||||
// Centralized sanitization helper.
|
||||
|
||||
@@ -4,6 +4,7 @@ import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ExecApprovalsResolved } from "../infra/exec-approvals.js";
|
||||
import { captureEnv } from "../test-utils/env.js";
|
||||
import { sanitizeHostBaseEnv } from "./bash-tools.exec-runtime.js";
|
||||
import { sanitizeBinaryOutput } from "./shell-utils.js";
|
||||
|
||||
const isWin = process.platform === "win32";
|
||||
@@ -155,6 +156,28 @@ describe("exec PATH login shell merge", () => {
|
||||
});
|
||||
|
||||
describe("exec host env validation", () => {
|
||||
it("sanitizes inherited host env without mutating source object", () => {
|
||||
const inherited = {
|
||||
PATH: "/usr/bin",
|
||||
Path: "/should-not-win",
|
||||
SAFE_KEY: "ok",
|
||||
LD_PRELOAD: "bad",
|
||||
sslkeylogfile: "/tmp/keys.log",
|
||||
};
|
||||
const sanitized = sanitizeHostBaseEnv(inherited);
|
||||
expect(sanitized).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
SAFE_KEY: "ok",
|
||||
});
|
||||
expect(inherited).toEqual({
|
||||
PATH: "/usr/bin",
|
||||
Path: "/should-not-win",
|
||||
SAFE_KEY: "ok",
|
||||
LD_PRELOAD: "bad",
|
||||
sslkeylogfile: "/tmp/keys.log",
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks LD_/DYLD_ env vars on host execution", async () => {
|
||||
const tool = createExecTool({ host: "gateway", security: "full", ask: "off" });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user