Skip to content

fix(auth): fail fast on non-TTY login and tighten cli.yaml to 0600 - #282

Open
stantheman0128 wants to merge 2 commits into
zeabur:mainfrom
stantheman0128:fix/login-non-tty-0600
Open

stantheman0128 wants to merge 2 commits into
zeabur:mainfrom
stantheman0128:fix/login-non-tty-0600

Conversation

@stantheman0128

@stantheman0128 stantheman0128 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Unauthenticated commands hang forever on headless / non-TTY Linux environments. This is not the survey hang fixed in #280.

Cause

  1. PersistentPreRunE always calls AuthClient.GenerateToken when not logged in (except --json).
  2. browser.OpenURL can return nil even when no usable browser exists (e.g. DISPLAY=:1, Chromium starts, dbus/GPU dies).
  3. The login URL is never printed on the success path.
  4. WaitForToken has no timeout, so the process blocks forever.
  5. -i=false is ignored in PersistentPreRunE (only auth login -i=false takes the token path).

os.Stdin.Stat() + ModeCharDevice is the wrong non-TTY test: /dev/null is a char device, so that check false-positives as a terminal. term.IsTerminal correctly returns false for pipes and /dev/null.

Separately, os.Create for ~/.config/zeabur/cli.yaml uses 0666 & umask → typically 0644 while the file holds the access token.

Fix

  • CanCompleteBrowserLogin() via term.IsTerminal(stdin).
  • PersistentPreRunE: if not logged in and (JSON or !Interactive or non-TTY), require ZEABUR_TOKEN / --token instead of opening a browser.
  • GenerateToken: always print the URL; refuse the browser path when stdin is not a terminal; bound WaitForToken to 2 minutes.
  • auth login: only take the browser path when interactive and stdin is a terminal.
  • Create/chmod cli.yaml as 0600 (directory 0700).

Relation to #280

#280 adds ensureTerminal in pkg/prompt so survey does not hang. This PR covers the earlier hang: the implicit browser login in PersistentPreRunE / GenerateToken before any prompt runs. Both can occur on the same headless box; they are different code paths.

Test plan

  • go test ./pkg/auth ./pkg/config ./internal/cmd/auth/login
  • On Linux: timeout 5 zeabur auth login </dev/null → exit 1 (was 124)
  • On Linux: timeout 5 zeabur context clear -i=false </dev/null → fail-fast, no hang
  • Interactive TTY login still opens browser and prints URL

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

stantheman0128 and others added 2 commits October 2, 2026 16:44
Browser OpenURL can return nil on headless Linux (DISPLAY set, Chromium
starts, dbus dies) while WaitForToken blocks forever. ModeCharDevice is
the wrong test because /dev/null is a char device; use term.IsTerminal.

PersistentPreRunE now requires ZEABUR_TOKEN/--token when JSON, -i=false,
or stdin is not a terminal, instead of starting the browser callback.
GenerateToken always prints the URL and bounds WaitForToken.

Also create ~/.config/zeabur/cli.yaml as 0600 (and chmod existing files)
so the access token is not world-readable under a default umask.

Related to zeabur#280 (survey hang) but a different bug path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant