fix(dashboard): DataTables queries count as reads for read-only API keys

POST /api/tables/... only reads, so read-only keys may use it (and the
API docs list it for them). Keys limited to some addresses can't open
the WebSocket, whose address isn't checked, nor keys whose allowed
paths leave out /ws. Refusals are audited without an account target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 08:51:53 -05:00
parent 3f2a9cc5b0
commit 974a27329e
6 changed files with 20 additions and 12 deletions

View File

@@ -206,6 +206,9 @@ namespace ApiKeyService {
std::lock_guard lock(state.mutex);
const auto& cached = Lookup(state, DashboardAuthService::Sha256Hex(token));
if (!cached.key) return std::nullopt;
// The WebSocket doesn't tell us the address, so a key limited to some addresses can't use it; one limited to
// some paths only if /ws is one of them
if (!cached.allowedIps.empty() || !ApiKeys::PathAllowed(cached.allowedPaths, "/ws")) return std::nullopt;
const auto owner = CheckKeyAndOwner(*cached.key);
if (!owner) return std::nullopt;
return Verified{ cached.key->accountId, owner->username, owner->gmLevel,