Release 2.7.3.1: harden proxy recovery, updates and local API.
Restore orphaned system proxy after crash, require update SHA-256, add macOS /api auth token, fix UDP ping false positives, HTTPS-only subscriptions, and keep the UI responsive during connect. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,8 +3,10 @@ package config
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Protocol identifies a VPN/proxy backend.
|
||||
@@ -192,10 +194,47 @@ func (c *Config) Validate() error {
|
||||
default:
|
||||
return fmt.Errorf("config: profile %q: unsupported protocol %q", p.Name, p.Protocol)
|
||||
}
|
||||
for _, listen := range p.Listen {
|
||||
if err := validateListenURI(listen); err != nil {
|
||||
return fmt.Errorf("config: profile %q: %w", p.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateListenURI(uri string) error {
|
||||
uri = strings.TrimSpace(uri)
|
||||
if uri == "" {
|
||||
return nil
|
||||
}
|
||||
var hostPort string
|
||||
var ok bool
|
||||
for _, scheme := range []string{"http", "socks", "socks5", "https"} {
|
||||
if hostPort, ok = parseListenHostPort(uri, scheme); ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
lower := strings.ToLower(uri)
|
||||
if strings.Contains(lower, "127.0.0.1") || strings.Contains(lower, "localhost") || strings.Contains(lower, "[::1]") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("listen %q must bind to loopback", uri)
|
||||
}
|
||||
host, _, err := net.SplitHostPort(hostPort)
|
||||
if err != nil {
|
||||
host = hostPort
|
||||
}
|
||||
host = strings.Trim(host, "[]")
|
||||
switch strings.ToLower(host) {
|
||||
case "127.0.0.1", "localhost", "::1", "":
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("listen host %q is not loopback (only 127.0.0.1 / ::1)", host)
|
||||
}
|
||||
}
|
||||
|
||||
// ActiveProfile returns the selected profile.
|
||||
func (c *Config) ActiveProfile() (*Profile, error) {
|
||||
for i := range c.Profiles {
|
||||
|
||||
@@ -29,6 +29,17 @@ func (c *Config) ListProfiles() []ProfileInfo {
|
||||
return out
|
||||
}
|
||||
|
||||
// RedactProfileList clears Proxy URIs from a profile list (host/protocol remain).
|
||||
// Use for periodic UI polls so credentials are not echoed for every profile.
|
||||
func RedactProfileList(in []ProfileInfo) []ProfileInfo {
|
||||
out := make([]ProfileInfo, len(in))
|
||||
for i, p := range in {
|
||||
out[i] = p
|
||||
out[i].Proxy = ""
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func proxyHost(proxy string) string {
|
||||
proxy = strings.TrimSpace(proxy)
|
||||
if proxy == "" {
|
||||
|
||||
Reference in New Issue
Block a user