sec(cli): scheme-allowlist openBrowser + atomic tokens.Save (F-17, F-18)#20
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 invokeopen -F pathon 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:-(so they can't be parsed as helper-binary flags){http, https}F-18 — atomic tokens.Save (
internal/tokens/store.go)Crash mid-write previously truncated
~/.instant-tokensand lost every recorded anonymous token.Save()now mirrors the existingcliconfig.Saveidiom: temp file + atomic rename.Tests
cmd/login_safe_url_test.gocovers the allowlist and assertsopenBrowserdoesn't panic on refused URLs.internal/tokens/store_atomic_test.goverifies no.tmpleak after success and that rename overwrites pre-existing bytes.Local verify
🤖 Generated with Claude Code