Deep Dive: The Credential Exposure Module — Finding Secrets Before Attackers Do
Your Windows machine is leaking credentials in a dozen places you've never checked. WinSentinel's Credential Exposure module hunts them all — from plaintext SSH keys to cached cloud tokens buried in AppData.
Here's a question that should make you uncomfortable: if an attacker got a shell on your machine right now — standard user, no admin privileges — how many credentials could they harvest without triggering a single alert? The answer, on most Windows workstations, is "enough to pivot to production infrastructure within minutes."
This isn't about Mimikatz or LSASS dumping. Those require admin rights and are well-detected by modern EDR. I'm talking about credentials that are already on disk in readable form, accessible to any process running as your user. Git credential stores. SSH keys without passphrases. Cloud CLI tokens. Browser-saved passwords. Wi-Fi pre-shared keys. The credential surface on a typical developer or admin machine is staggering.
WinSentinel's Module #6 (Credential Exposure) systematically audits every one of these vectors. Let's walk through exactly what it checks, why each matters, and what you can do about it.
What the Module Actually Scans
When you run winsentinel --audit --modules credentials, the module performs seven distinct analysis passes:
1. Windows Credential Manager
The built-in Credential Manager (cmdkey /list) stores cached credentials for network shares, RDP sessions, and web logins. The problem isn't that it exists — it's that many of these entries outlive their usefulness and expand your blast radius if compromised.
$ winsentinel --audit --modules credentials
Credential Exposure
─────────────────────────────────────────────────────
[WARNING] Windows Credential Manager: 14 stored credentials
→ 3 RDP targets with saved passwords
→ 2 network shares with domain credentials
→ 1 entry older than 365 days (likely stale)
→ Review: cmdkey /list | Remove stale: cmdkey /delete:target
The risk: any process running as your user can enumerate and use these credentials via CredRead() API calls. An attacker doesn't need your password — they just call the same Windows API your RDP client uses.
What to do: Periodically purge credentials you no longer need. WinSentinel flags entries older than 180 days as likely stale. For RDP, use a password manager or certificate-based auth instead of saved passwords.
2. Git Credential Stores
Git's credential helpers vary wildly in security. The module checks for the worst offender first:
[CRITICAL] Git credentials stored in plaintext file
→ C:\Users\you\.git-credentials contains 3 tokens
→ credential.helper = store (writes plaintext to disk)
→ Fix: git config --global credential.helper manager
→ Then delete: Remove-Item ~/.git-credentials
git config credential.helper store writes your PATs and passwords to ~/.git-credentials in cleartext. No encryption. No ACL restrictions beyond your user profile. Any malware, any rogue npm postinstall script, any process running as you can read them.
The module checks for:
~/.git-credentials— plaintext credential file (Critical)credential.helper = storein git config (Critical)credential.helper = managerormanager-core— DPAPI-protected, acceptable (Info)- Tokens embedded directly in
.git/configremote URLs (Critical)
The fix: Switch to Git Credential Manager, which stores tokens in Windows Credential Manager (DPAPI-encrypted, tied to your login session):
git config --global credential.helper manager
Remove-Item "$env:USERPROFILE\.git-credentials" -ErrorAction SilentlyContinue
3. SSH Key Security
The module inspects every key in ~/.ssh/ for three properties: passphrase protection, algorithm strength, and file permissions.
[WARNING] SSH private key without passphrase: id_ed25519
→ C:\Users\you\.ssh\id_ed25519
→ Key type: ed25519 (algorithm OK)
→ No passphrase protection — usable by any process as your user
→ Fix: ssh-keygen -p -f ~/.ssh/id_ed25519
[WARNING] SSH key using weak algorithm: id_rsa (RSA-2048)
→ Consider upgrading to Ed25519: ssh-keygen -t ed25519
[INFO] SSH key with passphrase: deploy_key (protected)
A passphrase-less SSH key is functionally equivalent to a password written on a Post-it note next to your monitor. If malware can read files in your home directory (which any user-level process can), it has your key. The passphrase adds a symmetric encryption layer that requires user input to unlock.
Yes, passphrase-protected keys are slightly less convenient. Use ssh-agent to cache the decrypted key for your session — you type the passphrase once at login, and it stays unlocked until you log out. Security without constant friction:
# Start ssh-agent (if not running)
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
# Add your key (prompts for passphrase once)
ssh-add ~/.ssh/id_ed25519
4. Cloud CLI Credential Files
This is the vector most people forget about. Cloud CLIs cache authentication tokens to disk so you don't re-authenticate every command. Those cached tokens are typically:
- AWS:
~/.aws/credentials— plaintext access key + secret key - Azure:
~/.azure/msal_token_cache.json— OAuth refresh tokens - GCP:
~/.config/gcloud/credentials.db— SQLite with OAuth tokens - Kubernetes:
~/.kube/config— cluster certs and tokens
[CRITICAL] AWS credentials in plaintext
→ C:\Users\you\.aws\credentials
→ Contains access_key_id + secret_access_key for profile [production]
→ Risk: Full AWS API access for any process running as your user
→ Fix: Use aws sso login for temporary credentials, or
rotate keys and use credential_process with a secrets manager
[WARNING] Kubernetes config contains embedded certificates
→ C:\Users\you\.kube\config
→ 2 clusters with client-certificate-data embedded
→ Risk: Cluster admin access without additional authentication
The AWS credentials file is particularly dangerous because those keys don't expire unless you explicitly rotate them. An attacker who steals your ~/.aws/credentials has persistent API access even after you change your Windows password, rotate your domain credentials, or reimage the machine.
Mitigations:
- Use AWS SSO / IAM Identity Center for temporary session credentials
- Use Azure's
az loginwith short-lived tokens + MFA (token cache is DPAPI-protected on Windows) - For Kubernetes, use OIDC auth plugins instead of embedded certs
- Never store production credentials locally — use assume-role chains with MFA
5. Saved RDP Credentials
Every time you check "Remember my credentials" on an RDP connection, Windows stores them in Credential Manager. The module specifically audits .rdp files and Credential Manager entries for RDP targets:
[WARNING] Saved RDP credentials: 3 targets
→ PROD-SQL01.corp.local (domain admin context?)
→ DEV-JUMP01.corp.local
→ 10.0.50.12 (unresolved — internal IP)
→ Risk: Credential theft enables lateral movement to these targets
→ Review: cmdkey /list | grep "TERMSRV"
Saved RDP credentials are a lateral movement goldmine. Compromise one workstation, harvest the saved RDP creds, pivot to the next machine. Repeat until you hit a domain controller.
6. Browser Credential Stores
Chrome and Edge store passwords in a SQLite database encrypted with DPAPI. Firefox uses its own encryption. The module checks:
- Whether the browser credential store contains entries (quantity = risk surface)
- Whether Chrome's encryption is tied to the current user (DPAPI) or has a master password (Firefox)
- Whether any browser extensions have permission to access passwords
WinSentinel doesn't read or display your saved passwords — it counts them and flags the exposure surface. 200 saved passwords in Chrome means 200 credentials accessible to any malware running as your user that knows how to call CryptUnprotectData().
Recommendation: Use a dedicated password manager (1Password, Bitwarden, KeePass) instead of browser-native storage. Dedicated managers use stronger key derivation, support hardware key protection, and aren't accessible via standard Windows crypto APIs.
7. Plaintext Credential Files
The final pass is a heuristic scan for common credential file patterns that don't fit the above categories:
.envfiles containingAPI_KEY=,SECRET=,PASSWORD=patternsdocker-compose.ymlwith hardcoded database passwords*.configfiles with connection strings containing passwords- PowerShell scripts with
ConvertTo-SecureStringusing hardcoded keys credentials.json,secrets.yaml,*.pemin non-standard locations
[WARNING] Potential credential file: C:\Projects\myapp\.env
→ Contains 4 lines matching secret patterns
→ Not in .gitignore (risk of accidental commit)
→ Ensure this file is not tracked in version control
This isn't a secret scanner (it doesn't decode or validate the credentials). It's a surface-area check that identifies files likely to contain secrets so you can verify they're properly protected.
The Compound Risk
Each individual credential exposure is a moderate risk. The compound effect is devastating. Consider a realistic developer workstation:
- 3 passphrase-less SSH keys (access to: GitHub, production bastion, internal GitLab)
- AWS credentials for a staging account (with lateral access to production via assume-role)
- 8 saved RDP passwords (including a jump box that reaches prod databases)
- 142 browser-saved passwords (including SSO portals, cloud consoles, CI/CD systems)
- A
.envfile with a Stripe production API key (from debugging last month)
A single infostealer — delivered via a malicious VSCode extension, a compromised npm package, or a phishing email — harvests all of this in under 5 seconds. No privilege escalation needed. No exploit required. Just file reads from the user's home directory.
Running the Audit
# Full credential exposure scan
winsentinel --audit --modules credentials
# Fix what's auto-fixable (switches git credential helper, flags stale entries)
winsentinel --fix --modules credentials
# JSON output for tracking over time
winsentinel --audit --modules credentials --json > cred-audit-$(Get-Date -Format yyyy-MM-dd).json
The module runs in 3–5 seconds. It doesn't transmit anything, doesn't phone home, and doesn't read the content of your credentials — it identifies their existence and exposure level. All checks are local, offline, and deterministic.
The Uncomfortable Truth
Most security teams focus on network perimeters, endpoint detection, and patch management. These matter. But the single fastest path from "compromised workstation" to "breached production environment" runs through cached credentials on disk. It's not glamorous. It doesn't make conference talks. But it's how the majority of real-world lateral movement actually works.
Run winsentinel --audit --modules credentials today. If you have plaintext git credentials, fix them in 30 seconds. If you have passphrase-less SSH keys accessing production systems, add passphrases. If you have AWS access keys sitting in ~/.aws/credentials, switch to SSO. These are 5-minute fixes that eliminate the cheapest, most reliable attack path into your infrastructure.