fix(server::bootsrapper): token compare is now constant-time
Some checks failed
ci/woodpecker/push/server-audit Pipeline was successful
ci/woodpecker/push/server-vet Pipeline failed
ci/woodpecker/push/server-lint Pipeline failed
ci/woodpecker/push/server-test Pipeline was successful

This commit is contained in:
hdbg
2026-04-06 18:27:46 +02:00
parent b3464cf8a6
commit 1497884ce6
3 changed files with 17 additions and 8 deletions

1
server/Cargo.lock generated
View File

@@ -760,6 +760,7 @@ dependencies = [
"smlang",
"spki",
"strum 0.28.0",
"subtle",
"test-log",
"thiserror 2.0.18",
"tokio",

View File

@@ -60,6 +60,7 @@ arbiter-tokens-registry.path = "../arbiter-tokens-registry"
anyhow = "1.0.102"
serde_with = "3.18.0"
mutants.workspace = true
subtle = "2.6.1"
[dev-dependencies]
insta = "1.46.3"

View File

@@ -4,6 +4,7 @@ use diesel_async::RunQueryDsl;
use kameo::{Actor, messages};
use rand::{RngExt, distr::Alphanumeric, make_rng, rngs::StdRng};
use subtle::ConstantTimeEq as _;
use thiserror::Error;
use crate::db::{self, DatabasePool, schema};
@@ -44,14 +45,14 @@ pub struct Bootstrapper {
impl Bootstrapper {
pub async fn new(db: &DatabasePool) -> Result<Self, Error> {
let mut conn = db.get().await?;
let row_count: i64 = {
let mut conn = db.get().await?;
let row_count: i64 = schema::useragent_client::table
.count()
.get_result(&mut conn)
.await?;
drop(conn);
schema::useragent_client::table
.count()
.get_result(&mut conn)
.await?
};
let token = if row_count == 0 {
let token = generate_token().await?;
@@ -69,7 +70,13 @@ impl Bootstrapper {
#[message]
pub fn is_correct_token(&self, token: String) -> bool {
match &self.token {
Some(expected) => *expected == token,
Some(expected) => {
let expected_bytes = expected.as_bytes();
let token_bytes = token.as_bytes();
let choice = expected_bytes.ct_eq(token_bytes);
bool::from(choice)
}
None => false,
}
}