Summary
Two auth-hygiene issues in the ARI server. Note ARI is not currently served by the CLI (load_ari_conf is #[allow(dead_code)]; no AriServer/HttpListener is spawned in rustisk-cli), so these are latent — worth fixing before ARI is wired into the runtime.
1. Non-constant-time credential comparison
crates/asterisk-ari/src/server.rs:300-319 — AriServer::authenticate:
if user.username == *username && user.password == *password { … } // Basic
…
if user.password == *key { … } // ApiKey
== on the password/API-key strings short-circuits on the first differing byte → the same timing side-channel closed for AMI (PR #123) and SIP (PR #125). Fix: compare with subtle::ConstantTimeEq (already a workspace dep). The username == gate short-circuits password comparison on username match, so also compute both compares unconditionally.
2. Fail-open default credentials
crates/rustisk-cli/src/main.rs:1236-1240 (and the read-error branch at 1256-1260) — when no ari.conf exists, a default user asterisk / asterisk with read_only: false is injected and enabled: true. If ARI is ever served without an explicit config, it comes up with well-known full-access credentials. Fix: do not fabricate a default user; if ARI is enabled with no users configured, disable it (mirror the manager.conf "enabled without users → disable" guard at main.rs:1193-1196).
Recommended
Bundle the constant-time fix + drop-default-user into one PR with tests (wrong password/key rejected across mismatch positions; ARI refuses to enable with no configured users). Low priority until ARI is served, but low-risk and cheap.
Summary
Two auth-hygiene issues in the ARI server. Note ARI is not currently served by the CLI (
load_ari_confis#[allow(dead_code)]; noAriServer/HttpListeneris spawned inrustisk-cli), so these are latent — worth fixing before ARI is wired into the runtime.1. Non-constant-time credential comparison
crates/asterisk-ari/src/server.rs:300-319—AriServer::authenticate:==on the password/API-key strings short-circuits on the first differing byte → the same timing side-channel closed for AMI (PR #123) and SIP (PR #125). Fix: compare withsubtle::ConstantTimeEq(already a workspace dep). Theusername ==gate short-circuits password comparison on username match, so also compute both compares unconditionally.2. Fail-open default credentials
crates/rustisk-cli/src/main.rs:1236-1240(and the read-error branch at 1256-1260) — when noari.confexists, a default userasterisk/asteriskwithread_only: falseis injected andenabled: true. If ARI is ever served without an explicit config, it comes up with well-known full-access credentials. Fix: do not fabricate a default user; if ARI is enabled with no users configured, disable it (mirror themanager.conf"enabled without users → disable" guard atmain.rs:1193-1196).Recommended
Bundle the constant-time fix + drop-default-user into one PR with tests (wrong password/key rejected across mismatch positions; ARI refuses to enable with no configured users). Low priority until ARI is served, but low-risk and cheap.