Hermes Agent - PKCE Session Takeover via Redirect-URI Parser Confusion

High

Synopsis

Note: Another researcher identified the same vulnerability during the disclosure process with the Nous Researcher team.

In Hermes Agent, the public GET /auth/native/authorize flow validates the redirect_uri with Python's urllib.parse.urlparse, then hands the raw, unnormalized value back to the browser after authentication.

The two parsers treat backslashes differently. Python's parser and the browser's WHATWG parser therefore disagree on the URL's actual host. The server can accept a URL it classifies as loopback (127.0.0.1) while the browser navigates to a different, attacker-controlled origin. The attacker also chooses the PKCE challenge, so they can exchange the leaked authorization code for the victim account's tokens. This results in a full session takeover.

The _validate_loopback_redirect_uri function is explicitly meant to allow only literal loopback addresses, since a remote origin would otherwise receive a live authorization code. However, it parses raw, checks parsed.hostname, and then returns raw unchanged. register_pending stores this raw string. After a valid sign-in, auth_password_login appends code and state to it, and the page script redirects with window.location.assign(data.next).

The discrepancy reproduces with http://127.0.0.1:17777\@127.0.0.1:27777/callback. urlparse reads 127.0.0.1:17777\ as user information before the @ and reports the hostname as 127.0.0.1, with port 27777. The browser instead treats \ as a path separator in an HTTP URL. It opens http://127.0.0.1:17777/@127.0.0.1:27777/callback, so the request goes to the origin on port 17777. In testing, the browser reached this second origin carrying the code and state parameters. 

A remote host placed before the backslash would receive the authorization code in the same way.

Solution

Upgrade to Hermes Agent version 0.21.6 or later.

Disclosure Timeline

September 03 2026 - First Contact
September 09 2026 - Second Attempt
September 10 2026 - Nous Research requests details via email or GitHub.
September 10 2026 - Details sent by email
September 16 2026 - Tenable asking for updates
September 23 2026 - Tenable asking for updates
September 29 2026 - Tenable asking for updates
October 05 2026 - Tenable asking for updates
October 05 2026 - Nous Research request to send the details again
October 05 2026 - Tenable has re-sent the reports
October 05 2026 - Nous Research indicated that someone pushed a fix four days ago, so it is considered already fixed.

All information within TRA advisories is provided “as is”, without warranty of any kind, including the implied warranties of merchantability and fitness for a particular purpose, and with no guarantee of completeness, accuracy, or timeliness. Individuals and organizations are responsible for assessing the impact of any actual or potential security vulnerability.

Tenable takes product security very seriously. If you believe you have found a vulnerability in one of our products, we ask that you please work with us to quickly resolve it in order to protect customers. Tenable believes in responding quickly to such reports, maintaining communication with researchers, and providing a solution in short order.

For more details on submitting vulnerability information, please see our Vulnerability Reporting Guidelines page.

If you have questions or corrections about this advisory, please email [email protected]