Skip to content

Fix auth switch writing to a stale config path - #1883

Open
jstoadv wants to merge 1 commit into
digitalocean:mainfrom
jstoadv:fix/auth-switch-stale-config-path
Open

Fix auth switch writing to a stale config path#1883
jstoadv wants to merge 1 commit into
digitalocean:mainfrom
jstoadv:fix/auth-switch-stale-config-path

Conversation

@jstoadv

@jstoadv jstoadv commented Jul 17, 2026

Copy link
Copy Markdown

Fixes #1882

What

doctl auth switch --context <name> prints Now using context [<name>] by default but silently fails to persist when the config file carries a top-level config: key pointing somewhere other than the file in use. It writes the update to that stale path and leaves the live config unchanged.

Why

writeConfig() marshals viper.AllSettings(), which includes the bound config flag, so a top-level config: key gets baked into the file on every write. On the next run viper reads it back, and because a config-file value outranks a flag's default, viper.GetString("config") returns that stored path. defaultConfigFileWriter() then uses it as the write target. When the config was copied between machines (e.g. macOS ~/Library/Application Support/doctl/ → a Linux container's ~/.config/doctl/), the stored path is stale and the write misses the live file. --config <path> masks the bug because an explicitly-set flag outranks the config-file value.

Fix

Write to viper.ConfigFileUsed() — the path resolved at init, before the config file is read — falling back to viper.GetString("config") only if it is unset. This can't be hijacked by the persisted key. The file still contains the config: key (unchanged behavior, still asserted by TestAuthInitConfig); only the write target is corrected.

Test

TestDefaultConfigFileWriterUsesLoadedConfig loads a config that carries a stale config: path and asserts the writer targets the loaded file, not the stale path. It fails on main and passes with this change.

ok  github.com/digitalocean/doctl/commands

Reproduce (before this change)

sed -i 's#^config: .*#config: /tmp/doctl-STALE.yaml#' ~/.config/doctl/config.yaml
doctl auth switch --context myteam      # prints success
grep '^context:' ~/.config/doctl/config.yaml   # unchanged
grep '^context:' /tmp/doctl-STALE.yaml         # context: myteam  (written here instead)

@jstoadv
jstoadv force-pushed the fix/auth-switch-stale-config-path branch from dcc47c7 to 4d07690 Compare July 17, 2026 17:46
`auth switch` writes the updated config to `viper.GetString("config")`, but
`writeConfig` persists `viper.AllSettings()` — which includes the bound
`config` flag — so a top-level `config:` key is saved into the file. On the
next run viper reads it back, and because a config-file value outranks a
flag's default, `GetString("config")` returns that stored path. When a config
is copied between machines the path is stale, so `auth switch` silently writes
there and prints success while the loaded config is left unchanged.

Write to `viper.ConfigFileUsed()` — the path resolved at init, before the
config file is read — so the write target can't be hijacked by the persisted
key. Add a regression test covering a config that carries a stale `config:`.

Fixes digitalocean#1882
@jstoadv
jstoadv force-pushed the fix/auth-switch-stale-config-path branch from 4d07690 to ba2ff2e Compare July 17, 2026 17:49
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.

auth switch silently writes to a stale path when config carries a persisted config: key

1 participant