flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion
Hermes Agent native sign-in redirect parsing flaw
Tenable disclosed a high-severity redirect validation flaw in Hermes Agent native sign-in. Versions before 0.21.6 are affected. The v0.21.6 fix reached Docker/Hermes Cloud and CLI/git installs; v0.21.7, released October 11, also lists the Desktop app, Microsoft Store/MSIX, installer, Docker, and Hermes Cloud. The reviewed release notes do not name Termux, so verify that channel separately. Tenable rates it High (CVSS 4.0 8.6); no CVE is assigned. CWE-601 is an editorial mapping for the redirect outcome.[1], [2], [5]
Imagine a receptionist checks an address using one map, writes down the unchecked address exactly as supplied, and later gives it to a courier using a different map. The courier may go somewhere the receptionist never approved. Hermes checked a callback as loopback with Python, then handed its raw form to a browser that can parse it differently.[1]
Core Concepts & Subsystem Terms
Native-app callback- A temporary local web address used by a desktop app to receive the result of a browser-based sign-in.[1], [4]
URL parser differential- Two URL parsers assign different meaning to the same input; validating one interpretation and later using another breaks the security boundary.[1], [3]
Framework mappings
- FlawOpen’s conceptual mapping to MITRE CWE; no vendor or CVE record assigned this weakness ID to this research demonstration. CWE-601
Step-by-Step Attack Flow
A public native-login route receives a callback
The native sign-in authorization endpoint accepts a redirect URI and PKCE challenge before the user is authenticated.[1]
A completed sign-in can expose the authorization code
After the victim completes the normal login, the browser may send the code to the authority it parsed. An attacker who selected the matching PKCE challenge can then attempt to redeem it. The issue requires victim sign-in; it is not a no-interaction account takeover.[1]
Canonicalize and update the delivered build
The fix rejects ambiguous syntax and noncanonical authorities, returns the canonical URI, and stores that returned value. Upgrade to v0.21.7 or later through a supported channel; verify Termux separately because the reviewed v0.21.7 notes do not name it.[2], [5], [3]
Source Code: Flaw vs. Secure Implementation
This is an illustrative boundary model, not the complete Hermes Agent source or an exploit. The vulnerable example captures the advisory’s validate-parsed-host/use-raw pattern. The hardened example demonstrates the property in the merged fix: reject ambiguous input, allow only canonical loopback authorities, return the canonical URI, and persist/use that return value. See the linked PR for the actual implementation and tests.[1], [3]
from urllib.parse import urlparse
def validate_callback(raw):
parsed = urlparse(raw)
# The original flow checked the parsed host, then retained raw.
if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1"}:
return raw
raise ValueError("callback must be loopback")
from urllib.parse import urlparse, urlunparse
LOOPBACK_HOSTS = {"127.0.0.1": "127.0.0.1", "::1": "[::1]"}
def validate_callback(raw):
if not raw.isascii() or "\\" in raw or any(ord(c) <= 0x20 or ord(c) == 0x7f for c in raw):
raise ValueError("callback must use canonical loopback syntax")
try:
parsed = urlparse(raw)
host, port = parsed.hostname, parsed.port
except ValueError as exc:
raise ValueError("invalid callback") from exc
if parsed.scheme != "http" or "#" in raw or parsed.username is not None or parsed.password is not None:
raise ValueError("callback must be a plain loopback URL")
authority_host = LOOPBACK_HOSTS.get(host)
if authority_host is None:
raise ValueError("callback host must be a loopback IP literal")
authority = authority_host + (f":{port}" if port is not None else "")
if parsed.netloc != authority:
raise ValueError("callback authority is not canonical")
return urlunparse(parsed._replace(path=parsed.path or "/"))
Engineering & System Hardening Checklist
- ✓Inventory Hermes Agent versions and installation channels, then verify the running build. The v0.21.7 release lists Desktop, Microsoft Store/MSIX, installer, Docker, and Hermes Cloud delivery.[5]
- ✓Upgrade to v0.21.7 or later through the relevant supported channel; verify Termux separately because the reviewed release notes do not list it.[2], [5]
- ✓Ensure callback validation returns a canonical value and the authorization flow stores and uses that exact value; never validate one representation and later use the raw input.[3]
- ✓Add regression tests for parser disagreement, userinfo, backslashes, fragments, noncanonical IP spellings and ports; verify rejected values stop before login code issuance.[3]