From f8654408d65cc9dd839df9589d7d01c1af9d51f0 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Thu, 15 Feb 2024 08:13:43 -0500 Subject: [PATCH] go/build: add check for allowed vendor packages Add a test that checks that all vendored packages in both src/ and src/cmd are on an allowlist. For #65678. Change-Id: Ie9982f8b69c9c0fc6fef41c9dadeb464ecd7781a Reviewed-on: https://go-review.googlesource.com/c/go/+/564355 Reviewed-by: Bryan Mills LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov --- src/go/build/vendor_test.go | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/go/build/vendor_test.go diff --git a/src/go/build/vendor_test.go b/src/go/build/vendor_test.go new file mode 100644 index 00000000000..7f6237ffd59 --- /dev/null +++ b/src/go/build/vendor_test.go @@ -0,0 +1,79 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package build + +import ( + "internal/testenv" + "runtime" + "strings" + "testing" +) + +// Prefixes for packages that can be vendored into the go repo. +// The prefixes are component-wise; for example, "golang.org/x" +// matches "golang.org/x/build" but not "golang.org/xyz". +// +// DO NOT ADD TO THIS LIST TO FIX BUILDS. +// Vendoring a new package requires prior discussion. +var allowedPackagePrefixes = []string{ + "golang.org/x", + "github.com/google/pprof", + "github.com/ianlancetaylor/demangle", + "rsc.io/markdown", +} + +// Verify that the vendor directories contain only packages matching the list above. +func TestVendorPackages(t *testing.T) { + _, thisFile, _, _ := runtime.Caller(0) + goBin := testenv.GoToolPath(t) + listCmd := testenv.Command(t, goBin, "list", "std", "cmd") + out, err := listCmd.Output() + if err != nil { + t.Fatal(err) + } + for _, fullPkg := range strings.Split(string(out), "\n") { + pkg, found := strings.CutPrefix(fullPkg, "vendor/") + if !found { + _, pkg, found = strings.Cut(fullPkg, "/vendor/") + if !found { + continue + } + } + if !isAllowed(pkg) { + t.Errorf(` + Package %q should not be vendored into this repo. + After getting approval from the Go team, add it to allowedPackagePrefixes + in %s.`, + pkg, thisFile) + } + } +} + +func isAllowed(pkg string) bool { + for _, pre := range allowedPackagePrefixes { + if pkg == pre || strings.HasPrefix(pkg, pre+"/") { + return true + } + } + return false +} + +func TestIsAllowed(t *testing.T) { + for _, test := range []struct { + in string + want bool + }{ + {"evil.com/bad", false}, + {"golang.org/x/build", true}, + {"rsc.io/markdown", true}, + {"rsc.io/markdowntonabbey", false}, + {"rsc.io/markdown/sub", true}, + } { + got := isAllowed(test.in) + if got != test.want { + t.Errorf("%q: got %t, want %t", test.in, got, test.want) + } + } +}