diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index cde9d341c..1ba66531a 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -6,6 +6,7 @@ package cli import ( + "bytes" "context" "encoding/json" "errors" @@ -14,7 +15,6 @@ "io" "log" "os" - "regexp" "runtime" "strings" "sync" @@ -582,11 +582,32 @@ type sanitizeWriter struct { w io.Writer } -var rxTskey = regexp.MustCompile(`tskey-[\w-]+`) - +// Write logically replaces /tskey-[A-Za-z0-9-]+/ with /tskey-XXXX.../ in buf +// before writing to the underlying writer. +// +// We avoid the "regexp" package to not bloat the minbox build, and without +// making this a featuretag-omittable protection. func (w sanitizeWriter) Write(buf []byte) (int, error) { - sanitized := rxTskey.ReplaceAll(buf, []byte("tskey-REDACTED")) - diff := len(sanitized) - len(buf) - n, err := w.w.Write(sanitized) - return n - diff, err + const prefix = "tskey-" + scrub := buf + for { + i := bytes.Index(scrub, []byte(prefix)) + if i == -1 { + break + } + scrub = scrub[i+len(prefix):] + + for i, b := range scrub { + if (b >= 'a' && b <= 'z') || + (b >= 'A' && b <= 'Z') || + (b >= '0' && b <= '9') || + b == '-' { + scrub[i] = 'X' + } else { + break + } + } + } + + return w.w.Write(buf) } diff --git a/cmd/tailscale/cli/cli_test.go b/cmd/tailscale/cli/cli_test.go index ac6a94d52..537e641fc 100644 --- a/cmd/tailscale/cli/cli_test.go +++ b/cmd/tailscale/cli/cli_test.go @@ -1804,8 +1804,8 @@ func TestSanitizeWriter(t *testing.T) { buf := new(bytes.Buffer) w := sanitizeOutput(buf) - in := []byte(`my auth key is tskey-auth-abc123-def456, what's yours?`) - want := []byte(`my auth key is tskey-REDACTED, what's yours?`) + in := []byte(`my auth key is tskey-auth-abc123-def456 and tskey-foo, what's yours?`) + want := []byte(`my auth key is tskey-XXXXXXXXXXXXXXXXXX and tskey-XXX, what's yours?`) n, err := w.Write(in) if err != nil { t.Fatal(err) diff --git a/cmd/tailscaled/depaware-minbox.txt b/cmd/tailscaled/depaware-minbox.txt index 41bf4d984..f087e6809 100644 --- a/cmd/tailscaled/depaware-minbox.txt +++ b/cmd/tailscaled/depaware-minbox.txt @@ -420,8 +420,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de path from io/fs+ path/filepath from crypto/x509+ reflect from crypto/x509+ - regexp from tailscale.com/cmd/tailscale/cli - regexp/syntax from regexp runtime from crypto/internal/fips140+ runtime/debug from github.com/klauspost/compress/zstd+ slices from crypto/tls+ diff --git a/cmd/tailscaled/deps_test.go b/cmd/tailscaled/deps_test.go index 118913848..596985043 100644 --- a/cmd/tailscaled/deps_test.go +++ b/cmd/tailscaled/deps_test.go @@ -294,6 +294,7 @@ func TestMinTailscaledWithCLI(t *testing.T) { "tailscale.com/clientupdate/distsign": "unexpected distsign dep", "archive/tar": "unexpected archive/tar dep", "tailscale.com/feature/conn25": "unexpected conn25 dep", + "regexp": "unexpected regexp dep; bloats binary", }, }.Check(t) }