security(ui): force POST on credential-bearing auth forms

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 check clean on both adapter crates.
  • curl against the running Dioxus example (:8080) confirms method="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 check only (identical change; its example wasn't running).
  • Formal zap-baseline.py re-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