From 7d9cfc4cd507532e845425bad95d59fa3f0ebd3a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 04:29:59 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20fix=20XSS?= =?UTF-8?q?=20vulnerability=20in=20HTTP=20server=20dashboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed multiple XSS vulnerabilities in the agent's HTTP dashboard by refactoring data structures to use raw strings instead of template.HTML. This allows the Go html/template engine to perform contextual auto-escaping on all user-provided or external data. Key changes: - Refactored Participant, Peer, KnownPeer, IndexData, and KV structs to use raw strings. - Moved HTML rendering logic (badges, links, styling) from Go code into HTML templates. - Registered sanitizeURL and wrapString as template functions for secure and consistent rendering. - Added a security test case to verify that malicious input is properly escaped in the dashboard. This commit has been created by an automated coding assistant, with human supervision. Full prompt used: [The prompt was too long to include here, but it focused on fixing the XSS vulnerability at internal/server/http_server.go:416] Co-authored-by: filmil <246576+filmil@users.noreply.github.com> --- internal/server/grpc_status.go | 14 +-- internal/server/http_server.go | 129 +++++++++++------------- internal/server/http_server_test.go | 58 +++++++++++ internal/server/templates/grpc.html | 2 +- internal/server/templates/index.html | 17 +++- internal/server/templates/messages.html | 12 ++- internal/server/templates/peers.html | 8 +- internal/server/templates/store.html | 2 +- 8 files changed, 155 insertions(+), 87 deletions(-) diff --git a/internal/server/grpc_status.go b/internal/server/grpc_status.go index 7399e6b..6e46ad5 100644 --- a/internal/server/grpc_status.go +++ b/internal/server/grpc_status.go @@ -34,14 +34,14 @@ func (s *HTTPServer) handleGRPC(w http.ResponseWriter, r *http.Request) { members, err := s.store.GetMembers() if err != nil { - data.ErrorMsg = template.HTML("
{{.Key}}%s", html.EscapeString(grpcAddr))
- if info.HTTPURL != "" {
- endpoints += fmt.Sprintf(" | %s", html.EscapeString(sanitizeURL(info.HTTPURL)), html.EscapeString(info.HTTPURL))
- }
data.Peers = append(data.Peers, Peer{
- Label: template.HTML(label),
- AgentID: id,
- Endpoints: template.HTML(endpoints),
+ Name: info.ShortName,
+ IsSelf: id == agentID,
+ AgentID: id,
+ GRPCAddr: grpcAddr,
+ HTTPURL: info.HTTPURL,
})
}
@@ -591,12 +588,6 @@ func (s *HTTPServer) handlePeers(w http.ResponseWriter, r *http.Request) {
}
grpcURL := fmt.Sprintf("grpc://%s", grpcAddr)
- httpLink := ""
- if info.HTTPURL != "" {
- httpLink = fmt.Sprintf("%s", html.EscapeString(sanitizeURL(info.HTTPURL)), html.EscapeString(info.HTTPURL))
- } else {
- httpLink = "N/A"
- }
certPEM := ""
if len(info.Certificate) > 0 {
if cert, err := identity.UnmarshalCertificate(info.Certificate); err == nil {
@@ -605,12 +596,12 @@ func (s *HTTPServer) handlePeers(w http.ResponseWriter, r *http.Request) {
}
data.Peers = append(data.Peers, KnownPeer{
- ID: id,
- Name: info.ShortName,
- GRPCURL: grpcURL,
- HTTPLink: template.HTML(httpLink),
- HasCert: len(info.Certificate) > 0,
- CertPEM: certPEM,
+ ID: id,
+ Name: info.ShortName,
+ GRPCURL: grpcURL,
+ HTTPURL: info.HTTPURL,
+ HasCert: len(info.Certificate) > 0,
+ CertPEM: certPEM,
})
}
@@ -640,7 +631,7 @@ func (s *HTTPServer) handleStore(w http.ResponseWriter, r *http.Request) {
for _, kv := range kvs {
data.KVs = append(data.KVs, KV{
- Key: template.HTML(fmt.Sprintf(`ID: {{.AgentID}}
+ID:
Name: {{.AgentName}}
Keys Count: {{.KeysCount}}
{{.GRPCAddr}}{{.GRPCAddr}}
+ {{if .HTTPURL}}
+ | {{.HTTPURL}}
+ {{end}}
+ {{.ID}}