Skip to content

Credential file changes not detected mid-session in v5 #415

@AlexDaines

Description

@AlexDaines

Discussed in #414

Originally posted by nwsparks April 13, 2026
in our environment we need to regenerate credentials every hour. im using a shared credential file ~/.aws/credentials

in order to generate new credentials I'm running this https://github.com/venth/aws-adfs from bash which is updating the shared credential file.

prior to upgrading to v5, when the value of that file would change, pwsh would seamlessly pick it up. after upgrading to v5 i have to restart the pwsh session. I'm also having difficult when changing accounts as it seems to be caching the old account somehow.

Description

Users who rotate credentials via external tools (e.g. aws-adfs) that write to ~/.aws/credentials find that PS Tools v5 does not pick up the new credentials mid-session. This worked in v4. The user has to restart PowerShell or manually run Clear-AWSCredential.

Root Cause

Two caching layers prevent file changes from being detected:

  1. $StoredAWSCredentials session variable. Once TryGetCredentials() in CredentialsArguments.cs resolves credentials, the result is stored in $StoredAWSCredentials. Subsequent cmdlet calls hit lines 151-157 and short-circuit, returning the cached credentials without re-reading the profile chain. The SharedCredentialsFile.Refresh() path (which does re-read from disk) is never reached.

  2. DefaultAWSCredentialsIdentityResolver.EnvironmentState (lines 311-340 in DefaultAWSCredentialsIdentityResolver.cs). The HasEnvironmentChanged() method only monitors four environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_PROFILE). It does not check the credentials file mtime. This was deliberately scoped to env vars in PR #3590 (commit 9dd33271). File-based rotation was not considered.

In v4 (SDK v3), the $StoredAWSCredentials short-circuit path was less aggressively used, so the profile chain probe ran more often and SharedCredentialsFile.Refresh() re-read the file on each cmdlet call.

Suggested Fix

Add credentials file change detection to EnvironmentState.HasEnvironmentChanged(). Snapshot the file's last-modified timestamp alongside the env var snapshot, and include it in the invalidation check. SharedCredentialsFile.Refresh() already handles re-reading, the missing piece is triggering it when the file changes.

Updated Analysis

Dug into this more and the straightforward EnvironmentState fix is riskier than it looks. HasEnvironmentChanged() gets called on every API request through the auth pipeline (BaseAuthResolverHandler.PreInvoke -> ResolveIdentity -> InternalGetCredentials), so adding a file stat there means a syscall on every request. That's going to hurt at high throughput and on NFS/network home dirs. It also opens the door to cache thrashing for credential_process users where the helper touches the credentials file during refresh, which would trigger a full re-resolution (including re-running the subprocess) on every write. And we'd need to watch ~/.aws/config too since SSO profiles live there, not just ~/.aws/credentials.

Probably better to fix this closer to where the problem actually is:

  1. Fix it in the PS Tools layer (preferred). The regression is really about $StoredAWSCredentials short-circuiting the file re-read in interactive sessions. We could invalidate that cache when the credentials file changes without touching the SDK's per-request auth path at all. No impact on Lambda/ECS/high-throughput workloads.
  2. Opt-in flag in SDK Core. (don't love this one) Add something like EnableFileSystemWatch (default off) that PS Tools can flip on. Keeps the cost opt-in.
  3. Throttled stat in SDK Core. If it has to live in Core, at least cap the file check to once every N seconds so we're not doing a stat per request.

Workaround

Run Clear-AWSCredential after external credential rotation to force the next cmdlet to re-read from disk.

References

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions