Skip to content

Harden OAuth U2M token cache encryption and file permissions#1520

Open
sreekanth-db wants to merge 1 commit into
mainfrom
fix/sec-20598-token-cache-hardening
Open

Harden OAuth U2M token cache encryption and file permissions#1520
sreekanth-db wants to merge 1 commit into
mainfrom
fix/sec-20598-token-cache-hardening

Conversation

@sreekanth-db

@sreekanth-db sreekanth-db commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replaces the hardcoded PBKDF2 salt in EncryptedFileTokenCache with a per-file random salt, preventing offline key derivation from the passphrase alone.
  • Fixes the TOCTOU file-permission race by setting owner-only permissions (0600) before writing content, rather than after.
  • Adds unit tests covering random salt uniqueness, hardcoded-salt resistance, cross-instance round-trip, and POSIX permission enforcement.

Scope: Only affects the OAuth U2M browser flow (AuthMech=11;Auth_Flow=2) with EnableTokenCache=1. PAT, M2M, token-passthrough, and Azure-MI are unaffected.

User impact: Existing cached tokens (old format) will not decrypt after upgrade, triggering a one-time browser re-login. This is handled gracefully — load() returns null and the SDK performs a fresh authentication.

Addresses SEC-20598.

Testing

Unit Tests

All 21 unit tests in EncryptedFileTokenCacheTest pass — 14 existing tests remain green, and 5 new tests were added covering:

  • Tokens saved in the new format cannot be decrypted using the old hardcoded salt and passphrase alone.
  • Each save produces a unique per-file salt (no two encrypted files share the same key derivation input).
  • Round-trip save/load works correctly across separate cache instances with the same passphrase.
  • File is created with owner-only permissions (rw-------) from the start, not loosened then tightened.
  • Pre-existing files with loose permissions (e.g. rw-r--r--) are tightened to rw------- on overwrite.

Offline Vulnerability Repro

A deterministic test (no browser or network required) saves a token and then simulates an attacker who knows the passphrase and the old hardcoded salt attempting to decrypt it:

  • Before fix: attacker successfully recovers the refresh token — confirming the vulnerability.
  • After fix: decryption fails — the random per-file salt prevents offline key derivation.

End-to-End U2M Browser Flow

Tested the full OAuth U2M flow (AuthMech=11;Auth_Flow=2;EnableTokenCache=1) against an Azure Databricks workspace, both before and after the fix:

Before fix (baseline):

  • Browser login succeeded, query executed, token cache file written.
  • File permissions: rw-------.
  • Cache file was decryptable using the old hardcoded salt — confirming the vulnerability.
  • Second connection reused the cache silently (no browser prompt).

After fix:

  • Browser login succeeded, query executed, token cache file written in the new format.
  • File permissions: rw-------.
  • Cache file not decryptable using the old hardcoded salt — vulnerability resolved.
  • Second connection reused the cache silently (no browser prompt) — confirms the new encrypted format saves and loads correctly.
  • Old-format cache files fail to decrypt gracefully (no crash), triggering a one-time browser re-login. Subsequent connections reuse the new-format cache as expected.

NO_CHANGELOG=false

This pull request and its description were written by Isaac.

- Replace the hardcoded PBKDF2 salt with a per-file random 16-byte salt,
  stored alongside the IV in the encrypted payload. This prevents offline
  key derivation from the passphrase alone.
- Set file permissions to owner-only (0600) before writing content,
  eliminating the TOCTOU window where the cache file could be
  world-readable. Non-POSIX platforms retain best-effort behavior.
- New on-disk format: Base64(salt[16] || IV[16] || ciphertext). Existing
  caches written with the old fixed-salt format will fail to decrypt and
  trigger a one-time re-authentication (handled gracefully by the SDK).
- Add unit tests for random salt uniqueness, hardcoded-salt resistance,
  cross-instance round-trip, and POSIX permission enforcement.

Co-authored-by: Isaac
Signed-off-by: Sreekanth Vadigi <sreekanth.vadigi@databricks.com>
@vikrantpuppala

Copy link
Copy Markdown
Collaborator

can we add testing details to pr description?

@sreekanth-db

Copy link
Copy Markdown
Collaborator Author

Updated the PR description with testing details — unit tests, offline vulnerability repro, and end-to-end U2M browser flow results (before and after the fix).

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