mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-03 02:38:23 +00:00
fix(security): block shell-wrapper line-continuation allowlist bypass
This commit is contained in:
@@ -5,6 +5,7 @@ export type ExecApprovalDecision = "allow-once" | "allow-always" | null;
|
||||
export type SystemRunPolicyDecision = {
|
||||
analysisOk: boolean;
|
||||
allowlistSatisfied: boolean;
|
||||
shellWrapperBlocked: boolean;
|
||||
windowsShellWrapperBlocked: boolean;
|
||||
requiresAsk: boolean;
|
||||
approvalDecision: ExecApprovalDecision;
|
||||
@@ -28,6 +29,7 @@ export function resolveExecApprovalDecision(value: unknown): ExecApprovalDecisio
|
||||
}
|
||||
|
||||
export function formatSystemRunAllowlistMissMessage(params?: {
|
||||
shellWrapperBlocked?: boolean;
|
||||
windowsShellWrapperBlocked?: boolean;
|
||||
}): string {
|
||||
if (params?.windowsShellWrapperBlocked) {
|
||||
@@ -37,6 +39,13 @@ export function formatSystemRunAllowlistMissMessage(params?: {
|
||||
"approve once/always or run with --ask on-miss|always)"
|
||||
);
|
||||
}
|
||||
if (params?.shellWrapperBlocked) {
|
||||
return (
|
||||
"SYSTEM_RUN_DENIED: allowlist miss " +
|
||||
"(shell wrappers like sh/bash/zsh -c require approval; " +
|
||||
"approve once/always or run with --ask on-miss|always)"
|
||||
);
|
||||
}
|
||||
return "SYSTEM_RUN_DENIED: allowlist miss";
|
||||
}
|
||||
|
||||
@@ -49,11 +58,13 @@ export function evaluateSystemRunPolicy(params: {
|
||||
approved?: boolean;
|
||||
isWindows: boolean;
|
||||
cmdInvocation: boolean;
|
||||
shellWrapperInvocation: boolean;
|
||||
}): SystemRunPolicyDecision {
|
||||
const shellWrapperBlocked = params.security === "allowlist" && params.shellWrapperInvocation;
|
||||
const windowsShellWrapperBlocked =
|
||||
params.security === "allowlist" && params.isWindows && params.cmdInvocation;
|
||||
const analysisOk = windowsShellWrapperBlocked ? false : params.analysisOk;
|
||||
const allowlistSatisfied = windowsShellWrapperBlocked ? false : params.allowlistSatisfied;
|
||||
shellWrapperBlocked && params.isWindows && params.cmdInvocation;
|
||||
const analysisOk = shellWrapperBlocked ? false : params.analysisOk;
|
||||
const allowlistSatisfied = shellWrapperBlocked ? false : params.allowlistSatisfied;
|
||||
const approvedByAsk = params.approvalDecision !== null || params.approved === true;
|
||||
|
||||
if (params.security === "deny") {
|
||||
@@ -63,6 +74,7 @@ export function evaluateSystemRunPolicy(params: {
|
||||
errorMessage: "SYSTEM_RUN_DISABLED: security=deny",
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
shellWrapperBlocked,
|
||||
windowsShellWrapperBlocked,
|
||||
requiresAsk: false,
|
||||
approvalDecision: params.approvalDecision,
|
||||
@@ -83,6 +95,7 @@ export function evaluateSystemRunPolicy(params: {
|
||||
errorMessage: "SYSTEM_RUN_DENIED: approval required",
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
shellWrapperBlocked,
|
||||
windowsShellWrapperBlocked,
|
||||
requiresAsk,
|
||||
approvalDecision: params.approvalDecision,
|
||||
@@ -94,9 +107,13 @@ export function evaluateSystemRunPolicy(params: {
|
||||
return {
|
||||
allowed: false,
|
||||
eventReason: "allowlist-miss",
|
||||
errorMessage: formatSystemRunAllowlistMissMessage({ windowsShellWrapperBlocked }),
|
||||
errorMessage: formatSystemRunAllowlistMissMessage({
|
||||
shellWrapperBlocked,
|
||||
windowsShellWrapperBlocked,
|
||||
}),
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
shellWrapperBlocked,
|
||||
windowsShellWrapperBlocked,
|
||||
requiresAsk,
|
||||
approvalDecision: params.approvalDecision,
|
||||
@@ -108,6 +125,7 @@ export function evaluateSystemRunPolicy(params: {
|
||||
allowed: true,
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
shellWrapperBlocked,
|
||||
windowsShellWrapperBlocked,
|
||||
requiresAsk,
|
||||
approvalDecision: params.approvalDecision,
|
||||
|
||||
Reference in New Issue
Block a user