Skip to content

refactor(rivetkit-core): use subtle::ConstantTimeEq for inspector token verify#4730

Closed
NathanFlurry wants to merge 1 commit into04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rowsfrom
04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify
Closed

refactor(rivetkit-core): use subtle::ConstantTimeEq for inspector token verify#4730
NathanFlurry wants to merge 1 commit into04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rowsfrom
04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify

Conversation

@NathanFlurry
Copy link
Copy Markdown
Member

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Copy link
Copy Markdown
Member Author

NathanFlurry commented Apr 24, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from d26d955 to 1c8fb57 Compare April 24, 2026 09:52
@NathanFlurry NathanFlurry mentioned this pull request Apr 24, 2026
11 tasks
@claude
Copy link
Copy Markdown

claude Bot commented Apr 24, 2026

Code Review: refactor(rivetkit-core): use subtle::ConstantTimeEq for inspector token verify

Overview

This PR replaces the hand-rolled timing_safe_equal function with the battle-tested subtle::ConstantTimeEq trait. Small but meaningful security improvement.


What the PR Does

  • Removes the custom timing_safe_equal implementation in inspector/auth.rs
  • Adds subtle as a workspace dependency in rivetkit-core
  • Uses ct_eq(...).into() from subtle::ConstantTimeEq directly on byte slices

Analysis

Security — Correct Direction

The custom timing_safe_equal was a reasonable attempt, but hand-rolled constant-time comparisons are notoriously fragile. Compilers and CPUs can optimize them in unexpected ways (short-circuit evaluation, instruction reordering, etc.). The subtle crate is specifically designed to resist these optimizations and is widely used in the Rust cryptography ecosystem. This is the right choice.

Behavior Change — Important Nuance

The old timing_safe_equal padded both slices to max_len before comparing, meaning mismatched lengths still XOR through all bytes. subtle::ConstantTimeEq for [u8] short-circuits to false immediately if lengths differ (the default trait impl checks self.len() == other.len() first). This is technically a length leak — an attacker could learn the expected token length by timing the response.

In this specific context, the token is always generated as a fixed-length base64 string from generate_inspector_token() (specifically TOKEN_LENGTH bytes encoded with URL_SAFE_NO_PAD). Since the expected token is always the same fixed length, the length leak is not exploitable in practice. Still worth documenting.

Dependency — Already a Workspace Dep

subtle = "2" is already declared in the root Cargo.toml workspace dependencies, so adding it to rivetkit-core is clean with no version churn.

Code Quality

The diff is minimal and correct. The import is added, the call site is clean (candidate.ct_eq(expected).into()), and the hand-rolled function is fully removed with no leftover dead code.


Suggestions

  1. Minor: Add a one-line comment near verify_token_bytes noting that the token is always fixed-length (TOKEN_LENGTH bytes base64-encoded), so future maintainers understand why ct_eq (which leaks length on mismatch) is acceptable here.

  2. Optional: Fill out the PR description checklist before merging.


Summary

Good, focused security improvement. Replacing a hand-rolled constant-time comparison with the audited subtle crate is clearly correct. The one nuance (length-leak behavior of ct_eq vs. the old padding approach) is not exploitable given fixed-length tokens. Clean diff, correct dependency wiring.

@NathanFlurry NathanFlurry force-pushed the 04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rows branch from a512a8f to b3d5c95 Compare April 24, 2026 10:19
@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from 1c8fb57 to 7377471 Compare April 24, 2026 10:19
@NathanFlurry NathanFlurry force-pushed the 04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rows branch from b3d5c95 to 95ff109 Compare April 24, 2026 10:32
@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from 7377471 to 6b8454a Compare April 24, 2026 10:32
@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from 6b8454a to 4026613 Compare April 24, 2026 11:48
@NathanFlurry NathanFlurry force-pushed the 04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rows branch from 95ff109 to 14947c2 Compare April 24, 2026 11:48
@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from 4026613 to bef6550 Compare April 24, 2026 12:14
@NathanFlurry NathanFlurry force-pushed the 04-23-fix_rivetkit_drop_is_read_only_sql_classifier_surface_returning_rows branch from 048de9b to d47c579 Compare April 24, 2026 12:32
@NathanFlurry NathanFlurry force-pushed the 04-23-refactor_rivetkit-core_use_subtle_constanttimeeq_for_inspector_token_verify branch from bef6550 to 9189e26 Compare April 24, 2026 12:32
@NathanFlurry
Copy link
Copy Markdown
Member Author

Landed in main via stack-merge fast-forward push. Commits are in main; closing to match.

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.

1 participant