fix(security): detect obfuscated commands that bypass allowlist filters (#24287)
* security(exec): add obfuscated command detector * test(exec): cover obfuscation detector patterns * security(exec): enforce obfuscation approval on gateway host * security(exec): enforce obfuscation approval on node host * test(exec): prevent obfuscation timeout bypass * chore(changelog): credit obfuscation security fix
This commit is contained in:
@@ -11,7 +11,9 @@ import {
|
||||
resolveExecApprovals,
|
||||
resolveExecApprovalsFromFile,
|
||||
} from "../infra/exec-approvals.js";
|
||||
import { detectCommandObfuscation } from "../infra/exec-obfuscation-detect.js";
|
||||
import { buildNodeShellCommand } from "../infra/node-shell.js";
|
||||
import { logInfo } from "../logger.js";
|
||||
import { requestExecApprovalDecisionForHost } from "./bash-tools.exec-approval-request.js";
|
||||
import {
|
||||
DEFAULT_APPROVAL_TIMEOUT_MS,
|
||||
@@ -133,12 +135,20 @@ export async function executeNodeHostCommand(
|
||||
// Fall back to requiring approval if node approvals cannot be fetched.
|
||||
}
|
||||
}
|
||||
const requiresAsk = requiresExecApproval({
|
||||
ask: hostAsk,
|
||||
security: hostSecurity,
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
});
|
||||
const obfuscation = detectCommandObfuscation(params.command);
|
||||
if (obfuscation.detected) {
|
||||
logInfo(
|
||||
`exec: obfuscation detected (node=${nodeQuery ?? "default"}): ${obfuscation.reasons.join(", ")}`,
|
||||
);
|
||||
params.warnings.push(`⚠️ Obfuscated command detected: ${obfuscation.reasons.join("; ")}`);
|
||||
}
|
||||
const requiresAsk =
|
||||
requiresExecApproval({
|
||||
ask: hostAsk,
|
||||
security: hostSecurity,
|
||||
analysisOk,
|
||||
allowlistSatisfied,
|
||||
}) || obfuscation.detected;
|
||||
const invokeTimeoutMs = Math.max(
|
||||
10_000,
|
||||
(typeof params.timeoutSec === "number" ? params.timeoutSec : params.defaultTimeoutSec) * 1000 +
|
||||
@@ -203,7 +213,9 @@ export async function executeNodeHostCommand(
|
||||
if (decision === "deny") {
|
||||
deniedReason = "user-denied";
|
||||
} else if (!decision) {
|
||||
if (askFallback === "full") {
|
||||
if (obfuscation.detected) {
|
||||
deniedReason = "approval-timeout (obfuscation-detected)";
|
||||
} else if (askFallback === "full") {
|
||||
approvedByAsk = true;
|
||||
approvalDecision = "allow-once";
|
||||
} else if (askFallback === "allowlist") {
|
||||
|
||||
Reference in New Issue
Block a user