fix(approval): harden YOLO bypass, LLM parsing, auto-approve audit, pipe pattern (#23835)
* fix(approval): harden YOLO bypass, LLM parsing, auto-approve audit, pipe pattern - BUG-009 (CRITICAL): freeze HERMES_YOLO_MODE at module import via _YOLO_MODE_FROZEN; prevents skills/prompt-injection from calling os.environ["HERMES_YOLO_MODE"]="true" at runtime to bypass all checks - BUG-002 (HIGH): replace substring "APPROVE" in answer with exact answer == "APPROVE" in _smart_approve; prompt already requests exactly one word, substring match was exploitable via verbose LLM responses - BUG-001 (MEDIUM): add logger.warning for every dangerous command that auto-approves in non-interactive non-gateway context; makes silent approvals visible in audit logs without breaking script behavior - BUG-008 (LOW): expand curl/wget pipe pattern to cover | /bin/bash and | bash -c variants, not just | sh / | bash Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(approval): add missing is_truthy_value import + fix yolo test patches _YOLO_MODE_FROZEN uses is_truthy_value() from utils — import was missing. Tests that set HERMES_YOLO_MODE via monkeypatch.setenv() no longer work because the value is frozen at import time; update them to patch the module-level flag directly via monkeypatch.setattr(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
3ab7e2aa91
commit
4cb3eb03c7
@@ -55,8 +55,8 @@ class TestYoloMode:
|
||||
assert not result["approved"]
|
||||
|
||||
def test_dangerous_command_approved_in_yolo_mode(self, monkeypatch):
|
||||
"""With HERMES_YOLO_MODE, dangerous (non-hardline) commands are auto-approved."""
|
||||
monkeypatch.setenv("HERMES_YOLO_MODE", "1")
|
||||
"""With HERMES_YOLO_MODE, dangerous commands are auto-approved."""
|
||||
monkeypatch.setattr(approval_module, "_YOLO_MODE_FROZEN", True)
|
||||
monkeypatch.setenv("HERMES_INTERACTIVE", "1")
|
||||
monkeypatch.setenv("HERMES_SESSION_KEY", "test-session")
|
||||
|
||||
@@ -68,8 +68,8 @@ class TestYoloMode:
|
||||
assert result["message"] is None
|
||||
|
||||
def test_yolo_mode_works_for_all_patterns(self, monkeypatch):
|
||||
"""Yolo mode bypasses dangerous patterns (except the hardline floor)."""
|
||||
monkeypatch.setenv("HERMES_YOLO_MODE", "1")
|
||||
"""Yolo mode bypasses all dangerous patterns, not just some."""
|
||||
monkeypatch.setattr(approval_module, "_YOLO_MODE_FROZEN", True)
|
||||
monkeypatch.setenv("HERMES_INTERACTIVE", "1")
|
||||
|
||||
# Dangerous but recoverable — yolo should bypass.
|
||||
@@ -90,7 +90,7 @@ class TestYoloMode:
|
||||
|
||||
def test_combined_guard_bypasses_yolo_mode(self, monkeypatch):
|
||||
"""The new combined guard should preserve yolo bypass semantics."""
|
||||
monkeypatch.setenv("HERMES_YOLO_MODE", "1")
|
||||
monkeypatch.setattr(approval_module, "_YOLO_MODE_FROZEN", True)
|
||||
monkeypatch.setenv("HERMES_INTERACTIVE", "1")
|
||||
|
||||
called = {"value": False}
|
||||
|
||||
Reference in New Issue
Block a user