mirror of
https://github.com/dsec-hub/dsec-discord-bot.git
synced 2026-09-22 15:53:56 +00:00
Address adversarial-review findings on the verify path: - Already-linked caller bypass (HIGH): add_dsec_discord_table no longer early-returns Linked on any existing row. It now checks the SUBMITTED id's owner first (idempotent only when that owner is the caller) and refuses a caller already linked to a DIFFERENT student id -- closing the path where a stale COR-03 partial-insert row let an account claim someone else's id. - Check-then-insert race (HIGH): the insert now catches a UNIQUE(student_id) violation (SQLSTATE 23505), re-queries the owner and converts it to the generic refusal + audit. SECURITY.md now marks the live UNIQUE constraint (after the dup sweep) as a merge/deploy gate, not optional. - PII leak in error prints (HIGH): raw supabase/reqwest errors (which embed student_id=eq.<id> and a 23505 Key detail) are never printed on the verify path. New redact_digits() masks 7+ digit runs; the interaction id is used as an opaque correlation ref. student_id_owner now selects only discord_id. - Concurrent-attempt rate-limit bypass (HIGH): a per-UserId tokio Mutex (AppState. verify_locks) serializes a whole verification attempt so concurrent modal submits cannot each slip under the 5-in-15min limit. Requires tokio "sync" feature. - Ownership conflict never counted (MED): a refused link now records exactly one failed attempt (success/infra-error record none), so a stolen-but-claimed credential can no longer loop the query set forever. - Expired-interaction mutate-then-skip (MED): defer_ephemeral is now sent the instant the modal arrives, before any DB/logs work; every later reply edits the deferred response. - Log oracle (MED): the failed-attempt audit line is one fixed generic string, so "not found" vs "name mismatch" are indistinguishable in the logs channel too. Also: on_error no longer forwards a handled FrameworkError::Command to poise's builtin (whose Command arm does a non-ephemeral ctx.say(raw_error), leaking DB error text); mutex locks recover from poisoning instead of panicking; and the attempt/lock maps evict stale/idle entries so they cannot grow unbounded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017XrE7F9ZuBWdQnS8CZvYDE
15 lines
No EOL
369 B
TOML
15 lines
No EOL
369 B
TOML
[package]
|
|
name = "dsec_bot"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
|
|
[dependencies]
|
|
dotenv = "0.15.0"
|
|
poise = "0.6.1"
|
|
reqwest = "0.12.24"
|
|
serde_json = "1.0.145"
|
|
serenity = "0.12"
|
|
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread", "sync"] }
|
|
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
|
|
supabase-lib-rs = "0.5.3"
|
|
serde = "1.0.228" |