Fix reachable security issues found in the audit

This commit is contained in:
Ian Gulliver
2026-10-21 18:33:57 -07:00
parent 883fa797d4
commit 24cd47de8b
+30
View File
@@ -112,6 +112,26 @@ func (m *Manager) servePreview(port int) error {
ln.Close()
return err
}
// HTTP previews also arrive through the app's loopback forwards. Reject
// attacker-controlled hostnames before proxying: DNS rebinding makes those
// requests same-origin, so cross-origin protection alone cannot stop them.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
status, err := lc.StatusWithoutPeers(ctx)
if err != nil {
ln.Close()
return fmt.Errorf("get preview hostnames: %w", err)
}
hosts := map[string]bool{}
if status.Self != nil {
name := strings.ToLower(strings.TrimSuffix(status.Self.DNSName, "."))
hosts[name] = true
hosts[strings.SplitN(name, ".", 2)[0]] = true
}
for _, ip := range status.TailscaleIPs {
hosts[ip.String()] = true
}
tracked := &previewListener{Listener: ln, conns: map[net.Conn]bool{}}
m.previewMu.Lock()
m.previewListeners[port] = tracked
@@ -126,6 +146,16 @@ func (m *Manager) servePreview(port int) error {
FlushInterval: -1,
}
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
host := r.Host
if h, _, err := net.SplitHostPort(host); err == nil {
host = h
}
host = strings.ToLower(strings.TrimSuffix(host, "."))
ip := net.ParseIP(host)
if host == "" || !(hosts[host] || host == "localhost" || strings.HasSuffix(host, ".localhost") || (ip != nil && ip.IsLoopback())) {
http.Error(w, "forbidden preview host", http.StatusForbidden)
return
}
who, err := lc.WhoIs(r.Context(), r.RemoteAddr)
if err != nil {
http.Error(w, err.Error(), http.StatusForbidden)