Hermes Agent Security Sprint: Root-Wipe Bypass Patched, Restart Loop Breaker, and Cross-Session State Leaks Fixed

Hermes Agent Security Sprint: Root-Wipe Bypass Patched, Restart Loop Breaker, and Cross-Session State Leaks Fixed
📑 Table of Contents

On July 1, 2026, Nous Research’s Teknium merged a batch of security and reliability fixes into Hermes Agent’s main branch — a focused sprint addressing a root-filesystem bypass, a cron restart loop, cross-session state corruption, and four CVE patches in core dependencies.

The rm -rf / Shell-Collapse Bypass

The headline fix closes an edge case in the root-filesystem hardline — Hermes Agent’s unconditional blocklist that prevents terminal commands from wiping the filesystem, regardless of yolo mode or approval settings. The original pattern caught rm -rf / and rm -rf /*, but missed shell-collapse variants: rm -rf //, /./, /../, and //* all resolve to / in the shell but slipped past the regex.

The fix, co-authored by kernel-t1, broadens the hardline from matching the literal "/" token to "/[/.]*/\\*" — any root-anchored path whose components collapse back to / with an optional trailing glob. A trailing real segment like /home or /tmp still passes through to softer dangerous-pattern rules. It only catches paths that resolve to the root itself.

This means: even under --yolo, approvals.mode=off, or cron approve mode, no shell-collapse spelling of a root wipe can reach the terminal. The one unconditional floor is now harder to slip under.

Cron Restart-Loop Circuit Breaker

Issue #30719 tracked a long-standing problem: if a cron job or gateway session triggered a SIGTERM, the auto-resume mechanism would re-run it on boot, potentially creating an infinite restart loop. Two previous defenses (lifecycle command filtering on hermes gateway stop|restart, and a cron-creation filter) had already landed, but gaps remained.

The new fix adds gateway/restart_loop_guard.py: a rolling-window counter (default: 3 boots in 60 seconds) that, once tripped, skips auto-resume for that boot. The gateway still comes up and serves real inbound messages — it just stops replaying the session that keeps killing it. Additionally, the lifecycle guard was moved to a shared chokepoint (cron/lifecycle_guard.py) so model-tool-created cron jobs are filtered at creation time, not just at execution.

Credit flows through PR #33395 (@kshitijk4poor) from original work by @SimoKiihamaki in #30728.

Cross-Session Compressor State Leaks

A subtle bug from benbarclay: on_session_end() was only clearing _previous_summary, but on_session_reset() clears 14+ per-session variables. When a session ended (cron exit, gateway expiry, session-id rotation) and the compressor instance was reused, surviving stale state caused:

  • _ineffective_compression_count surviving → next session skips compression prematurely
  • _summary_failure_cooldown_until surviving → blocks summary generation for an unrelated transient error
  • _last_compress_aborted surviving → callers think compression is still aborted

The fix clears all per-session state in on_session_end(), matching on_session_reset(). Six targeted tests now guard the leak vectors.

CVE-Driven Dependency Bumps

The aiohttp dependency was bumped from 3.14.0 to 3.14.1, covering CVE-2026-34993 (CookieJar.load RCE via deserialization) and CVE-2026-47265 (per-request cookie leak on cross-origin redirect). Critically, the fix also enforces the patched version on lazy messaging paths (Discord, Matrix, Teams) that previously got aiohttp transitively without the explicit pin, plus CVE-2026-34450 / CVE-2026-34452 in anthropic bumped from 0.86.0 to 0.87.0. A new test guard in test_packaging_metadata.py prevents pyproject.toml and lazy_deps.py pins from silently diverging again.


The sprint represents a security-focused rhythm typical of Hermes Agent’s development cycle: major releases push capability, then focused hardening tightens the seams. All fixes are on main now — run hermes update to pull them in.