flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion
Hermes Agent ネイティブログインのリダイレクト解析不備
Tenable は Hermes Agent のネイティブログインにおける重大なリダイレクト検証不備を公開しました。0.21.6 より前の版が影響を受けます。0.21.6 の修正は Docker/Hermes Cloud と CLI/git 向けに提供され、10 月 11 日公開の 0.21.7 では Desktop アプリ、Microsoft Store/MSIX、インストーラー、Docker、Hermes Cloud も配布対象として記載されています。確認したリリースノートに Termux は記載されていないため、別途確認してください。Tenable は High(CVSS 4.0 8.6)と評価しています。CVE は割り当てられていません。CWE-601 はリダイレクトの影響に対する編集上の分類です。[1], [2], [5]
受付が一つの地図で住所を確認し、受け取った文字列をそのまま別の地図を使う配達員に渡す場面を考えてください。配達員は受付が許可していない場所へ行くかもしれません。Hermes は Python のパーサーで callback を確認した後、未正規化の文字列をブラウザーへ渡しており、ブラウザーは別の意味に解釈する可能性がありました。[1]
主要な概念と専門用語
フレームワーク対応
- FlawOpenによるMITRE CWEへの概念上の対応付けです。ベンダーやCVEレコードがこの研究デモに弱点IDを割り当てたものではありません。 CWE-601
ステップ・バイ・ステップの攻撃フロー
ソースコード比較:脆弱 vs 堅牢化
これはセキュリティ境界を示す例であり、Hermes Agent の完全なソースコードや exploit ではありません。脆弱例は「解析後の host を確認して元入力を使う」流れを要約しています。修正版は、曖昧な入力を拒否し、正規の loopback authority のみ許可して正規 URI を返し、その値を保存・使用するという merged fix の性質を示します。実際の実装とテストはリンク先の PR を確認してください。[1], [3]
from urllib.parse import urlparse
def validate_callback(raw):
parsed = urlparse(raw)
# 元の処理は解析後のホストを検証しても、その後は未加工の URL を使い続けていました。
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 "/"))
エンジニアリング&システム堅牢化チェックリスト
- ✓Hermes Agent のバージョンとインストールチャネルを棚卸しし、実行中のビルドを確認します。0.21.7 のリリースノートには Desktop アプリ、Microsoft Store/MSIX、インストーラー、Docker、Hermes Cloud が記載されています。[5]
- ✓対応するチャネルで 0.21.7 以降へ更新してください。確認したリリースノートに Termux は記載されていないため、別途確認します。[2], [5]
- ✓検証関数が正規化した値を返し、認可フローが同じ値を保存して使うことを確認します。別表現を検証して元入力を使ってはいけません。[3]
- ✓パーサー差異、userinfo、バックスラッシュ、フラグメント、非正規 IP/ポートを拒否する回帰テストを追加し、拒否値がコード発行に到達しないことを確認します。[3]