security(ui): force POST on credential-bearing auth forms
#11 in tonybierman/arium — merged 2026-05-25
What
Adds method: "post" to the six credential-bearing auth forms across both adapters:
- arium-dioxus:
login_panel,forgot_password,reset_password - arium-leptos:
login_panel,forgot_password,reset_password
Why
The forms intercept submit with prevent_default() and dispatch through a server-fn (POST), so the live hydrated flow never puts credentials in the URL. But the <form> elements carried no method attribute, so HTML defaulted them to method=GET against the current URL.
Any path that doesn't run the WASM handler — JS disabled, the brief pre-hydration window, or a scanner's native form submit — degraded to a GET that wrote the typed email/password into the query string (→ server access logs, browser history, Referer).
This is the root cause of ZAP baseline finding 10024 (credentials in login URL — board #4, card #48): the spider submitted the method-less form natively and the params landed in /?email=…&password=….
The fix is inert in the live path (prevent_default still wins); in the degraded path the native submit is now a POST, keeping credentials out of the URL. MFA / token / audit / account forms are intentionally untouched (no URL-leakable secret).
Verification
cargo checkclean on both adapter crates.curlagainst the running Dioxus example (:8080) confirmsmethod="post"now renders in the SSR markup for/,/auth/forgot, and/auth/reset(the attribute was absent before this change).- arium-leptos twin verified by
cargo checkonly (identical change; its example wasn't running). - Formal
zap-baseline.pyre-run not executed — the fix is correct by HTML spec and the curl markup check covers it.
🤖 Generated with Claude Code
Last updated 2026-05-26
Links to this note
Merged pull requests, newest first.