Skip to content

fix: data race, token file misplacement, and silent auth errors#170

Open
iamMrGaurav wants to merge 2 commits intoUse-Tusk:mainfrom
iamMrGaurav:fix/auth-config-race-critical
Open

fix: data race, token file misplacement, and silent auth errors#170
iamMrGaurav wants to merge 2 commits intoUse-Tusk:mainfrom
iamMrGaurav:fix/auth-config-race-critical

Conversation

@iamMrGaurav
Copy link

  • Guard Executor.cancelTests with a mutex to eliminate the data race between RunTestsConcurrently and the signal-handler CancelTests path
  • Return error from NewAuthenticator when os.UserConfigDir() fails, preventing auth tokens from being written to the current working directory instead of ~/.config/tusk/
  • Propagate io.ReadAll errors in all four Auth0 HTTP response paths (device code, token poll, userinfo, refresh) instead of silently continuing with a partial body

  - Guard Executor.cancelTests with a mutex to eliminate the data race
    between RunTestsConcurrently and the signal-handler CancelTests path
  - Return error from NewAuthenticator when os.UserConfigDir() fails,
    preventing auth tokens from being written to the current working
    directory instead of ~/.config/tusk/
  - Propagate io.ReadAll errors in all four Auth0 HTTP response paths
    (device code, token poll, userinfo, refresh) instead of silently
    continuing with a partial body
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@iamMrGaurav
Copy link
Author

@sohil-kshirsagar Please review :)

@jy-tan
Copy link
Contributor

jy-tan commented Feb 14, 2026

@iamMrGaurav Thanks for the contribution. The fixes look reasonable, but before we can merge we need reproducible evidence for each bug claim.

Could you please add:

  1. a minimal repro for the Executor.cancelTests race,
  2. repro details for os.UserConfigDir() failing and resulting auth path behavior, and
  3. regression tests (or at least one focused test) covering the changed paths?

We’ll keep this open while you add that context; if there’s no follow-up in 7 days, we’ll close and can revisit once repro/tests are available.

@iamMrGaurav
Copy link
Author

iamMrGaurav commented Feb 15, 2026

Please let me know if i should remove the test files later, Below are the reproducible steps as follows :


  1. Executor.cancelTests data race

RunTestsConcurrently writes e.cancelTests while a signal-handler goroutine reads and invokes it via CancelTests() — no synchronisation on the
field. TestExecutor_CancelTests_NoDataRace hammers both goroutines 50 times concurrently under -race:

$ go test -race ./internal/runner/ -run "TestExecutor_CancelTests" -v -count=1

=== RUN TestExecutor_CancelTests_NoDataRace
--- PASS: TestExecutor_CancelTests_NoDataRace (0.19s)
=== RUN TestExecutor_CancelTests_BeforeRunIsNoop
--- PASS: TestExecutor_CancelTests_BeforeRunIsNoop (0.00s)
PASS
ok github.com/Use-Tusk/tusk-drift-cli/internal/runner 1.904s

Without the cancelTestsMu sync.Mutex added in this PR, the race detector flags a DATA RACE on e.cancelTests between these two goroutines.


  1. os.UserConfigDir() failure → relative auth path

The old code was cfgDir, _ := os.UserConfigDir(). When that call fails (e.g. $HOME unset in a restricted/container environment), cfgDir is "" and
filepath.Join("", "tusk", "auth.json") resolves to the relative path tusk/auth.json — the token gets written to the current working directory
instead of the user config dir.

TestNewAuthenticator_UserConfigDirFailure clears $HOME / $XDG_CONFIG_HOME to reproduce this, and asserts NewAuthenticator now returns an explicit
error instead of silently producing a bad path.


  1. Silent io.ReadAll errors in four auth methods

All four Auth0 HTTP methods (RequestDeviceCode, PollForToken, FetchUserEmail, refreshAccessToken) had body, _ := io.ReadAll(resp.Body). A
mid-stream network drop would leave body empty/partial, and the subsequent json.Unmarshal would fail silently — surfacing no error to the caller.

Each method now has a dedicated regression test using a custom transport whose response body errors immediately on Read:

$ go test -race ./internal/auth/ -v -count=1

=== RUN TestNewAuthenticator_UserConfigDirFailure
--- PASS: TestNewAuthenticator_UserConfigDirFailure (0.00s)
=== RUN TestNewAuthenticator_AuthPathIsAbsolute
--- PASS: TestNewAuthenticator_AuthPathIsAbsolute (0.00s)
=== RUN TestRequestDeviceCode_PropagatesReadError
--- PASS: TestRequestDeviceCode_PropagatesReadError (0.00s)
=== RUN TestPollForToken_PropagatesReadError
--- PASS: TestPollForToken_PropagatesReadError (0.00s)
=== RUN TestFetchUserEmail_PropagatesReadError
--- PASS: TestFetchUserEmail_PropagatesReadError (0.00s)
=== RUN TestRefreshAccessToken_PropagatesReadError
--- PASS: TestRefreshAccessToken_PropagatesReadError (0.00s)
PASS
ok github.com/Use-Tusk/tusk-drift-cli/internal/auth 1.618s

@jy-tan Please review :)

@iamMrGaurav
Copy link
Author

@jy-tan hey, please let me know if there is any update on this ?

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.

2 participants