Phase 2 #4
No reviewers
Labels
No labels
bug
dependencies
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
rust
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
navicore/anz!4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "phase-2"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 2 Review
Good, solid work — rate limiting, audit logging, branding, session management, and RFC 7009 revocation are all implemented cleanly. The 53-test suite is a major improvement over Phase 1. A few things worth looking at:
Security
custom_cssis HTML-escaped by Askama (templates/login.html)Askama escapes
{{ }}variables as HTML by default, so characters like<,>,&in the CSS value will be rendered as<,>, etc. This means CSS containing those characters (e.g.content: "<", attribute selectors) will be silently broken. Since this is operator-controlled config, the fix is to render it raw with{{ css | safe }}and accept that only the operator can set it. The current behaviour is confusing — it looks like it works but quietly corrupts valid CSS.validate_aud = falseinsrc/crypto/token.rsThis was added without a comment. For a JWT library that validates claims, silently disabling audience validation is a non-obvious security trade-off. Even if it's intentional (public clients, no fixed audience), a comment explaining the reasoning would help the next reader avoid re-adding it by mistake.
Rate limiter map grows unbounded (
src/server/mod.rs)login_attempts: HashMap<IpAddr, Vec<Instant>>accumulates one entry per unique source IP and is never cleaned up.retainprunes old timestamps for the IP being checked, but entries for IPs that never check again stay forever. On a reachable server this could slowly consume memory. A simple fix: afterretain, remove the entry if it becomes empty:revoke.rs— no client authenticationRFC 7009 §2.1 says requests SHOULD include client credentials. The current implementation accepts revocations from anyone with knowledge of a valid refresh token. For public-client-only deployments this is acceptable, but it should be called out as a documented gap (it isn't listed in ROADMAP.md's Known Gaps).
Code Quality
branding_titleused as submit button text (templates/login.html)Before this change the button said "Sign In". Now if
titleis set to "Acme Corp", the submit button reads "Acme Corp". The title was designed for the<h1>heading — the button should probably stay "Sign In" or get its ownbutton_labelconfig field.hex_encodeallocates per byte (src/crypto/mod.rs)format!allocates aStringper byte. At SHA-256 output size (32 bytes) this is 32 small heap allocations. It works fine at this scale, but the idiomatic Rust approach avoids the allocations:Duplicate realm+user lookup in
src/cli/session.rsThe
ListandRevokearms both do identical realm-then-user lookups. Not a bug, but if a third session subcommand is added it becomes a maintenance burden. A small helper function would help.Test Coverage
These new modules have no tests:
src/server/static_files.rs— path traversal protection is security-critical; worth at least a test that attempts../traversal and gets 400/404src/server/revoke.rs— the core RFC 7009 logic (unknown token → 200, valid token → 200 + revoked, access_token hint → no-op) is untestedsrc/cli/session.rshandler — the list/revoke/cleanup dispatch is untestedThe existing test for
static_filesis implicit (relies on canonicalize returning NOT_FOUND for nonexistent paths). An explicit traversal test would be more trustworthy.Minor Notes
audit_log_enableddefaults totrue, writingaudit.login the current working directory on first run without config. This is surprising and could fail silently if the CWD is not writable (it does log a warning). Consider defaulting tofalseand letting operators opt in.#[cfg(test)] pub fn open_in_memory()helper insrc/db/mod.rsis a clean pattern — good call exposing it there rather than duplicating setup in each test module.Overall this is well-structured code with good separation of concerns, idiomatic Rust error handling, and solid coverage of the core cryptographic and DB paths. The issues above are mostly minor polish items — the main ones worth acting on are the
custom_cssescaping bug, the rate limiter memory growth, and the missing traversal test forstatic_files.