fix(exec): resolve remote approval regressions (#58792)

* fix(exec): restore remote approval policy defaults

* fix(exec): handle headless cron approval conflicts

* fix(exec): make allow-always durable

* fix(exec): persist exact-command shell trust

* fix(doctor): match host exec fallback

* fix(exec): preserve blocked and inline approval state

* Doctor: surface allow-always ask bypass

* Doctor: match effective exec policy

* Exec: match node durable command text

* Exec: tighten durable approval security

* Exec: restore owner approver fallback

* Config: refresh Slack approval metadata

---------

Co-authored-by: scoootscooob <zhentongfan@gmail.com>
This commit is contained in:
Vincent Koc
2026-04-01 18:07:20 +09:00
committed by GitHub
parent 4ceb01f9ed
commit 2d53ffdec1
34 changed files with 1609 additions and 226 deletions

View File

@@ -594,14 +594,18 @@ export function createExecTool(
});
const host: ExecHost = target.effectiveHost;
const configuredSecurity = defaults?.security ?? (host === "sandbox" ? "deny" : "allowlist");
const approvalDefaults = loadExecApprovals().defaults;
const configuredSecurity =
defaults?.security ??
approvalDefaults?.security ??
(host === "sandbox" ? "deny" : "allowlist");
const requestedSecurity = normalizeExecSecurity(params.security);
let security = minSecurity(configuredSecurity, requestedSecurity ?? configuredSecurity);
if (elevatedRequested && elevatedMode === "full") {
security = "full";
}
// Keep local exec defaults in sync with exec-approvals.json when tools.exec.ask is unset.
const configuredAsk = defaults?.ask ?? loadExecApprovals().defaults?.ask ?? "on-miss";
// Keep local exec defaults in sync with exec-approvals.json when tools.exec.* is unset.
const configuredAsk = defaults?.ask ?? approvalDefaults?.ask ?? "on-miss";
const requestedAsk = normalizeExecAsk(params.ask);
let ask = maxAsk(configuredAsk, requestedAsk ?? configuredAsk);
const bypassApprovals = elevatedRequested && elevatedMode === "full";
@@ -726,6 +730,7 @@ export function createExecTool(
security,
ask,
strictInlineEval: defaults?.strictInlineEval,
trigger: defaults?.trigger,
timeoutSec: params.timeout,
defaultTimeoutSec,
approvalRunningNoticeMs,
@@ -749,6 +754,7 @@ export function createExecTool(
safeBins,
safeBinProfiles,
strictInlineEval: defaults?.strictInlineEval,
trigger: defaults?.trigger,
agentId,
sessionKey: defaults?.sessionKey,
turnSourceChannel: defaults?.messageProvider,
@@ -767,6 +773,9 @@ export function createExecTool(
return gatewayResult.pendingResult;
}
execCommandOverride = gatewayResult.execCommandOverride;
if (gatewayResult.allowWithoutEnforcedCommand) {
execCommandOverride = undefined;
}
}
const explicitTimeoutSec = typeof params.timeout === "number" ? params.timeout : null;