Back to Blog & Resources
CVE Analysis · AI Agent · GitSpawn

Hermes Agent CVE Chain: GitSpawn RCE, Session Authorization and SSRF

A source-grounded analysis of four Hermes Agent CVEs: the verified GitSpawn command-execution path, adjacent session and URL-fetch boundaries, detection evidence and hardened deployment controls.

Riad DAHMANIK8SEC Security ResearchReviewed September 16, 2026
Illustrated Hermes Agent remote code execution security artwork supplied for this article
Hermes Agent security artwork supplied by the publisher. Technical conclusions are based on the official CVE records and upstream patch.

Evidence standard: four records, one verified GitSpawn RCE

The four published records concern the same project, but the public evidence does not establish one universal exploit chain. CVE-2026-71963 has the strongest record: a CNA description, an upstream pull request, a merged patch and regression tests for the automatic Git call sites. The authorization bypass, SSRF and denial-of-service records identify additional application boundaries. Composition depends on deployed versions, exposed interfaces, network placement, session design and runtime identity.

Keep four evidence layers separate: model output, application proposal, policy admission and observed effect. A transcript proves what the model returned. A policy event proves allow or deny. A child-process or target-side event is needed to prove command execution, network access or modification.

Confirmed
CVE-2026-71963 affects Hermes Agent 0.18.2–0.21.0; the record identifies upstream commit f6234d0 as the fix.
Published
CVE-2026-85105 describes a session authorization bypass in 0.18.0.
Conditional
CVE-2026-85106 becomes an internal-access path only when destination and response controls permit it.
Unproven
The records do not show that all four issues coexist or compose in every installation.

The four CVEs and the boundary each one crosses

Published scope and interpretation limits
CVEPublished behaviorAffected recordScoreLimit
CVE-2026-71963
CWE-78
Repository-local Git configuration can trigger command execution during automatic workspace inspection.0.18.2–0.21.0; fixed in commit f6234d0.8.8 v3.1
8.6 v4.0
Establishes the RCE mechanism, not compromise of every deployment.
CVE-2026-85105
CWE-639 / CWE-285
A controlled session_id reaches _sess_nowait and bypasses authorization.0.18.0 is explicitly listed.7.3 v3.1
6.9 v4.0
No complete affected range or fix is published in the CNA record.
CVE-2026-85106
CWE-918
fetchLinkTitle performs a server-side request to a controlled URL.0.18.0 is explicitly listed.6.3 v3.1
5.3 v4.0
The v3.1 vector requires low privileges; internal impact depends on egress and returned data.
CVE-2026-84287
CWE-404
The session chat API can be driven into denial of service.0.18.0 is explicitly listed.4.3 v3.1
5.3 v4.0
The public record does not identify the exact vulnerable function.
Investigation rule: record installed build, interface exposure and acting identity before assigning combined-chain impact. CVE adjacency creates a hypothesis; correlated effects prove a path.

GitSpawn anatomy: when inspection becomes execution

Hermes gathered coding context by running the system Git binary in the selected session directory. The upstream patch says workspace snapshots, project-tree discovery, diff context, goal fingerprints and worktree setup could run before a prompt, visible tool approval or trust gate. Git configuration can select executable behavior. The official Git documentation defines core.fsmonitor as a hook pathname when its value is not Boolean.

1. Repository deliveryA copied workspace retains repository-local .git metadata.
2. Automatic inspectionThe agent invokes Git to collect context.
3. Execution sinkLocal configuration influences a hook or diff executable.
4. Process authorityThe child inherits the agent user's accessible environment, files and network.

The delivery condition matters. The upstream fix notes that ordinary git clone does not transfer another repository's local .git/config. Directory archives, synchronized folders and removable-media workspaces can retain it. The fix therefore hardens every automatic Git path, rather than relying on users to recognize one malicious key.

The patched design supplies a controlled noninteractive Git environment that neutralizes repository-selected fsmonitor, hooks, pager, editor and credential helpers while ignoring global and system configuration. Diff-rendering calls also receive --no-ext-diff and --no-textconv; attacker-named diff drivers cannot be exhaustively disabled by guessing configuration keys.

textdef inspect_workspace(repo):
    env = inert_git_configuration()
    args = harden_diff_arguments(["status", "--porcelain"])
    return run(["git", *args], cwd=repo, env=env,
               stdin=DEVNULL, timeout=bounded_seconds)

# Required property: automatic inspection cannot select
# repository-defined executables or credential helpers.

Containerization reduces impact only when the agent lacks host credential mounts, broad workspaces, runtime sockets and unrestricted egress. The decisive question is which identity and resources the Git child process actually receives.

Session authorization, URL fetch and availability

Session objects need subject and tenant authorization

CVE-2026-85105 maps to CWE-639 and CWE-285. A controlled session identifier reaches the session lookup path. The server should authenticate the caller, load the requested session, compare its owner and tenant, then authorize the requested read, update, delete or delegation function. Possession of an identifier does not confer authority.

SSRF is destination authorization

CVE-2026-85106 maps to CWE-918. A link-title feature fetches a caller-selected URL. Exposure depends on parsing, DNS results, redirects, scheme restrictions, egress policy and response handling. Validate every resolved destination after redirects, block prohibited loopback, link-local and private ranges, limit response size and isolate the fetcher from privileged internal services.

Availability claims require observed resource effects

CVE-2026-84287 identifies the session chat interface but does not disclose the exact failing function. Avoid inventing a root cause. In an authorized environment, measure requester identity, endpoint, concurrency, resource use, health failures and recovery. Apply request-size limits, per-identity concurrency budgets, timeouts and workload isolation according to the observed bottleneck.

Interactive mindmap: inputs, authority and evidence

Expand each branch to follow its trust boundary and the evidence required to confirm it. The map keeps the records separate so reviewers can see where a proposed composition still lacks proof.

Hermes Agent attack surface
Repository metadata

Copied .git metadata → automatic Git probe → repository-selected executable behavior → user-process authority. Confirm with repository provenance, version, process ancestry and patch state.

Session object

Request → authenticated subject → session lookup → tenant/owner/function decision. Confirm with request, subject, object owner, policy outcome and returned object.

URL fetch

Controlled URL → parser → DNS/redirect resolution → egress decision → destination. Confirm every resolved address, network decision, requester and response handling.

Chat availability

Request stream → session handler → bounded resources → health and recovery. Confirm the resource and service effect without guessing the undisclosed implementation defect.

A defensible combined path names every required edge: entry point, accepted input, authorization result, invoked component, executing identity and target-side effect. If session access does not reach repository selection, or the fetcher cannot reach sensitive destinations, that proposed edge remains unproven.

Detection and forensic triage

Cross-plane evidence
SignalSourceSupportsDoes not prove
Unexpected child below GitEndpoint process telemetryInspection started another executable.Which configuration key selected it.
Executable Git keysQuarantined repository metadataA relevant precondition exists.That execution occurred.
Subject differs from session ownerAPI and policy eventsPossible ownership failure.Impact without returned or changed data.
Fetcher reaches restricted rangesDNS, proxy and firewallSSRF attempt or policy failure.Data disclosure unless the response path is observed.
Worker exhaustionGateway and runtime metricsAvailability effect and recovery time.The undisclosed defect's root cause.
bashset -euo pipefail
events_file="${1:?usage: review-events.sh EVENTS.jsonl}"
jq -c '
  select(
    (.process.parent == "git" and .process.image != "git") or
    (.policy.decision == "deny" and .effect.observed == true) or
    (.network.destination_class | IN("loopback","link-local","private"))
  )
  | {time, request_id, run_id, subject, tenant,
     process, policy, network, effect}
' "$events_file"

This example expects normalized defensive events. Adapt its fields to your telemetry. Preserve request, run and process identifiers while excluding raw API keys, authorization headers and unrestricted prompt content.

Remediation checklist

0 controls verified

If a potentially affected runtime held provider, source-control, registry or cloud credentials, rotate them according to observed exposure and incident policy. A vulnerable version establishes urgency; it does not by itself prove credential theft.

Verification runbook and primary sources

Run ancestry checks against a trusted Hermes source checkout, outside any untrusted workspace. The CVE record identifies a fixing commit but does not name a fixed release. Confirm that the deployed build contains the commit or obtain a vendor release statement before declaring remediation.

bashset -euo pipefail
agent_source="${1:?usage: verify-hermes.sh TRUSTED_HERMES_SOURCE}"
fixed_commit="f6234d00c5d59450adea1d7edd30ad3859375c79"

current_commit="$(git -C "$agent_source" rev-parse HEAD)"
printf 'Hermes source commit: %s\n' "$current_commit"

if git -C "$agent_source" merge-base --is-ancestor "$fixed_commit" HEAD; then
  printf 'GitSpawn fix commit is present.\n'
else
  printf 'GitSpawn fix commit was not found.\n' >&2
  exit 1
fi

Model output is not system action. Here, the strongest action boundary sits below the model: automatic context gathering invokes a trusted system tool whose local configuration can select executable behavior. Secure agent deployments constrain the application, subprocess, identity and network boundaries even when the model never requests a tool.

On this pageEvidence standardFour CVEsGitSpawn anatomyAdjacent boundariesInteractive mindmapDetectionRemediationVerification and sources