fix(auth): don't launch a text-mode browser inside the terminal for OAuth (#34479)

OAuth auto-open only checked _is_remote_session() (SSH + cloud-shell env
vars). On a headless/CLI-only Linux box with no GUI browser, none of those
trip, so webbrowser.open() resolved to a console browser (w3m/lynx/links)
and launched it INSIDE the terminal — hijacking the user's TTY with the
xAI 'Account Management' login page instead of letting them copy the URL.

Add _can_open_graphical_browser(): returns False when webbrowser would
resolve to a known console browser, when $BROWSER names one, when there's
no display server on Linux, or when no browser resolves at all. Gate all 5
OAuth auto-open callsites (xAI loopback, Spotify loopback, MiniMax device
code, Anthropic, Google) on it in addition to the existing remote check.
Headless boxes now print the URL / fall through to manual-paste instead.
This commit is contained in:
Teknium
2026-05-29 01:23:06 -07:00
committed by GitHub
parent f247686c42
commit c01a2df0a3
5 changed files with 201 additions and 7 deletions
+9 -3
View File
@@ -1256,10 +1256,16 @@ def run_hermes_oauth_login_pure() -> Optional[Dict[str, Any]]:
print()
try:
webbrowser.open(auth_url)
print(" (Browser opened automatically)")
from hermes_cli.auth import _can_open_graphical_browser as _can_open_gui
except Exception:
pass
_can_open_gui = lambda: True # noqa: E731 — degrade to prior behavior
if _can_open_gui():
try:
webbrowser.open(auth_url)
print(" (Browser opened automatically)")
except Exception:
pass
print()
print("After authorizing, you'll see a code. Paste it below.")
+9 -1
View File
@@ -899,7 +899,15 @@ def start_oauth_flow(
try:
import webbrowser
webbrowser.open(auth_url, new=1, autoraise=True)
try:
from hermes_cli.auth import (
_can_open_graphical_browser as _can_open_gui,
)
except Exception:
_can_open_gui = lambda: True # noqa: E731
if _can_open_gui():
webbrowser.open(auth_url, new=1, autoraise=True)
except Exception as exc:
logger.debug("webbrowser.open failed: %s", exc)