mirror of https://github.com/openclaw/openclaw.git
fix(security): restrict default safe-bin trusted dirs
This commit is contained in:
parent
2d159e5e87
commit
b67e600bff
|
|
@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Security/Workspace FS: normalize `@`-prefixed paths before workspace-boundary checks (including workspace-only read/write/edit and sandbox mount path guards), preventing absolute-path escape attempts from bypassing guard validation. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||
- Security/Native images: enforce `tools.fs.workspaceOnly` for native prompt image auto-load (including history refs), preventing out-of-workspace sandbox mounts from being implicitly ingested as vision input. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||
- Security/Exec approvals: bind `system.run` command display/approval text to full argv when shell-wrapper inline payloads carry positional argv values, and reject payload-only `rawCommand` mismatches for those wrapper-carrier forms, preventing hidden command execution under misleading approval text. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||
- Security/Exec: limit default safe-bin trusted directories to immutable system paths (`/bin`, `/usr/bin`) and require explicit opt-in (`tools.exec.safeBinTrustedDirs`) for package-manager/user bin paths (for example Homebrew), preventing writable-dir binary shadowing from auto-satisfying safe-bin allowlist checks. This ships in the next npm release. Thanks @tdjackey for reporting.
|
||||
- Telegram/Media fetch: prioritize IPv4 before IPv6 in SSRF pinned DNS address ordering so media downloads still work on hosts with broken IPv6 routing. (#24295, #23975) Thanks @Glucksberg.
|
||||
- Telegram/Replies: when markdown formatting renders to empty HTML (for example syntax-only chunks in threaded replies), retry delivery with plain text, and fail loud when both formatted and plain payloads are empty to avoid false delivered states. (#25096, #25091) Thanks @Glucksberg.
|
||||
- Sessions/Tool-result guard: avoid generating synthetic `toolResult` entries for assistant turns that ended with `stopReason: "aborted"` or `"error"`, preventing orphaned tool-use IDs from triggering downstream API validation errors. (#25429) Thanks @mikaeldiakhate-cell.
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ and no `$VARS` expansion) for stdin-only segments, so patterns like `*` or `$HOM
|
|||
used to smuggle file reads.
|
||||
Safe bins must also resolve from trusted binary directories (system defaults plus optional
|
||||
`tools.exec.safeBinTrustedDirs`). `PATH` entries are never auto-trusted.
|
||||
Default trusted safe-bin directories are intentionally minimal: `/bin`, `/usr/bin`.
|
||||
If your safe-bin executable lives in package-manager/user paths (for example
|
||||
`/opt/homebrew/bin`, `/usr/local/bin`, `/opt/local/bin`, `/snap/bin`), add them explicitly
|
||||
to `tools.exec.safeBinTrustedDirs`.
|
||||
Shell chaining and redirections are not auto-allowed in allowlist mode.
|
||||
|
||||
Shell chaining (`&&`, `||`, `;`) is allowed when every top-level segment satisfies the allowlist
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ Notes:
|
|||
- `tools.exec.node` (default: unset)
|
||||
- `tools.exec.pathPrepend`: list of directories to prepend to `PATH` for exec runs (gateway + sandbox only).
|
||||
- `tools.exec.safeBins`: stdin-only safe binaries that can run without explicit allowlist entries. For behavior details, see [Safe bins](/tools/exec-approvals#safe-bins-stdin-only).
|
||||
- `tools.exec.safeBinTrustedDirs`: additional explicit directories trusted for `safeBins` path checks. `PATH` entries are never auto-trusted.
|
||||
- `tools.exec.safeBinTrustedDirs`: additional explicit directories trusted for `safeBins` path checks. `PATH` entries are never auto-trusted. Built-in defaults are `/bin` and `/usr/bin`.
|
||||
- `tools.exec.safeBinProfiles`: optional custom argv policy per safe bin (`minPositional`, `maxPositional`, `allowedValueFlags`, `deniedFlags`).
|
||||
|
||||
Example:
|
||||
|
|
|
|||
|
|
@ -89,4 +89,18 @@ describe("exec safe-bin runtime policy", () => {
|
|||
expect(policy.trustedSafeBinDirs.has(path.resolve(customDir))).toBe(true);
|
||||
expect(policy.trustedSafeBinDirs.has(path.resolve(agentDir))).toBe(true);
|
||||
});
|
||||
|
||||
it("does not trust package-manager bin dirs unless explicitly configured", () => {
|
||||
const defaultPolicy = resolveExecSafeBinRuntimePolicy({});
|
||||
expect(defaultPolicy.trustedSafeBinDirs.has(path.resolve("/opt/homebrew/bin"))).toBe(false);
|
||||
expect(defaultPolicy.trustedSafeBinDirs.has(path.resolve("/usr/local/bin"))).toBe(false);
|
||||
|
||||
const optedIn = resolveExecSafeBinRuntimePolicy({
|
||||
global: {
|
||||
safeBinTrustedDirs: ["/opt/homebrew/bin", "/usr/local/bin"],
|
||||
},
|
||||
});
|
||||
expect(optedIn.trustedSafeBinDirs.has(path.resolve("/opt/homebrew/bin"))).toBe(true);
|
||||
expect(optedIn.trustedSafeBinDirs.has(path.resolve("/usr/local/bin"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@ import {
|
|||
} from "./exec-safe-bin-trust.js";
|
||||
|
||||
describe("exec safe bin trust", () => {
|
||||
it("keeps default trusted dirs limited to immutable system paths", () => {
|
||||
const dirs = getTrustedSafeBinDirs({ refresh: true });
|
||||
|
||||
expect(dirs.has(path.resolve("/bin"))).toBe(true);
|
||||
expect(dirs.has(path.resolve("/usr/bin"))).toBe(true);
|
||||
expect(dirs.has(path.resolve("/usr/local/bin"))).toBe(false);
|
||||
expect(dirs.has(path.resolve("/opt/homebrew/bin"))).toBe(false);
|
||||
});
|
||||
|
||||
it("builds trusted dirs from defaults and explicit extra dirs", () => {
|
||||
const dirs = buildTrustedSafeBinDirs({
|
||||
baseDirs: ["/usr/bin"],
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
import path from "node:path";
|
||||
|
||||
const DEFAULT_SAFE_BIN_TRUSTED_DIRS = [
|
||||
"/bin",
|
||||
"/usr/bin",
|
||||
"/usr/local/bin",
|
||||
"/opt/homebrew/bin",
|
||||
"/opt/local/bin",
|
||||
"/snap/bin",
|
||||
"/run/current-system/sw/bin",
|
||||
];
|
||||
// Keep defaults to OS-managed immutable bins only.
|
||||
// User/package-manager bins must be opted in via tools.exec.safeBinTrustedDirs.
|
||||
const DEFAULT_SAFE_BIN_TRUSTED_DIRS = ["/bin", "/usr/bin"];
|
||||
|
||||
type TrustedSafeBinDirsParams = {
|
||||
baseDirs?: readonly string[];
|
||||
|
|
|
|||
Loading…
Reference in New Issue