fix(lib): add comprehensive XSS protection logic (#905)

Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
Xe Iaso 2025-07-24 11:24:58 -04:00 committed by GitHub
parent 45ff8f526e
commit bb434a3351
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 65 additions and 51 deletions

View file

@ -264,7 +264,7 @@ func (s *Server) checkRules(w http.ResponseWriter, r *http.Request, cr policy.Ch
hash := rule.Hash()
lg.Debug("rule hash", "hash", hash)
s.respondWithStatus(w, r, fmt.Sprintf("%s %s", localizer.T("access_denied"), hash), s.policy.StatusCodes.Deny)
s.respondWithStatus(w, r, fmt.Sprintf("%s %s", localizer.T("access_denied"), hash), "/", s.policy.StatusCodes.Deny)
return true
case config.RuleChallenge:
lg.Debug("challenge requested")
@ -302,7 +302,7 @@ func (s *Server) handleDNSBL(w http.ResponseWriter, r *http.Request, ip string,
localizer.T("dronebl_entry"),
resp.String(),
localizer.T("see_dronebl_lookup"),
ip), s.policy.StatusCodes.Deny)
ip), "/", s.policy.StatusCodes.Deny)
return true
}
}
@ -388,13 +388,16 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) {
redirURL, err := url.ParseRequestURI(redir)
if err != nil {
lg.Error("invalid redirect", "err", err)
s.respondWithError(w, r, localizer.T("invalid_redirect"))
s.respondWithStatus(w, r, localizer.T("invalid_redirect"), "/", http.StatusBadRequest)
return
}
if redirURL.Scheme != "" && redirURL.Scheme != "http" && redirURL.Scheme != "https" {
switch redirURL.Scheme {
case "", "http", "https":
// allowed
default:
lg.Error("XSS attempt blocked, invalid redirect scheme", "scheme", redirURL.Scheme)
s.respondWithStatus(w, r, localizer.T("invalid_redirect"), http.StatusBadRequest)
s.respondWithStatus(w, r, localizer.T("invalid_redirect"), "/", http.StatusBadRequest)
return
}
@ -463,7 +466,7 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) {
case errors.As(err, &cerr):
switch {
case errors.Is(err, challenge.ErrFailed):
s.respondWithStatus(w, r, cerr.PublicReason, cerr.StatusCode)
s.respondWithStatus(w, r, cerr.PublicReason, "/", cerr.StatusCode)
case errors.Is(err, challenge.ErrInvalidFormat), errors.Is(err, challenge.ErrMissingField):
s.respondWithError(w, r, cerr.PublicReason)
}