Skip to content

Built-in denylist prompts still interrupt High-autonomy Droid automation #1220

@coygeek

Description

@coygeek

Summary

droid exec --auto high and High-autonomy Droid sessions still stop for built-in denylisted shell commands such as rm -rf ..., even when those commands are scoped to disposable worktrees, temporary run directories, or other expected cleanup targets.

This creates a sharp limitation for autonomous orchestration workflows. Long-running agent workflows often need to remove temporary directories, delete completed worktrees, prune execution residue, or clean generated plan artifacts at the end of a run. When Droid pauses on a denylisted command, the workflow stalls until a human returns to approve the prompt.

There is a true bypass flag for headless runs:

droid exec --skip-permissions-unsafe ...

But the default “High autonomy” path is easy to mistake for unattended execution, and normal command allowlists do not appear to override this built-in denial class.

Impact

This affects automation systems that use Droid as a worker in unattended or mostly unattended local workflows, especially:

  • multi-agent execution coordinators
  • generated plan execution workflows
  • CI-like local runners
  • worktree-based implementation workers
  • tools that launch droid exec --auto high as a “fully autonomous” mode
  • cleanup-heavy workflows that remove temporary directories after verification

The failure mode is not that Droid refuses the task outright. The issue is that it pauses mid-run for an interactive confirmation prompt. That is worse for automation because the workflow can appear to be running normally until it reaches cleanup, then silently waits for manual input.

Example prompt shape:

Droid would like to run a deny-listed command

Command to approve (denylisted) · high risk
Why this needs approval: Matched deny-list entry "rm -rf /".

Yes, allow
No, cancel

In the observed case, the command was not literally trying to delete /; it included scoped cleanup paths, but the denylist explanation reported a broad rm -rf / pattern match. The prompt is still understandable from a safety perspective, but it is problematic for already-isolated or deliberately YOLO automation contexts.

Expected behavior

There should be a clear, documented way to run High-autonomy Droid workflows without interactive pauses for built-in denylisted shell commands when the caller has explicitly opted into that behavior.

Possible acceptable designs:

  • Allow --skip-permissions-unsafe to be configured as a default for droid exec.
  • Add a named session/default setting for “unsafe/no-prompt exec mode” that applies only to droid exec.
  • Add a narrower flag such as --allow-denylisted-commands or --no-command-prompts for isolated automation environments.
  • Provide a project/user-level policy mechanism that can explicitly override built-in command denylist prompts for droid exec.
  • Make --auto high documentation and CLI output more explicit that it is not unattended/YOLO mode and that denylisted commands still halt the run.

Actual behavior

droid exec --auto high still fails or pauses on denylisted destructive command patterns.

A disposable smoke test showed:

droid exec --auto high ...

Result:

Error during droid execution: Exec ended early: insufficient permission to proceed. Re-run with --skip-permissions-unsafe.

The disposable target directory remained present.

The same test with the unsafe bypass succeeded:

droid exec --skip-permissions-unsafe ...

Result:

Succeeded.

The disposable target directory was removed.

Allowlist behavior

A runtime settings smoke test attempted to allow broad command patterns, including:

{
  "sessionDefaultSettings": {
    "interactionMode": "auto",
    "autonomyLevel": "high"
  },
  "commandAllowlist": ["rm -rf *", "rm *", "*"]
}

droid exec --auto high still refused the disposable rm -rf command with:

Error during droid execution: Exec ended early: insufficient permission to proceed. Re-run with --skip-permissions-unsafe.

That suggests ordinary allowlist configuration cannot override this built-in denial class.

Workaround used locally

The reliable workaround was to wrap headless Droid launches so any droid exec ... invocation is rewritten to use the unsafe bypass:

droid() {
  local droid_bin="${DROID_BIN:-$HOME/.local/bin/droid}"
  local -a before_exec filtered_args
  local found_exec=0

  while [ "$#" -gt 0 ]; do
    if [ "$1" = "exec" ]; then
      found_exec=1
      shift
      break
    fi
    before_exec+=("$1")
    shift
  done

  if [ "$found_exec" -eq 1 ]; then
    local arg skip_next=0 has_skip=0
    for arg in "$@"; do
      if [ "$skip_next" -eq 1 ]; then
        skip_next=0
        continue
      fi

      case "$arg" in
        --skip-permissions-unsafe)
          has_skip=1
          filtered_args+=("$arg")
          ;;
        --auto)
          skip_next=1
          ;;
        --auto=*)
          ;;
        *)
          filtered_args+=("$arg")
          ;;
      esac
    done

    if [ "$has_skip" -eq 1 ]; then
      command "$droid_bin" "${before_exec[@]}" exec "${filtered_args[@]}"
    else
      command "$droid_bin" "${before_exec[@]}" exec --skip-permissions-unsafe "${filtered_args[@]}"
    fi
  else
    command "$droid_bin" "${before_exec[@]}"
  fi
}

This preserves interactive droid behavior because top-level interactive Droid does not accept --skip-permissions-unsafe. It only changes the droid exec automation surface.

The wrapper also strips incompatible --auto flags, because --skip-permissions-unsafe cannot be combined with --auto.

Hook workaround

A PreToolUse hook can return:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "User YOLO profile auto-approves Execute tool calls."
  },
  "suppressOutput": true
}

This appears to be the documented mechanism for bypassing the permission system for matching tools. A local hook was installed for the Execute tool.

However, this is less ideal as the main workaround because:

  • hook setup is more complex than a CLI flag
  • externally edited hooks may need review or activation in the TUI
  • it applies at the tool level rather than expressing an explicit “this headless run is isolated and unsafe prompts should be bypassed” mode
  • it is not as straightforward for automation launchers as a single stable CLI flag or settings key

Why this matters

Autonomous execution frameworks often rely on a simple contract:

droid exec --auto high "do the work, verify it, clean up"

In practice, that is not sufficient for unattended workflows because cleanup commands can still hit built-in denylist prompts.

The current workaround requires every automation launcher to know about:

  • --skip-permissions-unsafe
  • the fact that it cannot be combined with --auto
  • the need to strip inherited --auto flags
  • the distinction between interactive droid and headless droid exec

That creates avoidable friction and brittle wrapper code for users who intentionally run Droid inside disposable, isolated, or otherwise trusted environments.

Request

Please consider adding a first-class, documented way to configure or launch droid exec in true unattended mode without requiring shell wrapper rewrites.

The ideal fix would make the intended mode obvious and stable for automation callers, for example:

droid exec --auto high --allow-denylisted-commands ...

or:

{
  "execDefaultSettings": {
    "skipPermissionsUnsafe": true
  }
}

Even if the current safety behavior remains the default, it would help to have an explicit automation-safe escape hatch that does not require rewriting command-line arguments externally.

Environment

  • Droid CLI: 0.144.2
  • Mode affected: droid exec --auto high
  • Workaround confirmed: droid exec --skip-permissions-unsafe

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions