Hermes Agent

Hermes tightens three exits for externally applied secrets

Three Hermes Agent security changes replace credential-name guessing with per-profile provenance: child processes lose externally applied secrets, terminal and memory output masks their exact values, and provider-bound tool results receive a final exact-value pass. One of the three inspected patches remained open at capture time.

← Back to homeOriginal source ↗

NousResearch/hermes-agent PR #77185 is the inspected primary source: “fix(security): wire applied-secrets snapshot into provider-egress sanitizers.” The two related records below were inspected as supporting context, not treated as independent confirmation.

The facts

- NousResearch/hermes-agent PR #77185 was created 2026-08-03T00:32:01Z and was closed at inspection; its title is “fix(security): wire applied-secrets snapshot into provider-egress sanitizers.” - NousResearch/hermes-agent PR #77181 was created 2026-08-03T00:21:04Z and was closed at inspection; its title is “fix(security): scrub applied-secrets snapshot from child-process envs.” - NousResearch/hermes-agent PR #77198 was created 2026-08-03T00:53:01Z and was open at inspection; its title is “fix(secrets): exact-value applied-secret redaction on the provider-egress path.” - The repository reported 224322 stars, 26842 open issues, default branch main, and last push 2026-08-03T00:20:48Z. - The latest tagged-release baseline checked was v2026.7.30 published 2026-07-30T23:45:37Z.

What changed

NousResearch/hermes-agent PR #77185 reports: What changed and why Secrets applied from external secret sources (Bitwarden / 1Password / command — hermes_cli.env_loader.get_secret_source_values) can arrive under **arbitrary names** (DATABASE_URL, FOO, any 1Password item key). Shape-based redaction (vendor prefixes, URL userinfo, auth headers) cannot catch those opaque values, so they were still leaking verbatim on several provider-egress surfaces. This PR wires the per-home applied-secrets snapshot into the remaining unclosed egress sanitizers: **agent/redact.py** — new exact-value masking primitive, namespaced with an egress prefix to avoid colliding with other in-flight exact-value maskers: mask_egress_secret_values(text, extra_values=None) — replaces exact occurrences of known credential values with ***; scans os.environ for credential-suffixed names (_API_KEY / _TOKEN / _SECRET / _KEY / _PASSWORD, values len ≥ 6) and merges

NousResearch/hermes-agent PR #77181 reports: What changed and why The child-process environment scrub was a **name-shape heuristic**. When Hermes spawns a child process (a terminal command via build_subprocess_env, or a non-terminal surface — browser worker, ACP executor, computer-use driver — via hermes_subprocess_env), secrets were stripped by matching exact names plus credential-shaped suffixes (_API_KEY / _SECRET / _KEY / _TOKEN) against a static blocklist. That left a hole: values applied from **external secret sources** (Bitwarden Secrets Manager, 1Password, a secret-source command) under **non-credential-shaped names** — DATABASE_URL, FOO, arbitrary 1Password item keys — matched no predicate and were inherited verbatim by every spawned child. The scrub guessed by name shape instead of consulting the authoritative record of what actually came from an

NousResearch/hermes-agent PR #77198 reports: What changed and why Closes **#77162** and **#77165**. Values applied from external secret sources (Bitwarden/1Password/command) under **any** env name — including non-credential-shaped names like DATABASE_URL, FOO, arbitrary 1Password item keys — that a tool echoes into its result (config/env artifact read, printenv, backend error quoting a key) passed all shape-based redaction passes and were transmitted **verbatim to the model provider** in the next API call. Emission-side channels (status lines #77012, logs #77020) already masked exact values; the **egress path** did not. The fix: one exact-value pass, wired into all three egress surfaces New agent.redact.redact_known_secret_values masks every value in the per-home **applied-secrets snapshot** (hermes_cli.env_loader.get_secret_source_values / _SECRET_SOURCE_VALUES_BY_HOME) plus credential-suffixed env values. It is: **Min-length guarded** (8 chars)

Why it matters

The important change is the authority model. A value is treated as secret because the active profile says it came from Bitwarden, 1Password or a secret-source command—not because its variable name happens to end in TOKEN. The operational test is whether persisted state, execution authority and visible user outcome describe the same event. Broad retries, hidden suppression or permission expansion can hide the symptom while making the boundary less trustworthy.

Current

The primary record was closed when captured on 2026-08-03. The release baseline was v2026.7.30 published 2026-07-30T23:45:37Z. Current repository metadata, pull requests, issues, release records, Google News discovery, Hacker News discovery, Lobsters, Metamesh and the rendered ClawCharts HTML row were checked. ClawCharts selected the subject; it did not prove the claim.

Evidence

The primary URL is https://github.com/NousResearch/hermes-agent/pull/77185. Supporting records are https://github.com/NousResearch/hermes-agent/pull/77181 and https://github.com/NousResearch/hermes-agent/pull/77198. Their source bodies, timestamps and states were captured in the daily evidence bundle. Test counts, reproductions and deployment observations remain attributed to their authors unless explicitly identified as independently rerun.

Source boundary

Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Issue closure would not by itself prove a deployed fix. Search residue, package mirrors and historically published source spines were excluded.

Operator take

Verify profile isolation, minimum-length guards, explicit passthrough behavior and all provider-bound content shapes before treating the series as complete. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently after intervention.

Caveat

Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.

Source inspected; source state, environment and release boundary remain explicit.