Repository navigation
Admin token comparison not constant-time #560
Description
The admin token comparison in dstack/kms/src/main_service.rs uses a standard byte-equality check rather than a constant-time comparison, leaking information about the token's value through response timing differences.
Root Cause
The KMS admin token verification uses a standard != comparison on hash bytes:
// main_service.rs:139-144
if provided_hash != expected_hash {
return Err(Error::Unauthorized);
}Standard byte comparison short-circuits on the first non-matching byte, creating a timing side-channel. An attacker can measure response times to determine how many leading bytes of the hash match, progressively recovering the admin token hash byte-by-byte.
Attack Path
- Attacker has network access to the KMS admin endpoint
- Attacker sends requests with different admin token values
- Attacker measures response times — longer times indicate more matching prefix bytes
- By iterating through possible byte values and observing timing differences, attacker recovers the admin token hash
- Attacker can now authenticate as admin and access all admin endpoints (including
remove_cachewith path traversal, a related finding)
Impact
The admin token can be recovered through timing analysis. While this requires many requests and precise timing measurements, it is a well-understood attack against non-constant-time comparisons. Compromising the admin token gives access to all admin endpoints.
Suggested Fix
Use constant-time comparison:
use subtle::ConstantTimeEq;
if !bool::from(provided_hash.ct_eq(&expected_hash)) {
return Err(Error::Unauthorized);
}The subtle crate provides constant-time operations specifically designed to prevent timing side-channels. ConstantTimeEq::ct_eq returns a Choice type; use bool::from() to convert it.
Note: This issue was created automatically. The vulnerability report was generated by Claude and has not been verified by a human.
Activity
kvinwang commentedon Mar 25, 2026
Thanks for reporting this.
We reviewed the admin token verification in
kms/src/main_service.rs. The service does not compare the raw admin token string; instead it computes a SHA-256 digest of the presented token and compares that digest against the configuredadmin_token_hash.This means any timing differences in the equality check apply only to the 256-bit hash value, not to the original secret token. Given that the admin token is intended to be a high-entropy random value and only its hash is stored, learning partial information about the digest via timing does not provide a practical way to recover or brute-force the underlying token.
Because of this, we do not consider the current implementation to introduce a meaningful side-channel for admin token compromise, and we do not plan to change this comparison at the moment. If we ever change the format (for example, truncate the hash or store lower-entropy values), we will revisit this and switch to an explicit constant-time comparison helper.
h4x3rotab commentedon Jun 30, 2026
Maintainer triage update: this is recorded in the public security report table: https://github.com/Dstack-TEE/dstack/blob/master/docs/security/public-security-reports.md#public-reports-and-findings
Disposition: not a production vulnerability. The comparison is over a SHA-256 digest of a high-entropy token, not the raw token. No code fix is planned for this report under the documented production threat model.
Closing as not planned.