mavweb: gate /api/revert behind passkey step-up
RevertFact voids the latest fact for a key — a store mutation — but /api/revert had no step-up gate, while POST /tools required L3. Close the inconsistency: thread the same *webauthn.PasskeySession into handleRevert and reject with 403 when a configured session isn't asserted. nil session (WebAuthn unconfigured) keeps prior behavior — transport-level auth only. Tests: un-asserted session → 403 and RevertFact not called; asserted → 200. The RevertFact mock now records its key so the gate assertion is meaningful. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-4
@@ -158,9 +158,6 @@ func main() {
|
||||
mux.HandleFunc("/notifications", func(w http.ResponseWriter, r *http.Request) {
|
||||
handleNotifications(w, r, core)
|
||||
})
|
||||
mux.HandleFunc("/api/revert", func(w http.ResponseWriter, r *http.Request) {
|
||||
handleRevert(w, r, core)
|
||||
})
|
||||
// ----- passkey (WebAuthn) endpoints -----
|
||||
// Wired when both -core and a configured origin are present. The origin
|
||||
// must match the browser's view of mavweb (e.g. https://maven.kvmx.ru).
|
||||
@@ -199,6 +196,13 @@ func main() {
|
||||
handleTools(w, r, core, stepUpSession)
|
||||
})
|
||||
|
||||
// /api/revert voids the latest fact for a key — a store mutation, so it
|
||||
// sits behind the same passkey step-up as tool enable (nil session ⇒
|
||||
// WebAuthn unconfigured ⇒ transport-level auth only, same as /tools).
|
||||
mux.HandleFunc("/api/revert", func(w http.ResponseWriter, r *http.Request) {
|
||||
handleRevert(w, r, core, stepUpSession)
|
||||
})
|
||||
|
||||
srv := &http.Server{Addr: *addr, Handler: mux}
|
||||
|
||||
go func() {
|
||||
@@ -485,7 +489,7 @@ func handleTrace(w http.ResponseWriter, r *http.Request, core ipc.CoreAPI) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleRevert(w http.ResponseWriter, r *http.Request, core ipc.CoreAPI) {
|
||||
func handleRevert(w http.ResponseWriter, r *http.Request, core ipc.CoreAPI, session *webauthn.PasskeySession) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "POST only", http.StatusMethodNotAllowed)
|
||||
return
|
||||
@@ -494,6 +498,12 @@ func handleRevert(w http.ResponseWriter, r *http.Request, core ipc.CoreAPI) {
|
||||
http.Error(w, "revert disabled (no -core)", http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
// nil session ⇒ WebAuthn not configured; step-up gate not applicable
|
||||
// (asserting would be impossible, not just unmet) — matches handleTools.
|
||||
if session != nil && !session.IsStepUp() {
|
||||
http.Error(w, "step-up required: assert a passkey first", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
key := strings.TrimSpace(r.FormValue("key"))
|
||||
if key == "" {
|
||||
http.Error(w, "key required", http.StatusBadRequest)
|
||||
|
||||
Reference in New Issue
Block a user