Skip to content

authenticator: zeroize ValidatedClaims and OidcClaims on drop#35704

Merged
jasonhernandez merged 2 commits intomainfrom
jasonhernandez/sec-115-authenticator-zeroize
Apr 17, 2026
Merged

authenticator: zeroize ValidatedClaims and OidcClaims on drop#35704
jasonhernandez merged 2 commits intomainfrom
jasonhernandez/sec-115-authenticator-zeroize

Conversation

@jasonhernandez
Copy link
Copy Markdown
Contributor

Motivation

Defense-in-depth: zero user identity and JWT claim data from memory after use.

Description

  • Implement Zeroize + ZeroizeOnDrop for ValidatedClaims (user identity string)
  • Implement Zeroize for OidcClaims (issuer, audience, timestamps, unknown claims)
  • Document that OidcDecodingKey wraps opaque jsonwebtoken::DecodingKey and cannot be zeroized
  • Document that borrowed JWT token &str parameters are the caller's responsibility
  • Regression tests for trait bounds and field clearing

No public API changes.

Depends on

Part of SEC-115.

@github-actions
Copy link
Copy Markdown
Contributor

Thanks for opening this PR! Here are a few tips to help make the review process smooth for everyone.

PR title guidelines

  • Use imperative mood: "Fix X" not "Fixed X" or "Fixes X"
  • Be specific: "Fix panic in catalog sync when controller restarts" not "Fix bug" or "Update catalog code"
  • Prefix with area if helpful: compute: , storage: , adapter: , sql:

Pre-merge checklist

  • The PR title is descriptive and will make sense in the git log.
  • This PR has adequate test coverage / QA involvement has been duly considered. (trigger-ci for additional test/nightly runs)
  • If this PR includes major user-facing behavior changes, I have pinged the relevant PM to schedule a changelog post.
  • This PR has an associated up-to-date design doc, is a design doc (template), or is sufficiently small to not require a design.
  • If this PR evolves an existing $T ⇔ Proto$T mapping (possibly in a backwards-incompatible way), then it is tagged with a T-proto label.
  • If this PR will require changes to cloud orchestration or tests, there is a companion cloud PR to account for those changes that is tagged with the release-blocker label (example).

@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch from e9bc8be to 1c8aafa Compare March 26, 2026 20:37
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-ore-zeroize-feature branch 4 times, most recently from 1308d53 to 9b3927b Compare March 31, 2026 17:21
Base automatically changed from jasonhernandez/sec-115-ore-zeroize-feature to main March 31, 2026 17:30
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch from 1c8aafa to eb68d55 Compare March 31, 2026 18:56
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch 2 times, most recently from 84c87e8 to 60e3a90 Compare April 15, 2026 05:01
@jasonhernandez jasonhernandez changed the title authenticator: Zeroize ValidatedClaims and OidcClaims on drop authenticator: zeroize ValidatedClaims and OidcClaims on drop Apr 15, 2026
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch 2 times, most recently from 3f2512b to 2860d6d Compare April 15, 2026 05:06
@jasonhernandez jasonhernandez marked this pull request as ready for review April 15, 2026 05:07
@jasonhernandez jasonhernandez requested a review from a team as a code owner April 15, 2026 05:07
Comment thread src/authenticator/src/oidc.rs Outdated
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch from 2860d6d to 20cc9b2 Compare April 16, 2026 21:23
Implement Zeroize + ZeroizeOnDrop for ValidatedClaims and Zeroize for
OidcClaims so sensitive identity data doesn't linger in memory.

Callers that previously moved out of ValidatedClaims.user now use
std::mem::take to avoid moving out of a ZeroizeOnDrop type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jasonhernandez jasonhernandez force-pushed the jasonhernandez/sec-115-authenticator-zeroize branch from 20cc9b2 to f0c6181 Compare April 16, 2026 21:25
@jasonhernandez jasonhernandez enabled auto-merge (squash) April 16, 2026 21:30
Forgot to commit the Cargo.lock change alongside the zeroize
dependency addition in the previous commit; lint-and-rustfmt and
lint-dependencies failed on the missing line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jasonhernandez added a commit that referenced this pull request Apr 17, 2026
Adds bin/git-hook-pre-push, which runs `cargo metadata --locked
--offline` (~0.5s) when the pushed commits touch any Cargo.toml or
Cargo.lock. If Cargo.lock is out of sync, the push is rejected with an
actionable message instead of a 15-minute CI round-trip.

Motivated by #35704, where a workspace dep was added but Cargo.lock
wasn't committed, failing lint-and-rustfmt (check-no-diff.sh) and
lint-dependencies (cargo tree --locked refused to run).

Install is opt-in per clone:

  ln -sf ../../bin/git-hook-pre-push .git/hooks/pre-push

Bypass with `git push --no-verify` if needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jasonhernandez jasonhernandez merged commit 3d45831 into main Apr 17, 2026
120 checks passed
@jasonhernandez jasonhernandez deleted the jasonhernandez/sec-115-authenticator-zeroize branch April 17, 2026 03:22
def- added a commit to def-/materialize that referenced this pull request Apr 17, 2026
Follow-up to MaterializeInc#35704.

The existing `impl Zeroize for OidcClaims` was dead code in production:
nothing in the runtime path called `.zeroize()` on it, and it did not
implement `ZeroizeOnDrop` or a manual `Drop`. The only caller was the
unit test.

In `validate_token`, `jsonwebtoken::decode::<OidcClaims>` produces a
`TokenData` whose `claims` field holds the full JWT payload including
`unknown_claims` (email, sub, groups, preferred_username, etc.). When
`token_data` drops at the end of the function, none of that is zeroed
— the sensitive data stays in freed heap memory.

Add `impl Drop` that calls `self.zeroize()` and an `unsafe impl
ZeroizeOnDrop` so every `OidcClaims` instance is automatically zeroized
when it goes out of scope. Add a compile-time regression test
(`assert_zod::<OidcClaims>()`) to prevent silent removal of
`ZeroizeOnDrop` in the future.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
def- added a commit to def-/materialize that referenced this pull request Apr 17, 2026
Follow-up to MaterializeInc#35704.

The previous `impl Zeroize for OidcClaims` added `Drop`-based
zeroization, but `unknown_claims` (the field holding the actual
sensitive JWT payload — email, sub, groups, preferred_username) was
only handled with `BTreeMap::clear()`. That drops entries via their
normal destructors without zeroing the backing memory first, so the
sensitive strings remained in freed heap memory.

Replace the `.clear()` call with a `pop_first()` drain loop that
zeroizes each key and recursively walks each `serde_json::Value` via a
new `zeroize_json_value` helper. String leaves are zeroized in-place,
arrays are element-wise zeroized then cleared, and object maps are
drained so owned keys can be zeroized too.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
def- added a commit that referenced this pull request Apr 21, 2026
…36137)

Follow-up to #35704.

The existing `impl Zeroize for OidcClaims` was dead code in production:
nothing in the runtime path called `.zeroize()` on it, and it did not
implement `ZeroizeOnDrop` or a manual `Drop`. The only caller was the
unit test.

In `validate_token`, `jsonwebtoken::decode::<OidcClaims>` produces a
`TokenData` whose `claims` field holds the full JWT payload including
`unknown_claims` (email, sub, groups, preferred_username, etc.). When
`token_data` drops at the end of the function, none of that is zeroed —
the sensitive data stays in freed heap memory.

Add `impl Drop` that calls `self.zeroize()` and an `unsafe impl
ZeroizeOnDrop` so every `OidcClaims` instance is automatically zeroized
when it goes out of scope. Add a compile-time regression test
(`assert_zod::<OidcClaims>()`) to prevent silent removal of
`ZeroizeOnDrop` in the future.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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