ipn: reject advertised routes with non-address bits set (#18649)

* ipn: reject advertised routes with non-address bits set

The config file path, EditPrefs local API, and App Connector API were
accepting invalid subnet route prefixes with non-address bits set (e.g.,
2a01:4f9:c010:c015::1/64 instead of 2a01:4f9:c010:c015::/64). All three
paths now reject prefixes where prefix != prefix.Masked() with an error
message indicating the expected masked form.

Updates tailscale/corp#36738

Signed-off-by: Brendan Creane <bcreane@gmail.com>

* address review comments

Signed-off-by: Brendan Creane <bcreane@gmail.com>

---------

Signed-off-by: Brendan Creane <bcreane@gmail.com>
This commit is contained in:
Brendan Creane
2026-03-20 10:10:43 -07:00
committed by GitHub
parent 79f71beb24
commit ffa7df2789
4 changed files with 198 additions and 0 deletions
+11
View File
@@ -4,6 +4,8 @@
package ipn
import (
"errors"
"fmt"
"net/netip"
"tailscale.com/tailcfg"
@@ -101,6 +103,15 @@ func (c *ConfigVAlpha) ToPrefs() (MaskedPrefs, error) {
mp.ExitNodeAllowLANAccessSet = true
}
if c.AdvertiseRoutes != nil {
var routeErrs []error
for _, route := range c.AdvertiseRoutes {
if route != route.Masked() {
routeErrs = append(routeErrs, fmt.Errorf("route %s has non-address bits set; expected %s", route, route.Masked()))
}
}
if err := errors.Join(routeErrs...); err != nil {
return mp, err
}
mp.AdvertiseRoutes = c.AdvertiseRoutes
mp.AdvertiseRoutesSet = true
}