feat(workflows): enforce node autoApprove by bypassing the CLI approval pause

The node "Auto-approve requests" toggle was captured but unused. The only
human-approval pause reachable from a custom node is the CLI first-run
trust-on-first-use gate (review-style nodes run as ephemeral readonly agents
with no permission gate), so autoApprove now bypasses that pause — a superset
of the CLI-specific cliSkipApproval flag. The inspector explains the effect
when the toggle is on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-06-03 15:26:29 -07:00
parent bd8f0fd23c
commit 291072446d
2 changed files with 18 additions and 8 deletions

View File

@@ -527,6 +527,11 @@ function InnerEditor({
/>
<span>Auto-approve requests</span>
</label>
{Boolean(selectedNode.data.config?.autoApprove) && (
<p className="wf-inspector-note">
Runs without pausing for approval — e.g. a CLI command executes on its first run without waiting for your sign-off.
</p>
)}
<label className="wf-field">
<span>Max retries</span>

View File

@@ -3503,16 +3503,21 @@ export class TaskExecutor {
const rawCommand = rawCliCommand;
if (rawCommand) {
// Arbitrary command: gated by trust-on-first-use approval unless the
// node explicitly opts out (cliSkipApproval). The exact command string
// must otherwise have been approved by the user.
// node explicitly opts out. Two node flags bypass the pause:
// - cliSkipApproval: CLI-specific "skip first-run approval".
// - autoApprove: the node's general "Auto-approve requests"
// toggle. The only human-approval pause reachable from a custom
// node is this CLI gate (review-style nodes run as ephemeral
// readonly agents with no permission gate), so honoring it here is
// what makes that toggle actually do something.
// The exact command string must otherwise have been approved by the user.
//
// SECURITY: cliSkipApproval is an intentional project-owner-only escape
// hatch. It is only reachable by someone who can author/edit a workflow
// SECURITY: both flags are intentional project-owner-only escape hatches.
// They are only reachable by someone who can author/edit a workflow
// definition for this project — the same trust boundary that already
// lets them add named scripts. It is NOT an untrusted-input surface.
// (Aligned with autoApprove, which is likewise gated by workflow
// authorship; neither is enforced at the IR-validation layer.)
const skipApproval = cfg.cliSkipApproval === true;
// lets them add named scripts. They are NOT untrusted-input surfaces,
// and neither is enforced at the IR-validation layer.
const skipApproval = cfg.cliSkipApproval === true || cfg.autoApprove === true;
if (!skipApproval && !(await this.store.isWorkflowCliCommandApproved(rawCommand))) {
return this.pauseForCliApproval(node, live, rawCommand);
}