Skip to content

feat(security): add tirith pre-exec command scanning#1256

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-720acdad
Mar 14, 2026
Merged

feat(security): add tirith pre-exec command scanning#1256
teknium1 merged 2 commits into
mainfrom
hermes/hermes-720acdad

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

  • salvage the substantive work from feat(security): add tirith pre-exec command scanning #904 onto current main, preserving the contributor-authored commit
  • integrate tirith pre-exec scanning without regressing current approval UX or yolo semantics
  • keep gateway replay approval in sync by carrying pattern_keys through approval + replay

Attribution

This PR salvages the substantive contributor work from #904 by @sheeki03.

  • Original contributor-authored commit preserved via cherry-pick: 375ce8a
  • Follow-up compatibility fix on top: 6f1889b

Main-current fixes on top of the cherry-pick

  • preserve HERMES_YOLO_MODE bypass in the combined guard
  • preserve existing non-interactive auto-allow behavior without invoking external tirith scanning
  • preserve long-command view full approval flow while still hiding [a]lways for tirith warnings
  • restore current gateway/run.py and reapply only the intended tirith startup + pattern_keys replay changes

Test plan

  • python -m pytest tests/tools/test_tirith_security.py tests/tools/test_command_guards.py tests/tools/test_approval.py tests/tools/test_yolo_mode.py tests/tools/test_terminal_tool_requirements.py -n0 -q
  • python -m pytest tests/ -n0 -q

Notes

Original PR: #904

sheeki03 and others added 2 commits March 14, 2026 00:11
Integrate tirith as a pre-execution security scanner that detects
homograph URLs, pipe-to-interpreter patterns, terminal injection,
zero-width Unicode, and environment variable manipulation — threats
the existing 50-pattern dangerous command detector doesn't cover.

Architecture: gather-then-decide — both tirith and the dangerous
command detector run before any approval prompt, preventing gateway
force=True replay from bypassing one check when only the other was
shown to the user.

New files:
- tools/tirith_security.py: subprocess wrapper with auto-installer,
  mandatory cosign provenance verification, non-blocking background
  download, disk-persistent failure markers with retryable-cause
  tracking (cosign_missing auto-clears when cosign appears on PATH)
- tests/tools/test_tirith_security.py: 62 tests covering exit code
  mapping, fail_open, cosign verification, background install,
  HERMES_HOME isolation, and failure recovery
- tests/tools/test_command_guards.py: 21 integration tests for the
  combined guard orchestration

Modified files:
- tools/approval.py: add check_all_command_guards() orchestrator,
  add allow_permanent parameter to prompt_dangerous_approval()
- tools/terminal_tool.py: replace _check_dangerous_command with
  consolidated check_all_command_guards
- cli.py: update _approval_callback for allow_permanent kwarg,
  call ensure_installed() at startup
- gateway/run.py: iterate pattern_keys list on replay approval,
  call ensure_installed() at startup
- hermes_cli/config.py: add security config defaults, split
  commented sections for independent fallback
- cli-config.yaml.example: document tirith security config
Restore gateway/run.py to current main behavior while keeping tirith startup
and pattern_keys replay, preserve yolo and non-interactive bypass semantics in
the combined guard, and add regression tests for yolo and view-full flows.
@teknium1 teknium1 merged commit 1869e88 into main Mar 14, 2026
1 check passed
sheeki03 added a commit to sheeki03/nanobot that referenced this pull request Mar 23, 2026
Add Tirith security scanning to the exec tool, detecting homograph
URLs, pipe-to-shell patterns, terminal injection, typosquatted
packages, and insecure transport before command execution.

- Create tirith_security.py: scanner with auto-install from GitHub
  releases (SHA-256 verified), platform-aware shell mode (posix/cmd)
- Add _tirith_guard() to ExecTool after _guard_command() regex checks
- Add TirithConfig to ExecToolConfig in config/schema.py
- Extend tests/test_exec_security.py with tirith gate + scanner tests

Tirith is already integrated in Hermes Agent
(NousResearch/hermes-agent#1256) and EurekaClaw
(EurekaClaw/EurekaClaw#1). Fail-open by default.
sheeki03 added a commit to sheeki03/picoclaw that referenced this pull request Mar 23, 2026
Add Tirith security scanning to the exec tool, detecting homograph
URLs, pipe-to-shell patterns, terminal injection, typosquatted
packages, and insecure transport before command execution.

- Create pkg/tools/tirith.go: scanner with proper *exec.ExitError
  handling, cross-platform auto-install (SHA-256 verified), and
  synchronized first-use installation
- Hook tirithGuard() into shell.go after guardCommand() regex checks
- Add TirithConfig to ExecConfig in config.go + defaults.go
- Cron jobs share the same ExecTool.Execute() path, already covered

Tirith is already integrated in Hermes Agent
(NousResearch/hermes-agent#1256) and EurekaClaw
(EurekaClaw/EurekaClaw#1). Fail-open by default.
sheeki03 added a commit to sheeki03/zeroclaw that referenced this pull request Mar 23, 2026
Add Tirith security scanning to both shell tool execution and cron
shell jobs, detecting homograph URLs, pipe-to-shell patterns,
terminal injection, and more before command execution.

- Create src/security/tirith.rs: shared async guard with ShellKind
  enum (Native for shell tool, Posix for cron scheduler)
- Hook tirith::guard() into shell.rs after security policy checks
- Hook tirith::guard() into scheduler.rs after command validation
  (cron uses sh -c even on Windows, so ShellKind::Posix)
- Fail-open by default, configurable

Tirith is already integrated in Hermes Agent
(NousResearch/hermes-agent#1256) and EurekaClaw
(EurekaClaw/EurekaClaw#1).
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…720acdad

feat(security): add tirith pre-exec command scanning
sheeki03 added a commit to sheeki03/ironclaw that referenced this pull request May 5, 2026
…roval paths

Runs the external Tirith terminal-security CLI (https://github.com/sheeki03/tirith)
as a pre-exec subprocess on every shell tool call that passes through the
interactive approval paths:

- v1 dispatcher initial path (src/agent/dispatcher.rs)
- v1 thread_ops deferred-replay path (src/agent/thread_ops.rs)
- v2 effect bridge (src/bridge/effect_adapter.rs::enforce_tool_permission)

Block / Warn / WarnAck verdicts (exit 1 / 2 / 3) all surface as approval
prompts with allow_always = false so a finding cannot be permanently
allow-listed. Only Allow (exit 0) skips the prompt.

Fail-closed (safety.tirith_fail_open = false) is a HARD denial, never an
approval — operational failures (missing binary, timeout, spawn error,
unknown exit) map to EngineError::LeaseDenied / PreflightOutcome::Rejected
/ a synthesized deferred-tool error. Encoded via the three-way
TirithPreflightDecision::{Allow, Approval, Deny} enum.

The reason text flows from a new EngineError::GatePaused.reason field
(boxed under clippy's result_large_err threshold) through
ThreadOutcome::GatePaused.reason into PendingGate.description and
EventKind::ApprovalRequested.description. Reasons are sanitized at the
helper level (C0/C1/bidi/zero-width strip + newline collapse) before
leaving tirith_guard.rs so terminal-control payloads tirith was scanning
for cannot reach TUI/SSE/channel surfaces unchanged.

Default-on with fail-open: machines without tirith on PATH see no
behavior change. Tests cover all verdict mappings, alias-canonical
resume safety, approval_already_granted re-scan skip, fail-closed
denial paths, and the sanitizer regression cases.

Coverage in this PR: interactive shell approval paths only. Autonomous
worker / scheduler / routine engine paths and inline ShellTool guard
are explicit follow-ups.

Configuration: safety.tirith_enabled (default true), safety.tirith_bin
(default "tirith"), safety.tirith_timeout_ms (default 5000),
safety.tirith_fail_open (default true). Each setting honors a
SAFETY_TIRITH_* env var with DB-first precedence.

Prior art:
- HKUDS/nanobot#2414 (helper module + ExecTool guard)
- NousResearch/hermes-agent#1256 (helper module + terminal_tool guard)
- NousResearch/hermes-agent#3428 (block AND warn approvable)
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…720acdad

feat(security): add tirith pre-exec command scanning
olympus-terminal pushed a commit to olympus-terminal/hermes-agent that referenced this pull request May 16, 2026
…720acdad

feat(security): add tirith pre-exec command scanning
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…720acdad

feat(security): add tirith pre-exec command scanning
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.

2 participants