Skip to content

feat: configurable approval mode for cron jobs (approvals.cron_mode)#3768

Merged
teknium1 merged 1 commit intomainfrom
feat/cron-approval-mode
Apr 19, 2026
Merged

feat: configurable approval mode for cron jobs (approvals.cron_mode)#3768
teknium1 merged 1 commit intomainfrom
feat/cron-approval-mode

Conversation

@teknium1
Copy link
Copy Markdown
Contributor

Summary

Adds a new approvals.cron_mode config option that controls how cron jobs handle dangerous commands. Previously, cron jobs silently auto-approved all dangerous commands because there was no user present to approve them — a potential security hole.

New config option

approvals:
  mode: manual        # existing — interactive sessions
  cron_mode: deny     # NEW — what to do when nobody can approve

Values:

  • deny (default) — block dangerous commands and let the agent find another way
  • approve — auto-approve everything (previous behavior)

How it works

When cron_mode: deny and a cron job tries to run a dangerous command, the command is blocked and the agent receives:

{"output": "", "exit_code": -1, "status": "blocked", "error": "BLOCKED: Command flagged as dangerous (...) but cron jobs run without a user present to approve it. Find an alternative approach..."}

This is identical to what happens when a user clicks "deny" in the CLI — the agent loop continues, it just has to adapt and find another way. The key insight: the denial doesn't stop the loop.

Changes

File Change
hermes_cli/config.py Add approvals.cron_mode: deny to DEFAULT_CONFIG
cron/scheduler.py Set HERMES_CRON_SESSION=1 env var before agent runs
tools/approval.py Add _get_cron_approval_mode() helper; modify both check_command_approval() and check_all_command_guards() to respect cron_mode
tests/tools/test_cron_approval_mode.py 21 new tests — config parsing, deny/approve behavior, edge cases

Interactions with other mechanisms

  • Container environments (docker, modal, etc.) still auto-approve regardless of cron_mode
  • --yolo / approvals.mode: off still overrides cron_mode
  • Non-cron, non-interactive sessions (scripted usage) still auto-approve as before
  • Safe commands (ls, echo, git, etc.) are never blocked

Test plan

python -m pytest tests/tools/test_cron_approval_mode.py -n0 -q  # 21 tests
python -m pytest tests/ -n0 -q                                    # full suite

Add approvals.cron_mode config option that controls how cron jobs handle
dangerous commands. Previously, cron jobs silently auto-approved all
dangerous commands because there was no user present to approve them.

Now the behavior is configurable:
  - deny (default): block dangerous commands and return a message telling
    the agent to find an alternative approach. The agent loop continues —
    it just can't use that specific command.
  - approve: auto-approve all dangerous commands (previous behavior).

When a command is blocked, the agent receives the same response format as
a user denial in the CLI — exit_code=-1, status=blocked, with a message
explaining why and pointing to the config option. This keeps the agent
loop running and encourages it to adapt.

Implementation:
  - config.py: add approvals.cron_mode to DEFAULT_CONFIG
  - scheduler.py: set HERMES_CRON_SESSION=1 env var before agent runs
  - approval.py: both check_command_approval() and check_all_command_guards()
    now check for cron sessions and apply the configured mode
  - 21 new tests covering config parsing, deny/approve behavior, and
    interaction with other bypass mechanisms (yolo, containers)
@teknium1 teknium1 force-pushed the feat/cron-approval-mode branch from c9152d4 to e01d668 Compare April 19, 2026 02:20
@teknium1 teknium1 merged commit 762f7e9 into main Apr 19, 2026
5 of 7 checks passed
@teknium1 teknium1 deleted the feat/cron-approval-mode branch April 19, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant