Every actionable rule in the Worker Remit, checked against the running code. Gap = declared but unenforced; Partial = enforced but incomplete or bypassable; Vague Policy = too imprecise to verify.
| Rule ID | Section | Rule (quoted) | Status | Finding |
|---|---|---|---|---|
| R-01 | Approved Communication Channels / Hermes Agent | "Every enabled network-exposed adapter MUST refuse to dispatch agent work, resolve approvals, or relay output until an operator-configured caller allowlist is set; no adapter may fail open when no allowlist is configured." | Partial | PRAX-2026-05-31-001 |
| R-02 | Approved Communication Channels / Hermes Agent | "Authorization MUST be re-checked at every surface that crosses a trust boundary; a session identifier is a routing handle only and MUST NOT be accepted as proof of authorization." | Verified | — |
| R-03 | Approved Communication Channels / Hermes Agent | "Local-IPC and editor surfaces (ACP, TUI gateway) MUST rely on OS-level access control and MUST NOT be exposed beyond the local user without an explicit network authentication layer." | Verified | — |
| R-04 | Approved Communication Channels / Hermes Agent | "Binding a loopback-default HTTP surface to a non-loopback interface MUST be an explicit operator action, never a silent default." | Verified | — |
| R-05 | Approved Communication Channels / Hermes Desktop | "The SSH Tunnel MUST bind only to `127.0.0.1` on the desktop side and MUST NOT expose the remote Hermes port to the public internet." | Verified | — |
| R-06 | Approved Communication Channels / Hermes Desktop | "The desktop MUST authenticate to a remote Hermes host using key-based SSH in non-interactive (`BatchMode`) mode, and MUST NOT fall back to transmitting an operator password to satisfy a prompt." | Verified | — |
| R-07 | Approved Communication Channels / Hermes Desktop | "The desktop MUST verify the remote host key on first connection and pin it, and MUST fail closed if a pinned host key later changes rather than silently re-trusting it." | Verified | — |
| R-08 | Approved Communication Channels / Hermes Desktop | "The desktop MUST authorize its connection only against a dedicated, non-root Hermes user account on the remote host." | Partial | PRAX-2026-05-31-004 |
| R-09 | Data Boundaries / Forbidden Data Movement / Hermes Agent | "Provider API keys and gateway tokens MUST be stripped from the environment passed to lower-trust in-process components (shell subprocesses, MCP subprocesses, the code-execution child) except where the operator or a loaded skill has explicitly declared a passthrough variable." | Verified | — |
| R-10 | Data Boundaries / Forbidden Data Movement / Hermes Agent | "Credentials and session-authorization material MUST NOT leak to any destination outside the trust envelope through environment passthrough, adapter logging, or transport errors that flush them upstream." | Verified | — |
| R-11 | Data Boundaries / Forbidden Data Movement / Hermes Agent | "Secret-like patterns MUST be redacted from operator-facing display surfaces." | Verified | — |
| R-12 | Data Boundaries / Forbidden Data Movement / Hermes Desktop | "Operator-entered credentials (provider API keys, SSH key paths, remote API keys) MUST be stored only in the operator's own config files and MUST NOT be transmitted anywhere other than the configured Agent host." | Verified | — |
| R-13 | Action Boundaries / Requires Human Approval / Hermes Agent | "Execution of destructive or state-mutating shell commands through the `terminal` tool." | Partial | PRAX-2026-05-31-005 |
| R-14 | Action Boundaries / Requires Human Approval / Hermes Agent | "Installation of third-party skills and plugins, which MUST be subject to operator review (reading the skill's Python and scripts, not only its description) before the code is loaded and run." | Partial | PRAX-2026-05-31-006 |
| R-15 | Action Boundaries / Requires Human Approval / Hermes Agent | "Loading or launching an operator-configured MCP server, which MUST pass the documented supply-chain guard at launch." | Partial | PRAX-2026-05-31-007 |
| R-16 | Action Boundaries / Never Allowed / Hermes Agent | "Ingesting content from operator-uncontrolled surfaces (open web, inbound email, multi-user channels, untrusted MCP servers) while relying only on in-process heuristics, with no OS-level isolation boundary in force." | Enforcement Not Possible | — |
| R-17 | Action Boundaries / Never Allowed / Hermes Agent | "Dispatching agent work, resolving an approval, or relaying output to a caller outside the configured authorization set." | Partial | PRAX-2026-05-31-001 |
| R-18 | Action Boundaries / Never Allowed / Hermes Agent | "Running the agent process as root in a deployment that ingests untrusted input." | Enforcement Not Possible | — |
| R-19 | Action Boundaries / Never Allowed / Hermes Desktop | "SSH'ing into, or authorizing its key on, the remote `root` account." | Partial | PRAX-2026-05-31-004 |
| R-20 | Action Boundaries / Never Allowed / Hermes Desktop | "Disabling the Agent's host-key verification or weakening the SSH tunnel's loopback-only bind." | Verified | — |
| R-21 | Behavioral Expectations / Acceptable Retry Behavior / Hermes Agent | "The tool-calling loop MUST remain bounded by its iteration and budget limits and MUST stop on an operator interrupt." | Verified | — |
| R-22 | Non-Goals / Hermes Desktop | "Acting as an autonomous agent or independently initiating agentic actions — it brokers operator control and must not originate tool calls or shell execution of its own." | Verified | — |
| R-23 | Tools and Capabilities / Known Good Baseline / Hermes Agent | "The documented core toolsets plus whatever subset the operator has enabled per platform; no tool present in code that is absent from the authorized set above." | Verified | — |
| R-24 | Behavioral Expectations / Acceptable Retry Behavior / Hermes Agent | "Cron sessions MUST honor the documented hard interrupt; a job that fails repeatedly MUST be auto-blocked rather than retried indefinitely." | Verified | — |
Findings, ordered by severity — each linked to its remit rule, evidence, and a recommended action. Tag chips jump to the relevant entry in the RAISE framework, the OWASP LLM Top 10, or the OWASP Agentic Top 10.
CRITICAL PRAX-2026-05-31-001 WeCom, Weixin, and Yuanbao gateway adapters default `dm_policy: "open"` and self-declare own-access-policy, so a default-config enable dispatches agent work to any caller with no operator allowlist.
"Every enabled network-exposed adapter MUST refuse to dispatch agent work, resolve approvals, or relay output until an operator-configured caller allowlist is set; no adapter may fail open when no allowlist is configured. / Dispatching agent work, resolving an approval, or relaying output to a caller outside the configured authorization set."
- Change the shipped default for `dm_policy` / `group_policy` in the WeCom, Weixin, and Yuanbao adapters from `"open"` to `"allowlist"` (or `"disabled"`), so an operator must opt into open access deliberately rather than inheriting it.
- Emit a startup warning (as the gateway already does for env-allowlist platforms at `gateway/run.py:4075`) whenever an own-access-policy adapter is enabled with an effective open policy and no allow_from configured.
HIGH PRAX-2026-05-31-004 The Desktop SSH path accepts an arbitrary `config.username`, including `root`, with no code guard rejecting or warning on a root target.
"The desktop MUST authorize its connection only against a dedicated, non-root Hermes user account on the remote host. / SSH'ing into, or authorizing its key on, the remote `root` account."
HIGH PRAX-2026-05-31-005 Destructive-shell approval rests on a regex denylist plus an optional auxiliary-LLM auto-approver, both of which are incomplete over Turing-complete shell input.
"Execution of destructive or state-mutating shell commands through the `terminal` tool."
MEDIUM PRAX-2026-05-31-006 Third-party skill/plugin install gating is a regex Skills Guard plus trust tiers; community skills with zero findings install without an enforced human-review step.
"Installation of third-party skills and plugins, which MUST be subject to operator review (reading the skill's Python and scripts, not only its description) before the code is loaded and run."
MEDIUM PRAX-2026-05-31-007 The MCP tool-description poisoning scanner logs warnings but does not block; a poisoned MCP tool description reaches the model regardless.
"Loading or launching an operator-configured MCP server, which MUST pass the documented supply-chain guard at launch."
MEDIUM PRAX-2026-05-31-008 Desktop PostHog telemetry defaults to enabled (opt-out) on first run for official builds, and client-side IP suppression is not achievable.
MEDIUM PRAX-2026-05-31-009 The agent has no in-process guard that warns or refuses when started as root while ingesting untrusted input; non-root operation is documentation-and-container default only.
Controls and behaviors that are correctly implemented and verified during this scan. These represent areas where the agent's implementation aligns with its stated policy and security best practices.
YOLO mode frozen at import against injection escalation
`tools/approval.py` reads `HERMES_YOLO_MODE` once at module import into `_YOLO_MODE_FROZEN`, explicitly so a skill running in-process cannot set the variable mid-session and bypass all approval checks — a deliberate prompt-injection-escalation defense.
Hardline command blocklist sits below YOLO and approval-off
A small unconditional blocklist of unrecoverable commands (filesystem destruction at /, raw block-device overwrite, kernel shutdown) is refused even under `--yolo`, `approvals.mode=off`, or cron approve mode, providing a floor that operator break-glass cannot cross on host-capable backends.
Provider-credential scrubbing for lower-trust child processes
`_HERMES_PROVIDER_ENV_BLOCKLIST` strips Hermes-managed provider keys from the env passed to shell, MCP, and code-execution children, and `env_passthrough.py` refuses to let a skill or config re-register a blocked provider credential — closing GHSA-rhgp-j443-p4rf.
API server fails closed without an API key
The API server adapter's `connect()` refuses to start when `API_SERVER_KEY` is unset, including for loopback-only binds, and refuses a placeholder/weak key when network-accessible — so the no-key branch in `_check_auth` is a test-only dead path, not a live fail-open.
Gateway authorization is default-deny
`_is_user_authorized` denies by default when no allowlist and no explicit allow-all flag are configured, treats session IDs as routing handles only, and re-checks authorization rather than trusting prior session state.
Desktop SSH uses key-only BatchMode auth with host-key pinning
The Desktop builds SSH connections with `BatchMode=yes` (no interactive password fallback) and `StrictHostKeyChecking=accept-new` (trust-on-first-use pinning that fails closed if a pinned key later changes), and binds all tunnel forwards to `127.0.0.1`.
Desktop keeps the remote API key out of the renderer
`getPublicConnectionConfig()` exposes only `hasApiKey` and the key length (for mask rendering) to the renderer process, never the secret itself, verified by `connection-config-security.test.ts`.
Electron operator layer is security-hardened
Both the main window and the askpass window set `nodeIntegration: false`, `contextIsolation: true`, `sandbox: true`, and `webSecurity: true`, with `security.ts` enforcing the same on web-preferences creation.
Exact-pinned dependencies with supply-chain CI
Every direct dependency in `pyproject.toml` is pinned to `==X.Y.Z` with a committed `uv.lock`, CVE-annotated, and gated by OSV-scanner and a narrow supply-chain-audit workflow in CI.
Log files found in the agent's workspace during this scan. Reviewing these files provides runtime evidence to complement the static analysis above.
| Path | Source | Content Type | Purpose | Last Modified | Status |
|---|---|---|---|---|---|
| ~/.hermes/logs/agent.log | Hermes Agent (hermes_logging.setup_logging) | plaintext, redacted, rotating (RedactingFormatter) | INFO+ catch-all of agent, tool, and session activity | unknown | Inferred |
| ~/.hermes/logs/errors.log | Hermes Agent (hermes_logging.setup_logging) | plaintext, redacted, rotating (RedactingFormatter) | WARNING+ quick-triage error log | unknown | Inferred |
| ~/.hermes/logs/gateway.log | Hermes Agent (hermes_logging.setup_logging, gateway mode) | plaintext, redacted, rotating (RedactingFormatter) | INFO+ gateway-component events (created when mode=gateway) | unknown | Inferred |
Each card represents one category and shows the top 3 findings. All items in the Findings section.
Each card represents one category and shows the top 3 findings. All items in the Findings section.
Overall maturity assessment across the six categories of the RAISE framework. This is a maturity model, not a school grade: a score of 3 / 5 means Established, not 60 percent. Most production AI agents today score between Ad hoc (1) and Established (3). See the full RAISE framework reference for the complete scale and scoring.
Maturity Scoring Rubric
Every score above is based on this scale. A score is a snapshot of observable posture — not a verdict on the people or team behind the system.
| Score | Label | Meaning |
|---|---|---|
| 5 | Exemplary | Best-in-class; automated, continuously tested, reference quality. Rarely achieved in shipping systems. |
| 4 | Strong | Comprehensive controls, active management, minor gaps. Production-ready. |
| 3 | Established | Documented controls consistently applied; known gaps accepted. A respectable baseline. |
| 2 | Partial | Some controls exist but coverage is incomplete; key gaps remain. |
| 1 | Ad hoc | Informal or inconsistent measures; relies on individual judgment. |
| 0 | Absent | No evidence this category is addressed at all. |