CVE-2026-55196 Overview
CVE-2026-55196 is an authentication bypass vulnerability in Hermes WebUI versions before 0.51.409. The flaw exists in passkey registration endpoints when HERMES_WEBUI_PASSKEY=1 is enabled and no credentials have been provisioned. Unauthenticated remote attackers can call POST /api/auth/passkey/register/options and POST /api/auth/passkey/register to claim the first passkey on the instance. Once registered, the attacker holds permanent administrative control over the application. The weakness is categorized as Missing Authentication for Critical Function [CWE-306].
Critical Impact
Remote, unauthenticated attackers can enroll the first passkey on an unprovisioned Hermes WebUI instance and gain persistent administrator access.
Affected Products
- Hermes WebUI versions before 0.51.409
- Deployments with HERMES_WEBUI_PASSKEY=1 enabled
- Instances with no existing credentials configured
Discovery Timeline
- 2026-06-17 - CVE-2026-55196 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2026-55196
Vulnerability Analysis
Hermes WebUI exposes two passkey registration endpoints used during WebAuthn enrollment. In affected releases, these endpoints do not verify a valid session before processing the request when the instance has no credentials yet. An attacker who reaches the application over the network can submit a registration options request followed by a registration completion request to permanently bind an attacker-controlled passkey to the administrative account. Because the first passkey establishes the initial authenticator of record, the attacker achieves persistent control with no prior access.
Root Cause
The registration handlers in api/routes.py lacked an authentication gate for the bootstrap path. The fix introduces _require_passkey_registration_auth, which mandates either a valid WebUI session or the existing local-only first-run onboarding gate before allowing enrollment. Earlier code paths treated the absence of credentials as an implicit permission to enroll a passkey, conflating first-run setup with privileged enrollment over arbitrary network paths.
Attack Vector
Exploitation requires network reachability to the Hermes WebUI HTTP service and the passkey feature flag enabled. The attacker sends a POST to /api/auth/passkey/register/options to obtain the WebAuthn challenge, then submits a forged attestation to /api/auth/passkey/register to complete enrollment. No user interaction on the target side is required.
# Patch from api/routes.py - require auth for passkey enrollment
# ── POST auth helpers
def _require_passkey_registration_auth(handler) -> tuple[bool, str, int]:
"""Require auth, or the existing local-only first-run bootstrap gate.
Registering additional passkeys is an auth-factor enrollment action and
requires a valid WebUI session. The first passkey can still bootstrap a
passkey-only instance, but only through the same local/private-network
onboarding gate used for first password setup.
"""
from api.auth import is_auth_enabled, parse_cookie, verify_session
auth_enabled = is_auth_enabled()
if not auth_enabled:
if _onboarding_gate_allows(handler, auth_enabled):
return True, "", 200
return False, "Authentication required", 401
cookie_val = parse_cookie(handler)
if not cookie_val or not verify_session(cookie_val):
return False, "Authentication required", 401
return True, "", 200
Source: GitHub commit 4d90577. The patch enforces session verification or the local-only onboarding gate before any passkey enrollment proceeds.
Detection Methods for CVE-2026-55196
Indicators of Compromise
- Unexpected POST /api/auth/passkey/register/options requests from external or unfamiliar IP addresses.
- Successful POST /api/auth/passkey/register responses occurring without a prior authenticated session cookie.
- New passkey credential identifiers in the Hermes WebUI credentials store that do not correspond to known administrators.
- Administrative actions originating from sessions established via newly enrolled passkeys shortly after deployment.
Detection Strategies
- Inspect web server and application logs for sequential calls to the two passkey registration endpoints from a single source within a short time window.
- Alert on HTTP 200 responses to /api/auth/passkey/register where no authenticated session cookie was presented in the request.
- Baseline the count of enrolled passkeys per instance and flag additions outside change-control windows.
Monitoring Recommendations
- Forward Hermes WebUI access and audit logs to a centralized log platform for retention and correlation.
- Monitor for first-time access to /api/auth/passkey/* paths on instances where the feature was not intentionally exposed.
- Track configuration drift on the HERMES_WEBUI_PASSKEY environment variable across managed deployments.
How to Mitigate CVE-2026-55196
Immediate Actions Required
- Upgrade Hermes WebUI to version 0.51.409 or later, with v0.51.442 containing the consolidated fix.
- Restrict network access to the Hermes WebUI management interface to trusted administrative networks until patched.
- Audit existing passkey enrollments and revoke any credentials that cannot be attributed to a known administrator.
- Rotate any sessions, API tokens, or downstream secrets accessible through the Hermes WebUI admin role if compromise is suspected.
Patch Information
The vendor addressed the issue in pull requests #4171 and #4267, with the fixed build available in Hermes WebUI v0.51.442. See the VulnCheck advisory for additional vendor guidance.
Workarounds
- Set HERMES_WEBUI_PASSKEY=0 to disable passkey registration endpoints until the upgrade is applied.
- Place Hermes WebUI behind a reverse proxy that enforces authentication or IP allowlisting on /api/auth/passkey/* routes.
- Bind the Hermes WebUI listener to loopback or a private interface and require VPN access for administrative use.
# Disable passkey feature flag and restart the service
export HERMES_WEBUI_PASSKEY=0
systemctl restart hermes-webui
# Example nginx allowlist for passkey registration endpoints
location ~ ^/api/auth/passkey/register {
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:8080;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

