Browse Source

lib/discover: Don't leak relay-tokens to discovery (#8762)

Use an allowlist to send only the `id` query param to the discovery server.
entity0xfe 2 years ago
parent
commit
4558eef446
2 changed files with 41 additions and 0 deletions
  1. 9 0
      lib/discover/global.go
  2. 32 0
      lib/discover/local.go

+ 9 - 0
lib/discover/global.go

@@ -54,6 +54,15 @@ type announcement struct {
 	Addresses []string `json:"addresses"`
 }
 
+func (a announcement) MarshalJSON() ([]byte, error) {
+	type announcementCopy announcement
+
+	a.Addresses = sanitizeRelayAddresses(a.Addresses)
+
+	aCopy := announcementCopy(a)
+	return json.Marshal(aCopy)
+}
+
 type serverOptions struct {
 	insecure   bool   // don't check certificate
 	noAnnounce bool   // don't announce

+ 32 - 0
lib/discover/local.go

@@ -116,6 +116,9 @@ func (c *localClient) announcementPkt(instanceID int64, msg []byte) ([]byte, boo
 	// usable as-is.
 	addrs = filterUnspecifiedLocal(addrs)
 
+	// do not leak relay tokens to discovery
+	addrs = sanitizeRelayAddresses(addrs)
+
 	if len(addrs) == 0 {
 		// Nothing to announce
 		return msg, false
@@ -315,3 +318,32 @@ func filterUnspecifiedLocal(addrs []string) []string {
 	}
 	return filtered
 }
+
+func sanitizeRelayAddresses(addrs []string) []string {
+	filtered := addrs[:0]
+	allowlist := []string{"id"}
+
+	for _, addr := range addrs {
+		u, err := url.Parse(addr)
+		if err != nil {
+			continue
+		}
+
+		if u.Scheme == "relay" {
+			s := url.Values{}
+			q := u.Query()
+
+			for _, w := range allowlist {
+				if q.Has(w) {
+					s.Add(w, q.Get(w))
+				}
+			}
+
+			u.RawQuery = s.Encode()
+			addr = u.String()
+		}
+
+		filtered = append(filtered, addr)
+	}
+	return filtered
+}