9c81c938d3
check_all_command_guards() swallowed ImportError from tools.tirith_security with an unconditional pass, leaving tirith_result["action"] as "allow" regardless of security.tirith_fail_open. When an operator sets tirith_fail_open: false they have explicitly opted into fail-closed behaviour; a missing or broken Tirith module must not silently permit command execution. Inside the except ImportError handler, read the live security config. When tirith_enabled is true and tirith_fail_open is false, synthesise a "warn"-action Tirith result so the command flows through the normal approval path (prompt the user, or block in cron/gateway contexts) instead of bypassing it. The default tirith_fail_open: true behaviour is unchanged. Adds three regression tests to tests/tools/test_approval.py: - fail_open=true + ImportError → silently allowed (no regression) - fail_open=false + ImportError → approval callback invoked, command denied - tirith_enabled=false → always allowed regardless of fail_open Fixes #20733 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> # Conflicts: # tests/tools/test_approval.py