From c50f517bffff5c9aac1e00a1f895372861a8c94a Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 8 May 2026 17:26:26 -0300 Subject: [PATCH] fix(approval): run tirith check in cron-deny mode to catch content-level threats In check_all_command_guards, the cron-deny path only ran detect_dangerous_command (regex patterns). The tirith check starts at line 1017, after the early return at line 1002, so content-level threats caught only by tirith (homograph URLs, pipe-to-interpreter, terminal injection) were silently approved in cron sessions even with approvals.cron_mode: deny. Add a tirith call inside the cron-deny block, mirroring the same ImportError guard used in the main flow. Co-Authored-By: Claude Sonnet 4.6 --- tools/approval.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/approval.py b/tools/approval.py index 137902b91e7..92585abf5c8 100644 --- a/tools/approval.py +++ b/tools/approval.py @@ -1684,6 +1684,27 @@ def check_all_command_guards(command: str, env_type: str, "approvals.cron_mode: approve in config.yaml." ), } + # Also run tirith check in cron-deny mode so content-level + # threats (homograph URLs, pipe-to-interpreter, terminal + # injection, etc.) are caught even when they do not match + # the pattern-based detection above. + try: + from tools.tirith_security import check_command_security + _cron_tirith = check_command_security(command) + if _cron_tirith.get("action") in ("block", "warn"): + _cron_desc = _format_tirith_description(_cron_tirith) + return { + "approved": False, + "message": ( + f"BLOCKED: {_cron_desc} " + "but cron jobs run without a user present to approve it. " + "Find an alternative approach that avoids this command. " + "To allow dangerous commands in cron jobs, set " + "approvals.cron_mode: approve in config.yaml." + ), + } + except ImportError: + pass # tirith not installed — allow return {"approved": True, "message": None} # --- Phase 1: Gather findings from both checks ---