Skip to content

sec(cli): scheme-allowlist openBrowser + atomic tokens.Save (F-17, F-18)#20

Merged
mastermanas805 merged 2 commits into
masterfrom
sec/openbrowser-scheme-allowlist
May 29, 2026
Merged

sec(cli): scheme-allowlist openBrowser + atomic tokens.Save (F-17, F-18)#20
mastermanas805 merged 2 commits into
masterfrom
sec/openbrowser-scheme-allowlist

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Closes SEC-CLI F-17 (CWE-78/88) and F-18 (CWE-367 TOCTOU) — both static-only findings, defense-in-depth.

F-17 — openBrowser scheme allowlist (cmd/login.go)

A hostile API server returning {"auth_url":"-Fpath"} would otherwise invoke open -F path on macOS, surfacing a local file in Finder. The CLI talks to TLS-protected instanode.dev today so the threat model is narrow, but the cost of hardening is ~20 LOC.

safeBrowserURL() now refuses:

  • empty / whitespace-only URLs
  • URLs with a leading - (so they can't be parsed as helper-binary flags)
  • any scheme outside {http, https}
  • URLs with an empty host

F-18 — atomic tokens.Save (internal/tokens/store.go)

Crash mid-write previously truncated ~/.instant-tokens and lost every recorded anonymous token. Save() now mirrors the existing cliconfig.Save idiom: temp file + atomic rename.

Tests

  • cmd/login_safe_url_test.go covers the allowlist and asserts openBrowser doesn't panic on refused URLs.
  • internal/tokens/store_atomic_test.go verifies no .tmp leak after success and that rename overwrites pre-existing bytes.

Local verify

go build ./...                                  -> 0
go test ./cmd/ ./internal/... -count=1 -short   -> ok (all 4 packages)

🤖 Generated with Claude Code

mastermanas805 and others added 2 commits May 29, 2026 23:25
Defense-in-depth fixes flagged in SEC-CLI:

* F-17 (cli/cmd/login.go): safeBrowserURL rejects leading-dash and
  non-http(s) schemes before invoking open/xdg-open/rundll32 with a
  server-controlled URL. Hostile {"auth_url":"-Fpath"} from a
  compromised /auth/cli response can no longer surface a local file in
  Finder on macOS.

* F-18 (cli/internal/tokens/store.go): Save() now writes
  ~/.instant-tokens.tmp + renames atomically, mirroring
  cliconfig.Save. A crash mid-write can no longer truncate the local
  anonymous-token cache and lose every recorded token (server still
  has the resource; user just couldn't find it locally).

Tests:
* cmd/login_safe_url_test.go covers the allowlist (leading-dash,
  javascript:, file:, ftp:, empty host) and a smoke check that
  openBrowser does not panic on refused URLs.
* internal/tokens/store_atomic_test.go verifies no .tmp leak after
  successful save and that rename clobbers pre-existing bytes.

Local verify:
  go build ./...                       -> 0
  go test ./cmd/ ./internal/... -count=1 -short -> ok (all 4 packages)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…patch gate

Address the coverage-gate failure on PR #20:

* Extract browserLauncherForGOOS + openBrowserOn so all per-OS branches
  (darwin / linux / windows / unknown) and the exec-failure path are
  reachable from a single Linux CI runner via injected GOOS strings.
* Add tests for tokens.Save's rename-failure cleanup branch — make the
  target path a non-empty directory so os.Rename fails and the
  best-effort os.Remove(tmp) runs.

Local verify:
  go build ./...                                  -> 0
  go test ./cmd/ ./internal/tokens -count=1       -> ok
  coverage on touched lines                       -> 100 %

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 6ee06fe into master May 29, 2026
10 checks passed
@mastermanas805 mastermanas805 deleted the sec/openbrowser-scheme-allowlist branch May 29, 2026 18:09
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