fix(security): clarify denyCommands exact-match guidance

This commit is contained in:
Peter Steinberger
2026-02-26 00:55:25 +01:00
parent eb73e87f18
commit 42f455739f
5 changed files with 30 additions and 5 deletions

View File

@@ -29,7 +29,7 @@ It also emits `security.trust_model.multi_user_heuristic` when config suggests l
For intentional shared-user setups, the audit guidance is to sandbox all sessions, keep filesystem access workspace-scoped, and keep personal/private identities or credentials off that runtime. For intentional shared-user setups, the audit guidance is to sandbox all sessions, keep filesystem access workspace-scoped, and keep personal/private identities or credentials off that runtime.
It also warns when small models (`<=300B`) are used without sandboxing and with web/browser tools enabled. It also warns when small models (`<=300B`) are used without sandboxing and with web/browser tools enabled.
For webhook ingress, it warns when `hooks.defaultSessionKey` is unset, when request `sessionKey` overrides are enabled, and when overrides are enabled without `hooks.allowedSessionKeyPrefixes`. For webhook ingress, it warns when `hooks.defaultSessionKey` is unset, when request `sessionKey` overrides are enabled, and when overrides are enabled without `hooks.allowedSessionKeyPrefixes`.
It also warns when sandbox Docker settings are configured while sandbox mode is off, when `gateway.nodes.denyCommands` uses ineffective pattern-like/unknown entries, when `gateway.nodes.allowCommands` explicitly enables dangerous node commands, when global `tools.profile="minimal"` is overridden by agent tool profiles, when open groups expose runtime/filesystem tools without sandbox/workspace guards, and when installed extension plugin tools may be reachable under permissive tool policy. It also warns when sandbox Docker settings are configured while sandbox mode is off, when `gateway.nodes.denyCommands` uses ineffective pattern-like/unknown entries (exact node command-name matching only, not shell-text filtering), when `gateway.nodes.allowCommands` explicitly enables dangerous node commands, when global `tools.profile="minimal"` is overridden by agent tool profiles, when open groups expose runtime/filesystem tools without sandbox/workspace guards, and when installed extension plugin tools may be reachable under permissive tool policy.
It also flags `gateway.allowRealIpFallback=true` (header-spoofing risk if proxies are misconfigured) and `discovery.mdns.mode="full"` (metadata leakage via mDNS TXT records). It also flags `gateway.allowRealIpFallback=true` (header-spoofing risk if proxies are misconfigured) and `discovery.mdns.mode="full"` (metadata leakage via mDNS TXT records).
It also warns when sandbox browser uses Docker `bridge` network without `sandbox.browser.cdpSourceRange`. It also warns when sandbox browser uses Docker `bridge` network without `sandbox.browser.cdpSourceRange`.
It also flags dangerous sandbox Docker network modes (including `host` and `container:*` namespace joins). It also flags dangerous sandbox Docker network modes (including `host` and `container:*` namespace joins).

View File

@@ -188,7 +188,7 @@ If more than one person can DM your bot:
- **Browser control exposure** (remote nodes, relay ports, remote CDP endpoints). - **Browser control exposure** (remote nodes, relay ports, remote CDP endpoints).
- **Local disk hygiene** (permissions, symlinks, config includes, “synced folder” paths). - **Local disk hygiene** (permissions, symlinks, config includes, “synced folder” paths).
- **Plugins** (extensions exist without an explicit allowlist). - **Plugins** (extensions exist without an explicit allowlist).
- **Policy drift/misconfig** (sandbox docker settings configured but sandbox mode off; ineffective `gateway.nodes.denyCommands` patterns; dangerous `gateway.nodes.allowCommands` entries; global `tools.profile="minimal"` overridden by per-agent profiles; extension plugin tools reachable under permissive tool policy). - **Policy drift/misconfig** (sandbox docker settings configured but sandbox mode off; ineffective `gateway.nodes.denyCommands` patterns because matching is exact command-name only (for example `system.run`) and does not inspect shell text; dangerous `gateway.nodes.allowCommands` entries; global `tools.profile="minimal"` overridden by per-agent profiles; extension plugin tools reachable under permissive tool policy).
- **Runtime expectation drift** (for example `tools.exec.host="sandbox"` while sandbox mode is off, which runs directly on the gateway host). - **Runtime expectation drift** (for example `tools.exec.host="sandbox"` while sandbox mode is off, which runs directly on the gateway host).
- **Model hygiene** (warn when configured models look legacy; not a hard block). - **Model hygiene** (warn when configured models look legacy; not a hard block).

View File

@@ -330,7 +330,7 @@ export const FIELD_HELP: Record<string, string> = {
"gateway.nodes.allowCommands": "gateway.nodes.allowCommands":
"Extra node.invoke commands to allow beyond the gateway defaults (array of command strings). Enabling dangerous commands here is a security-sensitive override and is flagged by `openclaw security audit`.", "Extra node.invoke commands to allow beyond the gateway defaults (array of command strings). Enabling dangerous commands here is a security-sensitive override and is flagged by `openclaw security audit`.",
"gateway.nodes.denyCommands": "gateway.nodes.denyCommands":
"Commands to block even if present in node claims or default allowlist.", "Node command names to block even if present in node claims or default allowlist (exact command-name matching only, e.g. `system.run`; does not inspect shell text inside that command).",
nodeHost: nodeHost:
"Node host controls for features exposed from this gateway node to other nodes or clients. Keep defaults unless you intentionally proxy local capabilities across your node network.", "Node host controls for features exposed from this gateway node to other nodes or clients. Keep defaults unless you intentionally proxy local capabilities across your node network.",
"nodeHost.browserProxy": "nodeHost.browserProxy":

View File

@@ -365,6 +365,31 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
); );
}); });
it("denies semicolon-chained shell payloads in allowlist mode without explicit approval", async () => {
const payloads = ["openclaw status; id", "openclaw status; cat /etc/passwd"];
for (const payload of payloads) {
const command =
process.platform === "win32"
? ["cmd.exe", "/d", "/s", "/c", payload]
: ["/bin/sh", "-lc", payload];
const { runCommand, sendInvokeResult } = await runSystemInvoke({
preferMacAppExecHost: false,
security: "allowlist",
ask: "on-miss",
command,
});
expect(runCommand, payload).not.toHaveBeenCalled();
expect(sendInvokeResult, payload).toHaveBeenCalledWith(
expect.objectContaining({
ok: false,
error: expect.objectContaining({
message: "SYSTEM_RUN_DENIED: approval required",
}),
}),
);
}
});
it("denies nested env shell payloads when wrapper depth is exceeded", async () => { it("denies nested env shell payloads when wrapper depth is exceeded", async () => {
if (process.platform === "win32") { if (process.platform === "win32") {
return; return;

View File

@@ -955,11 +955,11 @@ export function collectNodeDenyCommandPatternFindings(cfg: OpenClawConfig): Secu
severity: "warn", severity: "warn",
title: "Some gateway.nodes.denyCommands entries are ineffective", title: "Some gateway.nodes.denyCommands entries are ineffective",
detail: detail:
"gateway.nodes.denyCommands uses exact command-name matching only.\n" + "gateway.nodes.denyCommands uses exact node command-name matching only (for example `system.run`), not shell-text filtering inside a command payload.\n" +
detailParts.map((entry) => `- ${entry}`).join("\n"), detailParts.map((entry) => `- ${entry}`).join("\n"),
remediation: remediation:
`Use exact command names (for example: ${examples.join(", ")}). ` + `Use exact command names (for example: ${examples.join(", ")}). ` +
"If you need broader restrictions, remove risky commands from allowCommands/default workflows.", "If you need broader restrictions, remove risky command IDs from allowCommands/default workflows and tighten tools.exec policy.",
}); });
return findings; return findings;