Fix SAML replay TTL, 2FA backup codes, encryption backfill, and secret rotation grace period - #461
Merged
maugauwi-hash merged 1 commit intoAug 31, 2026
Conversation
…t rotation grace period - saml.rs: bound the assertion replay guard to the assertion's own validity window (NotOnOrAfter + clock skew) instead of retaining consumed IDs forever, so the guard set no longer grows unbounded. - two_factor.rs: add hashed, single-use backup codes for TOTP, consumed atomically under a dedicated lock so concurrent verification attempts can't both redeem the same code. - encryption.rs: add a batched, rate-limited, resumable key-rotation backfill job (run_backfill_batch/run_backfill) and wire a periodic run into the scheduler. - secret_rotation.rs: add max_token_lifetime_hours to rotation policies and reject any grace_period_hours that doesn't exceed it, so a rotation can't invalidate a session/token mid-use. - lib.rs: register the encryption and saml modules, which were never declared and so were silently excluded from the build and test suite. Closes ethos-protocol#388, closes ethos-protocol#389, closes ethos-protocol#390, closes ethos-protocol#391
|
@Idaonoli Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes four related security/reliability gaps, one per file:
backend/src/saml.rs(Add SAML Assertion Replay Prevention #388):validate_assertionalready rejected areused assertion ID, but
consumed_assertionskept every ID forever withno TTL, growing without bound. It's now a map from assertion ID to the
instant after which the guard entry may be purged — the assertion's own
NotOnOrAfterwidened byclock_skew_secs— since an assertion can neverbe replayed successfully once it's outside its own validity window
anyway. Expired entries are purged on each call.
backend/src/two_factor.rs(Implement Two-Factor Backup Code Single-Use Enforcement #389): TOTP 2FA had no backup codes atall. Adds 10 hashed (SHA-256), single-use backup codes generated on
enable and returned once in plaintext. Consumption
(
verify_and_consume_backup_code) is guarded by a dedicated mutex so aread-check-remove-write sequence can't race — two concurrent verification
attempts with the same code can't both succeed.
backend/src/encryption.rs(Add Field Encryption Key Rotation Backfill Job #390):rotate_fieldonly re-encryptedone record at a time, on demand. Adds
run_backfill_batch/run_backfill:a batched, rate-limited, resumable backfill that walks records still on
an old key version and re-encrypts them to
active_version, persisting acursor between batches so an interruption resumes instead of rescanning.
Wired into the scheduler to run hourly.
backend/src/secret_rotation.rs(Implement Secret Rotation Grace Period Overlap Validation #391): rotation policies had no wayto express how long a session/token issued with a secret can live, so a
short
grace_period_hours(e.g.jwt_secret's default 1 hour) couldinvalidate a still-valid session mid-use. Adds
max_token_lifetime_hourstoSecretRotationPolicyandvalidate_grace_period_overlap, enforced on policy upsert and atdefault-seeding time;
jwt_secret's default grace period is now 192hours (comfortably above its ~168h token lifetime) instead of 1 hour.
Also required
backend/src/lib.rsnever declaredpub mod encryption;orpub mod saml;— both files were silently excluded from the crate (andtherefore from
cargo test) despite containing substantial existing logicand tests. Registering them was necessary for this PR's own changes (and
tests) to actually compile and run, and surfaces both modules to the build
for the first time.
Test plan
cargo check --lib --tests— clean (no errors; pre-existingwarnings only)
cargo test --lib— 413 passed, 0 failed, including new tests forSAML replay TTL expiry, backup-code single-use + concurrent-race
regression, backfill batching/resumability/skip-current, and grace
period validation (valid/invalid/equal boundary + all seeded
defaults)
available in this environment)
Docs updated:
docs/saml-sso.md,docs/encrypted-field-storage.md,docs/secret-rotation-policy.md.Closes #388
Closes #389
Closes #390
Closes #391