adminui: the enrolment link was rendered as a dead anchor
html/template rewrites an href whose scheme it does not recognise to "#ZgotmplZ". echolot:// is not on its list, so "Open in the Echolot app" was not a link at all — tapping it did nothing, and nothing showed it: the markup reads correctly, the app resolves the scheme, and only the sanitised attribute in the served HTML gives it away. Marking the value template.URL opts out of that sanitising, which is only safe because the shape is now checked first. The link arrives in a query parameter, so without the check a crafted /devices?link=javascript:… would put a script URL into the page for an admin to click. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f6e093944c
commit
33799b8135
@@ -5,10 +5,12 @@ package adminui
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"echo-lot.app/server/internal/adminauth"
|
||||
@@ -122,9 +124,21 @@ func (s *Server) devices(w http.ResponseWriter, r *http.Request, sess *adminauth
|
||||
}
|
||||
rows = append(rows, row{Device: d, Runs: n})
|
||||
}
|
||||
// html/template rewrites an href whose scheme it does not recognise to "#ZgotmplZ", so the
|
||||
// enrollment link rendered as a dead anchor that did nothing when tapped — silently, since the
|
||||
// markup looks fine and only the sanitised attribute gives it away.
|
||||
//
|
||||
// Marking it template.URL opts out of that sanitising, which is only safe because the shape is
|
||||
// checked first: this value arrives in a query parameter, so without the check a crafted
|
||||
// /devices?link=javascript:… would put a script URL straight into the page.
|
||||
link := r.URL.Query().Get("link")
|
||||
var href template.URL
|
||||
if strings.HasPrefix(link, "echolot://enroll?") {
|
||||
href = template.URL(link)
|
||||
}
|
||||
s.render(w, r, "devices", map[string]any{
|
||||
"Session": sess, "CSRF": s.csrfToken(sess), "Rows": rows,
|
||||
"Link": r.URL.Query().Get("link"), "Admin": sess.Admin,
|
||||
"Link": link, "LinkHref": href, "Admin": sess.Admin,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user