vulndb: delete

Delete the vulndb module. Users should now use
golang.org/x/vuln/cmd/govulncheck.

Change-Id: Ia592a36f410fd7aef35a45b077cb2cbbf4bec38c
Reviewed-on: https://go-review.googlesource.com/c/exp/+/395534
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Trust: Julie Qiu <julie@golang.org>
diff --git a/vulndb/go.mod b/vulndb/go.mod
deleted file mode 100644
index 4c7d6fc..0000000
--- a/vulndb/go.mod
+++ /dev/null
@@ -1,15 +0,0 @@
-// Deprecated: use golang.org/x/vuln instead.
-module golang.org/x/exp/vulndb
-
-go 1.17
-
-require (
-	golang.org/x/tools v0.0.0-20210910171127-a568412ca0e6
-	golang.org/x/vuln v0.0.0-20211109030331-63d5d8171d01
-)
-
-require (
-	golang.org/x/mod v0.5.0 // indirect
-	golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
-	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
-)
diff --git a/vulndb/go.sum b/vulndb/go.sum
deleted file mode 100644
index db8f9cf..0000000
--- a/vulndb/go.sum
+++ /dev/null
@@ -1,102 +0,0 @@
-github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
-github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
-github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
-github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
-github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
-github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
-github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
-github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
-github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
-github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
-github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
-github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
-golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20210910171127-a568412ca0e6 h1:O8E8PvYQ1HtZae5hPC9lyLiVuGlqL50yMQW7Y6oRaXQ=
-golang.org/x/tools v0.0.0-20210910171127-a568412ca0e6/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM=
-golang.org/x/vuln v0.0.0-20211109030331-63d5d8171d01 h1:aohfMrFbzRmVFllsufGifzVZzGJHuCrdmXA88J2FX9Q=
-golang.org/x/vuln v0.0.0-20211109030331-63d5d8171d01/go.mod h1:vGjwvr4zd0JNGaeuScTP00A/lDhN8Ao3GFprqIUiIcM=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/vulndb/govulncheck/cache.go b/vulndb/govulncheck/cache.go
deleted file mode 100644
index d0295a7..0000000
--- a/vulndb/govulncheck/cache.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2021 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 main
-
-import (
-	"encoding/json"
-	"go/build"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"time"
-
-	"golang.org/x/vuln/osv"
-)
-
-// NOTE: this cache implementation should be kept internal to the go tooling
-// (i.e. cmd/go/internal/something) so that the vulndb cache is owned by the
-// go command. Also it is currently NOT CONCURRENCY SAFE since it does not
-// implement file locking. If ported to the stdlib it should use
-// cmd/go/internal/lockedfile.
-
-// The cache uses a single JSON index file for each vulnerability database
-// which contains the map from packages to the time the last
-// vulnerability for that package was added/modified and the time that
-// the index was retrieved from the vulnerability database. The JSON
-// format is as follows:
-//
-// $GOPATH/pkg/mod/cache/download/vulndb/{db hostname}/indexes/index.json
-//   {
-//       Retrieved time.Time
-//       Index osv.DBIndex
-//   }
-//
-// Each package also has a JSON file which contains the array of vulnerability
-// entries for the package. The JSON format is as follows:
-//
-// $GOPATH/pkg/mod/cache/download/vulndb/{db hostname}/{import path}/vulns.json
-//   []*osv.Entry
-
-// fsCache is file-system cache implementing osv.Cache
-// TODO: make cache thread-safe
-type fsCache struct {
-	rootDir string
-}
-
-// use cfg.GOMODCACHE available in cmd/go/internal?
-var defaultCacheRoot = filepath.Join(build.Default.GOPATH, "/pkg/mod/cache/download/vulndb")
-
-func defaultCache() *fsCache {
-	return &fsCache{rootDir: defaultCacheRoot}
-}
-
-type cachedIndex struct {
-	Retrieved time.Time
-	Index     osv.DBIndex
-}
-
-func (c *fsCache) ReadIndex(dbName string) (osv.DBIndex, time.Time, error) {
-	b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
-	if err != nil {
-		if os.IsNotExist(err) {
-			return nil, time.Time{}, nil
-		}
-		return nil, time.Time{}, err
-	}
-	var index cachedIndex
-	if err := json.Unmarshal(b, &index); err != nil {
-		return nil, time.Time{}, err
-	}
-	return index.Index, index.Retrieved, nil
-}
-
-func (c *fsCache) WriteIndex(dbName string, index osv.DBIndex, retrieved time.Time) error {
-	path := filepath.Join(c.rootDir, dbName)
-	if err := os.MkdirAll(path, 0755); err != nil {
-		return err
-	}
-	j, err := json.Marshal(cachedIndex{
-		Index:     index,
-		Retrieved: retrieved,
-	})
-	if err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (c *fsCache) ReadEntries(dbName string, p string) ([]*osv.Entry, error) {
-	b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, p, "vulns.json"))
-	if err != nil {
-		if os.IsNotExist(err) {
-			return nil, nil
-		}
-		return nil, err
-	}
-	var entries []*osv.Entry
-	if err := json.Unmarshal(b, &entries); err != nil {
-		return nil, err
-	}
-	return entries, nil
-}
-
-func (c *fsCache) WriteEntries(dbName string, p string, entries []*osv.Entry) error {
-	path := filepath.Join(c.rootDir, dbName, p)
-	if err := os.MkdirAll(path, 0777); err != nil {
-		return err
-	}
-	j, err := json.Marshal(entries)
-	if err != nil {
-		return err
-	}
-	if err := ioutil.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
-		return err
-	}
-	return nil
-}
diff --git a/vulndb/govulncheck/cache_test.go b/vulndb/govulncheck/cache_test.go
deleted file mode 100644
index 0a85bc4..0000000
--- a/vulndb/govulncheck/cache_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2021 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 main
-
-import (
-	"os"
-	"path/filepath"
-	"reflect"
-	"testing"
-	"time"
-
-	"golang.org/x/vuln/osv"
-)
-
-func TestCache(t *testing.T) {
-	tmpDir := t.TempDir()
-
-	cache := &fsCache{rootDir: tmpDir}
-	dbName := "vulndb.golang.org"
-
-	_, _, err := cache.ReadIndex(dbName)
-	if err != nil {
-		t.Fatalf("ReadIndex failed for non-existent database: %v", err)
-	}
-
-	if err = os.Mkdir(filepath.Join(tmpDir, dbName), 0777); err != nil {
-		t.Fatalf("os.Mkdir failed: %v", err)
-	}
-	_, _, err = cache.ReadIndex(dbName)
-	if err != nil {
-		t.Fatalf("ReadIndex failed for database without cached index: %v", err)
-	}
-
-	now := time.Now()
-	expectedIdx := osv.DBIndex{
-		"a.vuln.example.com": time.Time{}.Add(time.Hour),
-		"b.vuln.example.com": time.Time{}.Add(time.Hour * 2),
-		"c.vuln.example.com": time.Time{}.Add(time.Hour * 3),
-	}
-	if err = cache.WriteIndex(dbName, expectedIdx, now); err != nil {
-		t.Fatalf("WriteIndex failed to write index: %v", err)
-	}
-
-	idx, retrieved, err := cache.ReadIndex(dbName)
-	if err != nil {
-		t.Fatalf("ReadIndex failed for database with cached index: %v", err)
-	}
-	if !reflect.DeepEqual(idx, expectedIdx) {
-		t.Errorf("ReadIndex returned unexpected index, got:\n%s\nwant:\n%s", idx, expectedIdx)
-	}
-	if !retrieved.Equal(now) {
-		t.Errorf("ReadIndex returned unexpected retrieved: got %s, want %s", retrieved, now)
-	}
-
-	if _, err = cache.ReadEntries(dbName, "vuln.example.com"); err != nil {
-		t.Fatalf("ReadEntires failed for non-existent package: %v", err)
-	}
-
-	expectedEntries := []*osv.Entry{
-		{ID: "001"},
-		{ID: "002"},
-		{ID: "003"},
-	}
-	if err := cache.WriteEntries(dbName, "vuln.example.com", expectedEntries); err != nil {
-		t.Fatalf("WriteEntries failed: %v", err)
-	}
-
-	entries, err := cache.ReadEntries(dbName, "vuln.example.com")
-	if err != nil {
-		t.Fatalf("ReadEntries failed for cached package: %v", err)
-	}
-	if !reflect.DeepEqual(entries, expectedEntries) {
-		t.Errorf("ReadEntries returned unexpected entries, got:\n%v\nwant:\n%v", entries, expectedEntries)
-	}
-}
diff --git a/vulndb/govulncheck/main.go b/vulndb/govulncheck/main.go
deleted file mode 100644
index 5934976..0000000
--- a/vulndb/govulncheck/main.go
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2021 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.
-
-// Command govulncheck reports known vulnerabilities filed in a vulnerability database
-// (see https://golang.org/design/draft-vulndb) that affect a given package or binary.
-//
-// It uses static analysis or the binary's symbol table to narrow down reports to only
-// those that potentially affect the application.
-//
-// WARNING WARNING WARNING
-//
-// govulncheck is still experimental and neither its output or the vulnerability
-// database should be relied on to be stable or comprehensive.
-package main
-
-import (
-	"encoding/json"
-	"flag"
-	"fmt"
-	"go/build"
-	"log"
-	"os"
-	"runtime"
-	"strings"
-
-	"golang.org/x/exp/vulndb/internal/audit"
-	"golang.org/x/exp/vulndb/internal/binscan"
-	"golang.org/x/tools/go/buildutil"
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/vuln/client"
-)
-
-var (
-	jsonFlag    = flag.Bool("json", false, "")
-	verboseFlag = flag.Bool("verbose", false, "")
-	importsFlag = flag.Bool("imports", false, "")
-	allFlag     = flag.Bool("all", false, "")
-	testsFlag   = flag.Bool("tests", false, "")
-)
-
-const usage = `govulncheck: identify known vulnerabilities by call graph traversal.
-
-Usage:
-
-	govulncheck [-imports] [-json] [-all] [-tests] [-tags] {package pattern...}
-
-	govulncheck {binary path}
-
-Flags:
-
-	-imports   Perform a broad scan with more false positives, which reports all
-	           vulnerabilities found in any transitively imported package, regardless
-	           of whether they are reachable.
-
-	-json  	   Print vulnerability findings in JSON format.
-
-	-all       Show all representative findings for each vulnerability. A best effort
-		   is made to order findings by relevance. When false [default], show only
-		   the most relevant finding.
-
-	-verbose   Print progress information.
-
-	-tags	   Comma-separated list of build tags.
-
-	-tests     Boolean flag indicating if test files should be analyzed too.
-
-govulncheck can be used with either one or more package patterns (i.e. golang.org/x/crypto/...
-or ./...) or with a single path to a Go binary. In the latter case module and symbol
-information will be extracted from the binary in order to detect vulnerable symbols
-and the -imports flag is disregarded.
-
-The environment variable GOVULNDB can be set to a comma-separate list of vulnerability
-database URLs, with http://, https://, or file:// protocols. Entries from multiple
-databases are merged.
-`
-
-func init() {
-	flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
-}
-
-func main() {
-	flag.Usage = func() { fmt.Fprint(os.Stderr, usage) }
-	flag.Parse()
-
-	if len(flag.Args()) == 0 {
-		fmt.Fprint(os.Stderr, usage)
-		os.Exit(1)
-	}
-
-	dbs := []string{"https://storage.googleapis.com/go-vulndb"}
-	if GOVULNDB := os.Getenv("GOVULNDB"); GOVULNDB != "" {
-		dbs = strings.Split(GOVULNDB, ",")
-	}
-	dbClient, err := client.NewClient(dbs, client.Options{HTTPCache: defaultCache()})
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "govulncheck: %s\n", err)
-		os.Exit(1)
-	}
-
-	cfg := &packages.Config{
-		Mode:       packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps | packages.NeedModule,
-		Tests:      *testsFlag,
-		BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(build.Default.BuildTags, ","))},
-	}
-
-	r, err := run(cfg, flag.Args(), *importsFlag, dbClient)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "govulncheck: %s\n", err)
-		os.Exit(1)
-	}
-
-	if !*allFlag {
-		r = projectToSingleFinding(r)
-	}
-
-	writeOut(r, *jsonFlag)
-}
-
-func projectToSingleFinding(r *audit.Results) *audit.Results {
-	nr := &audit.Results{
-		SearchMode:      r.SearchMode,
-		Vulnerabilities: r.Vulnerabilities,
-		VulnFindings:    make(map[string][]audit.Finding),
-	}
-
-	for id, findings := range r.VulnFindings {
-		if len(findings) > 0 {
-			nr.VulnFindings[id] = []audit.Finding{findings[0]}
-		}
-	}
-
-	return nr
-}
-
-func writeOut(r *audit.Results, toJson bool) {
-	if !toJson {
-		os.Stdout.Write([]byte(r.String()))
-		return
-	}
-
-	b, err := json.MarshalIndent(r, "", "\t")
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "govulncheck: %s\n", err)
-		os.Exit(1)
-	}
-	os.Stdout.Write(b)
-	os.Stdout.Write([]byte{'\n'})
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*packages.Package) []*packages.Module {
-	modMap := map[string]*packages.Module{}
-	modKey := func(mod *packages.Module) string {
-		if mod.Replace != nil {
-			return fmt.Sprintf("%s@%s", mod.Replace.Path, mod.Replace.Version)
-		}
-		return fmt.Sprintf("%s@%s", mod.Path, mod.Version)
-	}
-
-	seen := map[*packages.Package]bool{}
-	var extract func(*packages.Package, map[string]*packages.Module)
-	extract = func(pkg *packages.Package, modMap map[string]*packages.Module) {
-		if pkg == nil || seen[pkg] {
-			return
-		}
-		if pkg.Module != nil {
-			modMap[modKey(pkg.Module)] = pkg.Module
-		}
-		seen[pkg] = true
-		for _, imp := range pkg.Imports {
-			extract(imp, modMap)
-		}
-	}
-	for _, pkg := range pkgs {
-		extract(pkg, modMap)
-	}
-
-	modules := []*packages.Module{}
-	for _, mod := range modMap {
-		modules = append(modules, mod)
-	}
-	return modules
-}
-
-func isFile(path string) bool {
-	s, err := os.Stat(path)
-	if err != nil {
-		return false
-	}
-	return !s.IsDir()
-}
-
-func run(cfg *packages.Config, patterns []string, importsOnly bool, dbClient client.Client) (*audit.Results, error) {
-	if len(patterns) == 1 && isFile(patterns[0]) {
-		modules, symbols, err := binscan.ExtractPackagesAndSymbols(patterns[0])
-		if err != nil {
-			return nil, err
-		}
-
-		vulns, err := audit.FetchVulnerabilities(dbClient, modules)
-		if err != nil {
-			return nil, fmt.Errorf("failed to load vulnerability dbs: %v", err)
-		}
-		vulns = vulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
-
-		results := audit.VulnerablePackageSymbols(symbols, vulns)
-		return &results, nil
-	}
-
-	// Load packages.
-	if *verboseFlag {
-		log.Println("loading packages...")
-	}
-	pkgs, err := packages.Load(cfg, patterns...)
-	if err != nil {
-		return nil, err
-	}
-	if packages.PrintErrors(pkgs) > 0 {
-		return nil, fmt.Errorf("packages contain errors")
-	}
-	if *verboseFlag {
-		log.Printf("\t%d loaded packages\n", len(pkgs))
-	}
-
-	// Load database.
-	if *verboseFlag {
-		log.Println("loading database...")
-	}
-
-	modVulns, err := audit.FetchVulnerabilities(dbClient, extractModules(pkgs))
-	if err != nil {
-		return nil, fmt.Errorf("failed to fetch vulnerabilities: %v", err)
-	}
-	modVulns = modVulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
-	if *verboseFlag {
-		log.Printf("\t%d known vulnerabilities.\n", modVulns.Num())
-	}
-
-	// Load SSA.
-	if *verboseFlag {
-		log.Println("building ssa...")
-	}
-	prog, ssaPkgs := ssautil.AllPackages(pkgs, 0)
-	prog.Build()
-	if *verboseFlag {
-		log.Println("\tbuilt ssa")
-	}
-
-	// Compute the findings.
-	if *verboseFlag {
-		log.Println("detecting vulnerabilities...")
-	}
-	var results audit.Results
-	if importsOnly {
-		results = audit.VulnerableImports(ssaPkgs, modVulns)
-	} else {
-		results = audit.VulnerableSymbols(ssaPkgs, modVulns)
-	}
-	return &results, nil
-}
-
-func lookupEnv(key string, defaultValue string) (value string) {
-	if v, ok := os.LookupEnv(key); ok {
-		return v
-	}
-	return defaultValue
-}
diff --git a/vulndb/internal/audit/detect.go b/vulndb/internal/audit/detect.go
deleted file mode 100644
index 993f84b..0000000
--- a/vulndb/internal/audit/detect.go
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2021 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 audit finds vulnerabilities affecting Go packages.
-package audit
-
-import (
-	"fmt"
-	"go/token"
-	"sort"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/osv"
-)
-
-// Preamble with types and common functionality used by vulnerability detection mechanisms in detect_*.go files.
-
-// SearchType represents a type of an audit search: call graph, imports, or binary.
-type SearchType int
-
-// enum values for SearchType.
-const (
-	CallGraphSearch SearchType = iota
-	ImportsSearch
-	BinarySearch
-)
-
-// Results contains the information on findings and identified vulnerabilities by audit search.
-type Results struct {
-	SearchMode SearchType
-
-	// TODO: identify vulnerability with <ID, package, symbol>?
-	// Vulnerabilities in dependent modules.
-	Vulnerabilities []osv.Entry
-
-	VulnFindings map[string][]Finding // vuln.ID -> findings
-}
-
-// String method for results.
-func (r Results) String() string {
-	sort.Slice(r.Vulnerabilities, func(i, j int) bool { return r.Vulnerabilities[i].ID < r.Vulnerabilities[j].ID })
-
-	rStr := ""
-	for _, v := range r.Vulnerabilities {
-		findings := r.VulnFindings[v.ID]
-		if len(findings) == 0 {
-			// TODO: add messages for such cases too?
-			continue
-		}
-
-		var aliases string
-		if len(v.Aliases) != 0 {
-			aliases = fmt.Sprintf(" (%s)", strings.Join(v.Aliases, ", "))
-		}
-		rStr += fmt.Sprintf("Findings for vulnerability: %s%s:\n\n", v.ID, aliases)
-
-		for _, finding := range findings {
-			rStr += finding.String() + "\n"
-		}
-	}
-	return rStr
-}
-
-// addFindings adds a findings `f` for vulnerability `v`.
-func (r Results) addFinding(v osv.Entry, f Finding) {
-	r.VulnFindings[v.ID] = append(r.VulnFindings[v.ID], f)
-}
-
-// sort orders findings for each vulnerability based on its
-// perceived usefulness to the user.
-func (r Results) sort() {
-	for _, fs := range r.VulnFindings {
-		sort.SliceStable(fs, func(i int, j int) bool { return findingCompare(&fs[i], &fs[j]) })
-	}
-}
-
-// Finding represents a finding for the use of a vulnerable symbol or an imported vulnerable package.
-// Provides info on symbol location and the trace leading up to the symbol use.
-type Finding struct {
-	Symbol   string
-	Position *token.Position `json:",omitempty"`
-	Type     SymbolType
-	Trace    []TraceElem
-
-	// Approximate measure for indicating how understandable the finding is to the client.
-	// The smaller the weight, the more understandable is the finding.
-	weight int
-
-	// Approximate measure for indicating confidence in finding being a true positive. The
-	// smaller the value, the bigger the confidence.
-	confidence int
-}
-
-// String method for findings.
-func (f Finding) String() string {
-	traceStr := traceString(f.Trace)
-
-	var pos string
-	if f.Position != nil {
-		pos = fmt.Sprintf(" (%s)", f.Position)
-	}
-
-	return fmt.Sprintf("Trace:\n%s%s\n%s\n", f.Symbol, pos, traceStr)
-}
-
-func traceString(trace []TraceElem) string {
-	// traces are typically short, so string builders are not necessary
-	traceStr := ""
-	for i := len(trace) - 1; i >= 0; i-- {
-		traceStr += trace[i].String() + "\n"
-	}
-	return traceStr
-}
-
-// SymbolType represents a type of a symbol use: function, global, or an import statement.
-type SymbolType int
-
-// enum values for SymbolType.
-const (
-	FunctionType SymbolType = iota
-	ImportType
-	GlobalType
-)
-
-// TraceElem represents an entry in the finding trace. Represents a function call or an import statement.
-type TraceElem struct {
-	Description string
-	Position    *token.Position `json:",omitempty"`
-}
-
-// String method for trace elements.
-func (e TraceElem) String() string {
-	if e.Position == nil {
-		return e.Description
-	}
-	return fmt.Sprintf("%s (%s)", e.Description, e.Position)
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (s SymbolType) MarshalText() ([]byte, error) {
-	var name string
-	switch s {
-	default:
-		name = "unrecognized"
-	case FunctionType:
-		name = "function"
-	case ImportType:
-		name = "import"
-	case GlobalType:
-		name = "global"
-	}
-	return []byte(name), nil
-}
-
-type modVulns struct {
-	mod   *packages.Module
-	vulns []*osv.Entry
-}
-
-type ModuleVulnerabilities []modVulns
-
-func matchesPlatform(os, arch string, e osv.EcosystemSpecific) bool {
-	matchesOS := len(e.GOOS) == 0
-	matchesArch := len(e.GOARCH) == 0
-	for _, o := range e.GOOS {
-		if os == o {
-			matchesOS = true
-			break
-		}
-	}
-	for _, a := range e.GOARCH {
-		if arch == a {
-			matchesArch = true
-			break
-		}
-	}
-	return matchesOS && matchesArch
-}
-
-func (mv ModuleVulnerabilities) Filter(os, arch string) ModuleVulnerabilities {
-	var filteredMod ModuleVulnerabilities
-	for _, mod := range mv {
-		module := mod.mod
-		modVersion := module.Version
-		if module.Replace != nil {
-			modVersion = module.Replace.Version
-		}
-		// TODO: if modVersion == "", try vcs to get the version?
-		var filteredVulns []*osv.Entry
-		for _, v := range mod.vulns {
-			var filteredAffected []osv.Affected
-			for _, a := range v.Affected {
-				// A module version is affected if
-				//  - it is included in one of the affected version ranges
-				//  - and module version is not ""
-				//  The latter means the module version is not available, so
-				//  we don't want to spam users with potential false alarms.
-				//  TODO: issue warning for "" cases above?
-				affected := modVersion != "" && a.Ranges.AffectsSemver(modVersion) && matchesPlatform(os, arch, a.EcosystemSpecific)
-				if affected {
-					filteredAffected = append(filteredAffected, a)
-				}
-			}
-			if len(filteredAffected) == 0 {
-				continue
-			}
-			newV := *v
-			newV.Affected = filteredAffected
-			filteredVulns = append(filteredVulns, &newV)
-		}
-		filteredMod = append(filteredMod, modVulns{
-			mod:   module,
-			vulns: filteredVulns,
-		})
-	}
-	return filteredMod
-}
-
-func (mv ModuleVulnerabilities) Num() int {
-	var num int
-	for _, m := range mv {
-		num += len(m.vulns)
-	}
-	return num
-}
-
-// VulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv ModuleVulnerabilities) VulnsForPackage(importPath string) []*osv.Entry {
-	var mostSpecificMod *modVulns
-	for _, mod := range mv {
-		md := mod
-		if strings.HasPrefix(importPath, md.mod.Path) {
-			if mostSpecificMod == nil || len(mostSpecificMod.mod.Path) < len(md.mod.Path) {
-				mostSpecificMod = &md
-			}
-		}
-	}
-
-	if mostSpecificMod == nil {
-		return nil
-	}
-
-	if mostSpecificMod.mod.Replace != nil {
-		importPath = fmt.Sprintf("%s%s", mostSpecificMod.mod.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.mod.Path))
-	}
-	vulns := mostSpecificMod.vulns
-	packageVulns := []*osv.Entry{}
-	for _, v := range vulns {
-		for _, a := range v.Affected {
-			if a.Package.Name == importPath {
-				packageVulns = append(packageVulns, v)
-				break
-			}
-		}
-	}
-	return packageVulns
-}
-
-// VulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv ModuleVulnerabilities) VulnsForSymbol(importPath, symbol string) []*osv.Entry {
-	vulns := mv.VulnsForPackage(importPath)
-	if vulns == nil {
-		return nil
-	}
-
-	symbolVulns := []*osv.Entry{}
-	for _, v := range vulns {
-	vulnLoop:
-		for _, a := range v.Affected {
-			if a.Package.Name != importPath {
-				continue
-			}
-			if len(a.EcosystemSpecific.Symbols) == 0 {
-				symbolVulns = append(symbolVulns, v)
-				continue vulnLoop
-			}
-			for _, s := range a.EcosystemSpecific.Symbols {
-				if s == symbol {
-					symbolVulns = append(symbolVulns, v)
-					continue vulnLoop
-				}
-			}
-		}
-	}
-	return symbolVulns
-}
-
-// Vulns returns vulnerabilities for all modules in `mv`.
-func (mv ModuleVulnerabilities) Vulns() []*osv.Entry {
-	var vulns []*osv.Entry
-	seen := make(map[string]bool)
-	for _, mv := range mv {
-		for _, v := range mv.vulns {
-			if !seen[v.ID] {
-				vulns = append(vulns, v)
-				seen[v.ID] = true
-			}
-		}
-	}
-	return vulns
-}
diff --git a/vulndb/internal/audit/detect_binary.go b/vulndb/internal/audit/detect_binary.go
deleted file mode 100644
index b8e2a9b..0000000
--- a/vulndb/internal/audit/detect_binary.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"fmt"
-)
-
-// VulnerablePackageSymbols returns a list of vulnerability findings for per-package symbols
-// in packageSymbols, given the `modVulns` vulnerabilities.
-//
-// Findings for each vulnerability are sorted by estimated usefulness to the user and do not
-// have an associated trace.
-func VulnerablePackageSymbols(packageSymbols map[string][]string, modVulns ModuleVulnerabilities) Results {
-	results := Results{
-		SearchMode:      BinarySearch,
-		Vulnerabilities: serialize(modVulns.Vulns()),
-		VulnFindings:    make(map[string][]Finding),
-	}
-	if len(modVulns) == 0 {
-		return results
-	}
-
-	for pkg, symbols := range packageSymbols {
-		for _, symbol := range symbols {
-			vulns := modVulns.VulnsForSymbol(pkg, symbol)
-			for _, v := range serialize(vulns) {
-				results.addFinding(v, Finding{
-					Symbol: fmt.Sprintf("%s.%s", pkg, symbol),
-					Type:   GlobalType,
-				})
-			}
-		}
-	}
-
-	results.sort()
-	return results
-}
diff --git a/vulndb/internal/audit/detect_callgraph.go b/vulndb/internal/audit/detect_callgraph.go
deleted file mode 100644
index 983b37a..0000000
--- a/vulndb/internal/audit/detect_callgraph.go
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"container/list"
-	"fmt"
-	"go/token"
-	"log"
-	"strings"
-	"sync"
-
-	"golang.org/x/tools/go/callgraph"
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/ssa/ssautil"
-
-	"golang.org/x/tools/go/callgraph/cha"
-	"golang.org/x/tools/go/callgraph/vta"
-)
-
-// VulnerableSymbols returns vulnerability findings for symbols transitively reachable
-// through the callgraph built using VTA analysis from the entry points of pkgs, given
-// 'modVulns' vulnerabilities.
-//
-// Returns all findings reachable from pkgs while analyzing each package only once,
-// preferring findings of shorter import traces. For instance, given call chains
-//   A() -> B() -> V
-//   A() -> D() -> B() -> V
-//   D() -> B() -> V
-// where A and D are top level packages and V is a vulnerable symbol, VulnerableSymbols
-// can return either
-//   A() -> B() -> V
-// or
-//   D() -> B() -> V
-// as traces of transitively using a vulnerable symbol V.
-//
-// Findings for each vulnerability are sorted by estimated usefulness to the user.
-//
-// Panics if packages in pkgs do not belong to the same program.
-func VulnerableSymbols(pkgs []*ssa.Package, modVulns ModuleVulnerabilities) Results {
-	results := Results{
-		SearchMode:      CallGraphSearch,
-		Vulnerabilities: serialize(modVulns.Vulns()),
-		VulnFindings:    make(map[string][]Finding),
-	}
-	if len(modVulns) == 0 {
-		return results
-	}
-
-	prog := pkgsProgram(pkgs)
-	if prog == nil {
-		panic("packages in pkgs must belong to a single common program")
-	}
-	entries := entryPoints(pkgs)
-	callGraph := callGraph(prog, entries)
-
-	queue := list.New()
-	for _, entry := range entries {
-		queue.PushBack(&callChain{f: entry})
-	}
-
-	seen := make(map[*ssa.Function]bool)
-	for queue.Len() > 0 {
-		front := queue.Front()
-		v := front.Value.(*callChain)
-		queue.Remove(front)
-
-		if seen[v.f] {
-			continue
-		}
-		seen[v.f] = true
-
-		calls := funcVulnsAndCalls(v, modVulns, &results, callGraph)
-		for _, call := range calls {
-			queue.PushBack(call)
-		}
-	}
-
-	results.sort()
-	return results
-}
-
-// callGraph builds a call graph of prog based on VTA analysis.
-func callGraph(prog *ssa.Program, entries []*ssa.Function) *callgraph.Graph {
-	entrySlice := make(map[*ssa.Function]bool)
-	for _, e := range entries {
-		entrySlice[e] = true
-	}
-	initial := cha.CallGraph(prog)
-	allFuncs := ssautil.AllFunctions(prog)
-
-	fslice := forwardReachableFrom(entrySlice, initial)
-	// Keep only actually linked functions.
-	pruneSlice(fslice, allFuncs)
-	vtaCg := vta.CallGraph(fslice, initial)
-
-	// Repeat the process once more, this time using
-	// the produced VTA call graph as the base graph.
-	fslice = forwardReachableFrom(entrySlice, vtaCg)
-	pruneSlice(fslice, allFuncs)
-
-	return vta.CallGraph(fslice, vtaCg)
-}
-
-func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
-	var entries []*ssa.Function
-	for _, pkg := range topPackages {
-		if pkg.Pkg.Name() == "main" {
-			// for "main" packages the only valid entry points are the "main"
-			// function and any "init#" functions, even if there are other
-			// exported functions or types. similarly to isEntry it should be
-			// safe to ignore the validity of the main or init# signatures,
-			// since the compiler will reject malformed definitions,
-			// and the init function is synthetic
-			entries = append(entries, memberFuncs(pkg.Members["main"], pkg.Prog)...)
-			for name, member := range pkg.Members {
-				if strings.HasPrefix(name, "init#") || name == "init" {
-					entries = append(entries, memberFuncs(member, pkg.Prog)...)
-				}
-			}
-			continue
-		}
-		for _, member := range pkg.Members {
-			for _, f := range memberFuncs(member, pkg.Prog) {
-				if isEntry(f) {
-					entries = append(entries, f)
-				}
-			}
-		}
-	}
-	return entries
-}
-
-func isEntry(f *ssa.Function) bool {
-	// it should be safe to ignore checking that the signature of the "init" function
-	// is valid, since it is synthetic
-	if f.Name() == "init" && f.Synthetic == "package initializer" {
-		return true
-	}
-
-	return f.Synthetic == "" && f.Object() != nil && f.Object().Exported()
-}
-
-// callChain helps doing BFS over package call graph while remembering the call stack.
-type callChain struct {
-	// nil for entry points of the chain.
-	call   ssa.CallInstruction
-	f      *ssa.Function
-	parent *callChain
-}
-
-func (chain *callChain) trace() []TraceElem {
-	if chain == nil {
-		return nil
-	}
-
-	var pos *token.Position
-	desc := fmt.Sprintf("%s.%s(...)", pkgPath(chain.f), dbFuncName(chain.f))
-	if chain.call != nil {
-		pos = instrPosition(chain.call)
-		if unresolved(chain.call) {
-			// In case of a statically unresolved call site, communicate to the client
-			// that this was approximately resolved to chain.f.
-			desc = fmt.Sprintf("%s(...) [approx. resolved to %s]", callName(chain.call), chain.f)
-		}
-	} else {
-		// No call information means the function is an entry point.
-		pos = funcPosition(chain.f)
-	}
-
-	return append(chain.parent.trace(), TraceElem{Description: desc, Position: pos})
-}
-
-// weight computes an approximate measure of how easy is to understand the call
-// chain when presented to the client as a trace. The smaller the value, the more
-// understendeable the chain is. Currently defined as the number of unresolved
-// call sites in the chain.
-func (chain *callChain) weight() int {
-	if chain == nil || chain.call == nil {
-		return 0
-	}
-
-	callWeight := 0
-	if unresolved(chain.call) {
-		callWeight = 1
-	}
-	return callWeight + chain.parent.weight()
-}
-
-// for assesing confidence level of findings.
-var stdPackages = make(map[string]bool)
-var loadStdsOnce sync.Once
-
-func isStdPackage(pkg *ssa.Package) bool {
-	if pkg == nil || pkg.Pkg == nil {
-		return false
-	}
-
-	loadStdsOnce.Do(func() {
-		pkgs, err := packages.Load(nil, "std")
-		if err != nil {
-			log.Printf("warning: unable to fetch list of std packages, ordering of findings might be affected: %v", err)
-		}
-
-		for _, p := range pkgs {
-			stdPackages[p.PkgPath] = true
-		}
-	})
-	return stdPackages[pkg.Pkg.Path()]
-}
-
-// confidence computes an approximate measure of whether the `chain`
-// represents a true finding. Currently, it equals the number of call
-// sites in `chain` that go through standard libraries. Such findings
-// have been experimentally shown to often result in false positives.
-//
-// TODO: add tests for trace confidence computation involving std libs.
-func (chain *callChain) confidence() int {
-	if chain == nil || chain.call == nil {
-		return 0
-	}
-
-	callConfidence := 0
-	if isStdPackage(chain.call.Parent().Pkg) {
-		callConfidence = 1
-	}
-	return callConfidence + chain.parent.confidence()
-}
-
-// funcVulnsAndCalls adds symbol findings to results for
-// function at the top of chain and next calls to analyze.
-func funcVulnsAndCalls(chain *callChain, modVulns ModuleVulnerabilities, results *Results, callGraph *callgraph.Graph) []*callChain {
-	var calls []*callChain
-	for _, b := range chain.f.Blocks {
-		for _, instr := range b.Instrs {
-			// First collect all findings for globals except callees in function call statements.
-			globalFindings(globalUses(instr), chain, modVulns, results)
-
-			// Callees are handled separately to produce call findings rather than global findings.
-			site, ok := instr.(ssa.CallInstruction)
-			if !ok {
-				continue
-			}
-
-			for _, callee := range siteCallees(site, callGraph) {
-				c := &callChain{call: site, f: callee, parent: chain}
-				calls = append(calls, c)
-				callFinding(c, modVulns, results)
-			}
-		}
-	}
-	return calls
-}
-
-// globalFindings adds findings for vulnerable globals among globalUses to results.
-// Assumes each use in globalUses is a use of a global variable. Can generate
-// duplicates when globalUses contains duplicates.
-func globalFindings(globalUses []*ssa.Value, chain *callChain, modVulns ModuleVulnerabilities, results *Results) {
-	if underRelatedVuln(chain, modVulns) {
-		return
-	}
-
-	for _, o := range globalUses {
-		g := (*o).(*ssa.Global)
-		vulns := modVulns.VulnsForSymbol(g.Package().Pkg.Path(), g.Name())
-		for _, v := range serialize(vulns) {
-			results.addFinding(v, Finding{
-				Symbol:     fmt.Sprintf("%s.%s", g.Package().Pkg.Path(), g.Name()),
-				Trace:      chain.trace(),
-				Position:   valPosition(*o, chain.f),
-				Type:       GlobalType,
-				weight:     chain.weight(),
-				confidence: chain.confidence()})
-		}
-	}
-}
-
-// callFinding adds findings to results for the call made at the top of the chain.
-// If there is no vulnerability or no call information, then nil is returned.
-// TODO(zpavlinovic): remove ssa info from higher-order calls.
-func callFinding(chain *callChain, modVulns ModuleVulnerabilities, results *Results) {
-	if underRelatedVuln(chain, modVulns) {
-		return
-	}
-
-	callee := chain.f
-	call := chain.call
-	if callee == nil || call == nil {
-		return
-	}
-
-	c := chain
-	if !unresolved(call) {
-		// If the last call is a resolved callsite, remove the edge from the trace as that
-		// information is provided in the symbol field.
-		c = c.parent
-	}
-
-	// some synthetic functions might not have an associated package
-	if callee.Package() == nil || callee.Package().Pkg == nil {
-		return
-	}
-
-	vulns := modVulns.VulnsForSymbol(callee.Package().Pkg.Path(), dbFuncName(callee))
-	for _, v := range serialize(vulns) {
-		results.addFinding(v, Finding{
-			Symbol:     fmt.Sprintf("%s.%s", callee.Package().Pkg.Path(), dbFuncName(callee)),
-			Trace:      c.trace(),
-			Position:   instrPosition(call),
-			Type:       FunctionType,
-			weight:     c.weight(),
-			confidence: c.confidence()})
-	}
-}
-
-// Checks if a potential vulnerability in chain.f is analyzed only because
-// a previous vulnerability in the same package as chain.f has been seen.
-// For instance, for the chain P1:A -> P2:B -> P2:C where both B and C are
-// vulnerable, the function returns true since B is already vulnerable and
-// has hence been reported. Clients are likely not interested in vulnerabilties
-// inside of a function that is already deemed vulnerable. This is an optimization
-// step to stop flooding of findings when a package has a lot of known vulnerable
-// symbols (e.g., all of them).
-//
-// Note that for P1:A -> P2:B -> P3:D -> P2:C the function returns false. This
-// is because C is called from D that comes from a different package.
-func underRelatedVuln(chain *callChain, modVulns ModuleVulnerabilities) bool {
-	pkg := pkgPath(chain.f)
-
-	c := chain
-	for {
-		c = c.parent
-		// Analyze the immediate substack related to pkg.
-		if c == nil || pkgPath(c.f) != pkg {
-			break
-		}
-
-		// some synthetic functions might not have an associated package
-		if c.f.Pkg == nil || c.f.Pkg.Pkg == nil {
-			continue
-		}
-
-		// TODO: can we optimize using the information on findings already reported?
-		if len(modVulns.VulnsForSymbol(c.f.Pkg.Pkg.Path(), dbFuncName(c.f))) > 0 {
-			return true
-		}
-	}
-	return false
-}
diff --git a/vulndb/internal/audit/detect_callgraph_test.go b/vulndb/internal/audit/detect_callgraph_test.go
deleted file mode 100644
index 17789ec..0000000
--- a/vulndb/internal/audit/detect_callgraph_test.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"go/token"
-	"reflect"
-	"testing"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/packages/packagestest"
-	"golang.org/x/vuln/osv"
-)
-
-func TestSymbolVulnDetectionVTA(t *testing.T) {
-	pkgs, modVulns := testContext(t)
-	results := VulnerableSymbols(pkgs, modVulns)
-
-	if results.SearchMode != CallGraphSearch {
-		t.Errorf("want call graph search mode; got %v", results.SearchMode)
-	}
-
-	// There should be four call chains reported with VTA-VTA version, in the following order,
-	// for vuln.VG and vuln.VulnData.Vuln vulnerabilities:
-	//  vuln.VG:
-	//   T:T1() -> vuln.VG                                     [use of global at line 4]
-	//   T:T2() -> vuln.Vuln() [approx.resolved] -> vuln.VG    [use of global at vuln.go:4]
-	//  vuln.VulnData.Vuln:
-	//   T:T1() -> A:A1() -> vuln.VulnData.Vuln()              [call at A.go:14]
-	//   T:T1() -> vuln.VulnData.Vuln() [approx. resolved]     [call at testdata.go:13]
-	// Without VTA-VTA, we would alse have the following false positive:
-	//   T:T2() -> vuln.VulnData.Vuln() [approx. resolved]     [call at testdata.go:26]
-	for _, test := range []struct {
-		vulnId   string
-		findings []Finding
-	}{
-		{vulnId: "V1", findings: []Finding{
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln.VulnData.Vuln",
-				Trace: []TraceElem{
-					{Description: "command-line-arguments.T1(...)", Position: &token.Position{Line: 11, Filename: "T.go"}},
-					{Description: "a.org/A.A1(...)", Position: &token.Position{Line: 14, Filename: "T.go"}}},
-				Type:     FunctionType,
-				Position: &token.Position{Line: 15, Filename: "A.go"},
-				weight:   0,
-			},
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln.VulnData.Vuln",
-				Trace: []TraceElem{
-					{Description: "command-line-arguments.T1(...)", Position: &token.Position{Line: 11, Filename: "T.go"}},
-					{Description: "a.org/A.I.Vuln(...) [approx. resolved to (thirdparty.org/vulnerabilities/vuln.VulnData).Vuln]", Position: &token.Position{Line: 14, Filename: "T.go"}}},
-				Type:     FunctionType,
-				Position: &token.Position{Line: 14, Filename: "T.go"},
-				weight:   1,
-			},
-		}},
-		{vulnId: "V2", findings: []Finding{
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln.VG",
-				Trace: []TraceElem{
-					{Description: "command-line-arguments.T1(...)", Position: &token.Position{Line: 11, Filename: "T.go"}},
-				},
-				Type:     GlobalType,
-				Position: &token.Position{Line: 5, Filename: "vuln.go"},
-				weight:   0,
-			},
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln.VG",
-				Trace: []TraceElem{
-					{Description: "command-line-arguments.T2(...)", Position: &token.Position{Line: 20, Filename: "T.go"}},
-					{Description: "command-line-arguments.t0(...) [approx. resolved to thirdparty.org/vulnerabilities/vuln.Vuln]", Position: &token.Position{Line: 22, Filename: "T.go"}},
-				},
-				Type:     GlobalType,
-				Position: &token.Position{Line: 5, Filename: "vuln.go"},
-				weight:   1,
-			},
-		}},
-	} {
-		got := projectFindings(results.VulnFindings[test.vulnId])
-		if !reflect.DeepEqual(test.findings, got) {
-			t.Errorf("want %v findings (projected); got %v", test.findings, got)
-		}
-	}
-}
-
-func TestInitReachability(t *testing.T) {
-	e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
-		{
-			Name: "golang.org/inittest",
-			Files: map[string]interface{}{"main.go": `
-			package main
-
-			import "example.com/vuln"
-
-			func main() {
-				vuln.Foo() // benign
-			}
-			`},
-		},
-		{
-			Name: "example.com@v1.1.1",
-			Files: map[string]interface{}{"vuln/vuln.go": `
-			package vuln
-
-			func init() {
-				Bad() // bad
-			}
-
-			func Foo() {}
-			func Bad() {}
-			`},
-		},
-	})
-	defer e.Cleanup()
-
-	_, pkgs, _, err := loadAndBuildPackages(e, "/inittest/main.go")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	modVulns := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{Path: "example.com", Version: "v1.1.1"},
-			vulns: []*osv.Entry{
-				{
-					ID: "V3",
-					Affected: []osv.Affected{{
-						Package:           osv.Package{Name: "example.com/vuln"},
-						Ranges:            osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.1.2"}}}},
-						EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"Bad"}},
-					}},
-				},
-			},
-		},
-	}
-	results := VulnerableSymbols(pkgs, modVulns)
-
-	if results.SearchMode != CallGraphSearch {
-		t.Errorf("want call graph search mode; got %v", results.SearchMode)
-	}
-
-	want := []Finding{
-		{
-			Symbol: "example.com/vuln.Bad",
-			Trace: []TraceElem{
-				{Description: "command-line-arguments.init(...)", Position: &token.Position{}},
-				{Description: "example.com/vuln.init(...)", Position: &token.Position{}},
-				{Description: "example.com/vuln.init#1(...)", Position: &token.Position{}}},
-			Type:     FunctionType,
-			Position: &token.Position{Line: 5, Filename: "vuln.go"},
-			weight:   0,
-		},
-	}
-	if got := projectFindings(results.VulnFindings["V3"]); !reflect.DeepEqual(want, got) {
-		t.Errorf("want %v findings (projected); got %v", want, got)
-	}
-}
diff --git a/vulndb/internal/audit/detect_imports.go b/vulndb/internal/audit/detect_imports.go
deleted file mode 100644
index 4e2a78e..0000000
--- a/vulndb/internal/audit/detect_imports.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"container/list"
-	"go/types"
-
-	"golang.org/x/tools/go/ssa"
-)
-
-// VulnerableImports returns vulnerability findings for packages imported by `pkgs`
-// given the vulnerability and platform info captured in `env`.
-//
-// Returns all findings reachable from `pkgs` while analyzing each package only once, preferring
-// findings of shorter import traces. For instance, given import chains
-//   A -> B -> V
-//   A -> D -> B -> V
-//   D -> B -> V
-// where A and D are top level packages and V is a vulnerable package, VulnerableImports can return either
-//   A -> B -> V
-// or
-//   D -> B -> V
-// as traces of importing a vulnerable package V.
-//
-// Findings for each vulnerability are sorted by estimated usefulness to the user.
-func VulnerableImports(pkgs []*ssa.Package, modVulns ModuleVulnerabilities) Results {
-	results := Results{
-		SearchMode:      ImportsSearch,
-		Vulnerabilities: serialize(modVulns.Vulns()),
-		VulnFindings:    make(map[string][]Finding),
-	}
-	if len(modVulns) == 0 {
-		return results
-	}
-
-	seen := make(map[string]bool)
-	queue := list.New()
-	for _, pkg := range pkgs {
-		queue.PushBack(&importChain{pkg: pkg.Pkg})
-	}
-
-	for queue.Len() > 0 {
-		front := queue.Front()
-		c := front.Value.(*importChain)
-		queue.Remove(front)
-
-		pkg := c.pkg
-		if pkg == nil {
-			continue
-		}
-
-		if seen[pkg.Path()] {
-			continue
-		}
-		seen[pkg.Path()] = true
-
-		for _, imp := range pkg.Imports() {
-			vulns := modVulns.VulnsForPackage(imp.Path())
-			for _, v := range serialize(vulns) {
-				t := c.trace()
-				results.addFinding(v, Finding{
-					Symbol: imp.Path(),
-					Type:   ImportType,
-					Trace:  t,
-					weight: len(t)})
-			}
-			queue.PushBack(&importChain{pkg: imp, parent: c})
-		}
-	}
-
-	results.sort()
-	return results
-}
-
-// importChain helps doing BFS over package imports while remembering import chains.
-type importChain struct {
-	pkg    *types.Package
-	parent *importChain
-}
-
-func (chain *importChain) trace() []TraceElem {
-	if chain == nil {
-		return nil
-	}
-	return append(chain.parent.trace(), TraceElem{Description: chain.pkg.Path()})
-}
diff --git a/vulndb/internal/audit/detect_imports_test.go b/vulndb/internal/audit/detect_imports_test.go
deleted file mode 100644
index e0f3968..0000000
--- a/vulndb/internal/audit/detect_imports_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"reflect"
-	"testing"
-)
-
-func TestImportedPackageVulnDetection(t *testing.T) {
-	pkgs, modVulns := testContext(t)
-	results := VulnerableImports(pkgs, modVulns)
-
-	if results.SearchMode != ImportsSearch {
-		t.Errorf("want import search mode; got %v", results.SearchMode)
-	}
-
-	// There should be two chains reported in the following order
-	// for two of the thirdparty.org test vulnerabilities:
-	//   T -> vuln
-	//   T -> A -> vuln
-	for _, test := range []struct {
-		vulnId   string
-		findings []Finding
-	}{
-		{vulnId: "V1", findings: []Finding{
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln",
-				Trace:  []TraceElem{{Description: "command-line-arguments"}},
-				Type:   ImportType,
-				weight: 1,
-			},
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln",
-				Trace:  []TraceElem{{Description: "command-line-arguments"}, {Description: "a.org/A"}},
-				Type:   ImportType,
-				weight: 2,
-			},
-		}},
-		{vulnId: "V2", findings: []Finding{
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln",
-				Trace:  []TraceElem{{Description: "command-line-arguments"}},
-				Type:   ImportType,
-				weight: 1,
-			},
-			{
-				Symbol: "thirdparty.org/vulnerabilities/vuln",
-				Trace:  []TraceElem{{Description: "command-line-arguments"}, {Description: "a.org/A"}},
-				Type:   ImportType,
-				weight: 2,
-			},
-		}},
-	} {
-		got := projectFindings(results.VulnFindings[test.vulnId])
-		if !reflect.DeepEqual(test.findings, got) {
-			t.Errorf("want %v findings (projected); got %v", test.findings, got)
-		}
-	}
-}
diff --git a/vulndb/internal/audit/detect_test.go b/vulndb/internal/audit/detect_test.go
deleted file mode 100644
index 6c54732..0000000
--- a/vulndb/internal/audit/detect_test.go
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/osv"
-)
-
-func moduleVulnerabilitiesToString(mv ModuleVulnerabilities) string {
-	var s string
-	for _, m := range mv {
-		s += fmt.Sprintf("mod: %v\n", m.mod)
-		for _, v := range m.vulns {
-			s += fmt.Sprintf("\t%v\n", v)
-		}
-	}
-	return s
-}
-
-func TestFilterVulns(t *testing.T) {
-	mv := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{
-					{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}},
-					{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.0.0"}}}}}, // should be filtered out
-				}},
-				{ID: "b", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows", "linux"}}}}},
-				{ID: "c", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64", "amd64"}}}}},
-				{ID: "d", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/b",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "e", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64"}}}}},
-				{ID: "f", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
-				{ID: "g", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.1"}, {Fixed: "2.0.1"}}}}}}},
-				{ID: "h", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}, GOARCH: []string{"amd64"}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path: "example.mod/c",
-			},
-			vulns: []*osv.Entry{
-				{ID: "i", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.0"}}}}}}},
-				{ID: "j", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "3.0.0"}}}}}}},
-				{ID: "k"},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/d",
-				Version: "v1.2.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "l", Affected: []osv.Affected{
-					{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}, // should be filtered out
-					{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}},
-				}},
-			},
-		},
-	}
-
-	expected := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
-				{ID: "c", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64", "amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.1"}}}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/b",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "f", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
-				{ID: "g", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.1"}, {Fixed: "2.0.1"}}}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path: "example.mod/c",
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/d",
-				Version: "v1.2.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "l", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
-			},
-		},
-	}
-
-	filtered := mv.Filter("linux", "amd64")
-	if !reflect.DeepEqual(filtered, expected) {
-		t.Fatalf("Filter returned unexpected results, got:\n%s\nwant:\n%s", moduleVulnerabilitiesToString(filtered), moduleVulnerabilitiesToString(expected))
-	}
-}
-
-func vulnsToString(vulns []*osv.Entry) string {
-	var s string
-	for _, v := range vulns {
-		s += fmt.Sprintf("\t%v\n", v)
-	}
-	return s
-}
-
-func TestVulnsForPackage(t *testing.T) {
-	mv := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a/b",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/d",
-				Version: "v0.0.1",
-			},
-			vulns: []*osv.Entry{
-				{ID: "d", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}}}},
-			},
-		},
-	}
-
-	filtered := mv.VulnsForPackage("example.mod/a/b/c")
-	expected := []*osv.Entry{
-		{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
-	}
-
-	if !reflect.DeepEqual(filtered, expected) {
-		t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
-	}
-}
-
-func TestVulnsForPackageReplaced(t *testing.T) {
-	mv := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path: "example.mod/a/b",
-				Replace: &packages.Module{
-					Path: "example.mod/b",
-				},
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b/c"}}}},
-			},
-		},
-	}
-
-	filtered := mv.VulnsForPackage("example.mod/a/b/c")
-	expected := []*osv.Entry{
-		{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b/c"}}}},
-	}
-
-	if !reflect.DeepEqual(filtered, expected) {
-		t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
-	}
-}
-
-func TestVulnsForSymbol(t *testing.T) {
-	mv := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
-			},
-		},
-		{
-			mod: &packages.Module{
-				Path:    "example.mod/a/b",
-				Version: "v1.0.0",
-			},
-			vulns: []*osv.Entry{
-				{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"a"}}}}},
-				{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"b"}}}}},
-			},
-		},
-	}
-
-	filtered := mv.VulnsForSymbol("example.mod/a/b/c", "a")
-	expected := []*osv.Entry{
-		{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"a"}}}}},
-	}
-
-	if !reflect.DeepEqual(filtered, expected) {
-		t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
-	}
-}
diff --git a/vulndb/internal/audit/helpers_test.go b/vulndb/internal/audit/helpers_test.go
deleted file mode 100644
index 0e65a1f..0000000
--- a/vulndb/internal/audit/helpers_test.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"go/token"
-	"io/ioutil"
-	"path"
-	"path/filepath"
-	"strings"
-	"testing"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/tools/go/packages/packagestest"
-	"golang.org/x/tools/go/ssa"
-	"golang.org/x/tools/go/ssa/ssautil"
-	"golang.org/x/vuln/osv"
-)
-
-// Loads test program and environment with the following import structure
-//                 T
-//              /  |  \
-//             A   |   B
-//             \   |   /
-//              \  |  A
-//               \ | /
-//               vuln
-// where `vuln` is a package containing some vulnerabilities. The definition
-// of T can be found in testdata/top_package.go, A is in testdata/a_dep.go,
-// B is in testdata/b_dep.go, and vuln is in testdata/vuln.go.
-//
-// The program has the following vulnerabilities that should be reported
-//   T:T1() -> vuln.VG
-//   T:T1() -> A:A1() -> vuln.VulnData.Vuln()
-//   T:T2() -> vuln.Vuln() [approx.resolved] -> vuln.VG
-//   T:T1() -> vuln.VulnData.Vuln() [approx. resolved]
-//
-// The following vulnerability should not be reported as it is redundant:
-//   T:T1() -> A:A1() -> B:B1() -> vuln.VulnData.Vuln()
-func testContext(t *testing.T) ([]*ssa.Package, ModuleVulnerabilities) {
-	e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
-		{
-			Name:  "golang.org/vulntest",
-			Files: map[string]interface{}{"T/T.go": readFile(t, "testdata/top_package.go")},
-		},
-		{
-			Name:  "a.org@v1.1.1",
-			Files: map[string]interface{}{"A/A.go": readFile(t, "testdata/a_dep.go")},
-		},
-		{
-			Name:  "b.org@v1.2.2",
-			Files: map[string]interface{}{"B/B.go": readFile(t, "testdata/b_dep.go")},
-		},
-		{
-			Name:  "thirdparty.org/vulnerabilities@v1.0.1",
-			Files: map[string]interface{}{"vuln/vuln.go": readFile(t, "testdata/vuln.go")},
-		},
-	})
-	defer e.Cleanup()
-
-	_, ssaPkgs, _, err := loadAndBuildPackages(e, "/vulntest/T/T.go")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if len(ssaPkgs) != 1 {
-		t.Errorf("want 1 top level SSA package; got %d", len(ssaPkgs))
-	}
-
-	modVulns := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{Path: "thirdparty.org/vulnerabilities", Version: "v1.0.1"},
-			vulns: []*osv.Entry{
-				{
-					ID: "V1",
-					Affected: []osv.Affected{{
-						Package:           osv.Package{Name: "thirdparty.org/vulnerabilities/vuln"},
-						Ranges:            osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
-						EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"VulnData.Vuln", "VulnData.VulnOnPtr"}},
-					}},
-				},
-				{
-					ID: "V2",
-					Affected: []osv.Affected{{
-						Package:           osv.Package{Name: "thirdparty.org/vulnerabilities/vuln"},
-						Ranges:            osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.2"}}}},
-						EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"VG"}},
-					}},
-				},
-			},
-		},
-	}
-
-	return ssaPkgs, modVulns
-}
-
-func loadAndBuildPackages(e *packagestest.Exported, file string) (*ssa.Program, []*ssa.Package, []*packages.Package, error) {
-	e.Config.Mode |= packages.NeedModule | packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps
-	// Get the path to the test file.
-	filepath := path.Join(e.Temp(), file)
-	pkgs, err := packages.Load(e.Config, filepath)
-	if err != nil {
-		return nil, nil, nil, err
-	}
-
-	prog, ssaPkgs := ssautil.AllPackages(pkgs, 0)
-	prog.Build()
-	return prog, ssaPkgs, pkgs, nil
-}
-
-// projectPosition simplifies position to only filename and location info.
-func projectPosition(pos *token.Position) *token.Position {
-	if pos == nil {
-		return nil
-	}
-	fname := pos.Filename
-	if fname != "" {
-		fname = filepath.Base(fname)
-	}
-	return &token.Position{Line: pos.Line, Filename: fname}
-}
-
-// projectTrace simplifies traces for testing comparison purposes
-// by simplifying position info.
-func projectTrace(trace []TraceElem) []TraceElem {
-	var nt []TraceElem
-	for _, e := range trace {
-		nt = append(nt, TraceElem{Description: e.Description, Position: projectPosition(e.Position)})
-	}
-	return nt
-}
-
-// projectFindings simplifies findings for testing comparison purposes. Traces
-// are removed their position info, finding's position only contains file and
-// line info, and vulnerabilities only have package path.
-func projectFindings(findings []Finding) []Finding {
-	var nfs []Finding
-	for _, f := range findings {
-		nf := Finding{
-			Type:     f.Type,
-			Symbol:   f.Symbol,
-			Position: projectPosition(f.Position),
-			Trace:    projectTrace(f.Trace),
-			weight:   f.weight,
-		}
-		nfs = append(nfs, nf)
-	}
-	return nfs
-}
-
-func readFile(t *testing.T, path string) string {
-	content, err := ioutil.ReadFile(path)
-	if err != nil {
-		t.Fatalf("failed to load code from `%v`: %v", path, err)
-	}
-	return strings.ReplaceAll(string(content), "// go:build ignore", "")
-}
diff --git a/vulndb/internal/audit/order.go b/vulndb/internal/audit/order.go
deleted file mode 100644
index 522e3ab..0000000
--- a/vulndb/internal/audit/order.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"fmt"
-	"strings"
-)
-
-// findingCompare compares two findings in terms of their estimated value to the user.
-// Findings of shorter traces generally come earlier in the ordering.
-//
-// Two findings produced by audit call graph search are lexicographically ordered by:
-// 1) their estimated level of confidence in being a true positive, 2) the length of
-// their traces, and 3) the number of unresolved call sites in the traces.
-func findingCompare(finding1, finding2 *Finding) bool {
-	if finding1.confidence != finding2.confidence {
-		return finding1.confidence < finding2.confidence
-	}
-
-	if len(finding1.Trace) != len(finding2.Trace) {
-		return len(finding1.Trace) < len(finding2.Trace)
-	}
-
-	if finding1.weight != finding2.weight {
-		return finding1.weight < finding2.weight
-	}
-	// At this point we just need to make sure the ordering is deterministic.
-	// TODO(zpavlinovic): is there a more meaningful ordering?
-	return findingStrCompare(finding1, finding2)
-}
-
-// findingStrCompare compares string representation of findings pointwise by their fields.
-func findingStrCompare(finding1, finding2 *Finding) bool {
-	if cmp := strings.Compare(finding1.Symbol, finding2.Symbol); cmp != 0 {
-		return cmp < 0
-	}
-
-	if cmp := strings.Compare(fmt.Sprintf("%v", finding1.Type), fmt.Sprintf("%v", finding2.Type)); cmp != 0 {
-		return cmp < 0
-	}
-
-	if cmp := strings.Compare(fmt.Sprintf("%v", finding1.Position), fmt.Sprintf("%v", finding2.Position)); cmp != 0 {
-		return cmp < 0
-	}
-
-	return strings.Compare(fmt.Sprintf("%v", finding1.Trace), fmt.Sprintf("%v", finding2.Trace)) <= 0
-}
diff --git a/vulndb/internal/audit/order_test.go b/vulndb/internal/audit/order_test.go
deleted file mode 100644
index 18506ce..0000000
--- a/vulndb/internal/audit/order_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"reflect"
-	"sort"
-	"testing"
-)
-
-func TestFindingsOrdering(t *testing.T) {
-	f1 := Finding{Trace: []TraceElem{
-		{Description: "T1"},
-	},
-	}
-	f2 := Finding{Trace: []TraceElem{
-		{Description: "T1"},
-		{Description: "T2"},
-	},
-	}
-	f3 := Finding{Trace: []TraceElem{
-		{Description: "T1"}},
-		confidence: 1,
-	}
-	f4 := Finding{Trace: []TraceElem{
-		{Description: "T1"}},
-		confidence: 1,
-		weight:     2,
-	}
-
-	finds := []Finding{f4, f3, f2, f1}
-	sort.SliceStable(finds, func(i int, j int) bool { return findingCompare(&finds[i], &finds[j]) })
-	if want := []Finding{f1, f2, f3, f4}; !reflect.DeepEqual(finds, want) {
-		t.Errorf("want ordering %v; got %v", want, finds)
-	}
-}
diff --git a/vulndb/internal/audit/slicing.go b/vulndb/internal/audit/slicing.go
deleted file mode 100644
index b976f16..0000000
--- a/vulndb/internal/audit/slicing.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"golang.org/x/tools/go/callgraph"
-	"golang.org/x/tools/go/ssa"
-)
-
-// forwardReachableFrom computes the set of functions forward reachable from `sources`.
-// A function f is reachable from a function g if f is an anonymous function defined
-// in g or a function called in g as given by the callgraph `cg`.
-func forwardReachableFrom(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.Function]bool {
-	m := make(map[*ssa.Function]bool)
-	for s := range sources {
-		forward(s, cg, m)
-	}
-	return m
-}
-
-func forward(f *ssa.Function, cg *callgraph.Graph, seen map[*ssa.Function]bool) {
-	if _, ok := seen[f]; ok {
-		return
-	}
-	seen[f] = true
-	var buf [10]*ssa.Value // avoid alloc in common case
-	for _, b := range f.Blocks {
-		for _, instr := range b.Instrs {
-			switch i := instr.(type) {
-			case ssa.CallInstruction:
-				for _, c := range siteCallees(i, cg) {
-					forward(c, cg, seen)
-				}
-			default:
-				for _, op := range i.Operands(buf[:0]) {
-					if fn, ok := (*op).(*ssa.Function); ok {
-						forward(fn, cg, seen)
-					}
-				}
-			}
-		}
-	}
-}
-
-// pruneSlice removes functions in `slice` that are in `toPrune`.
-func pruneSlice(slice map[*ssa.Function]bool, toPrune map[*ssa.Function]bool) {
-	for f := range slice {
-		if _, ok := toPrune[f]; !ok {
-			delete(slice, f)
-		}
-	}
-}
diff --git a/vulndb/internal/audit/slicing_test.go b/vulndb/internal/audit/slicing_test.go
deleted file mode 100644
index 782b6c3..0000000
--- a/vulndb/internal/audit/slicing_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"reflect"
-	"testing"
-
-	"golang.org/x/tools/go/callgraph/cha"
-	"golang.org/x/tools/go/packages/packagestest"
-	"golang.org/x/tools/go/ssa"
-)
-
-// funcsToString returns a set of function names for `funcs`.
-func funcsToString(funcs map[*ssa.Function]bool) map[string]bool {
-	fs := make(map[string]bool)
-	for f := range funcs {
-		fs[dbFuncName(f)] = true
-	}
-	return fs
-}
-
-func TestSlicing(t *testing.T) {
-	e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
-		{
-			Name:  "some/module",
-			Files: map[string]interface{}{"slice/slice.go": readFile(t, "testdata/slice.go")},
-		},
-	})
-	prog, pkgs, _, err := loadAndBuildPackages(e, "/module/slice/slice.go")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	pkg := pkgs[0]
-	sources := map[*ssa.Function]bool{pkg.Func("Apply"): true, pkg.Func("Do"): true}
-	fs := funcsToString(forwardReachableFrom(sources, cha.CallGraph(prog)))
-	want := map[string]bool{
-		"Apply":   true,
-		"Apply$1": true,
-		"X":       true,
-		"Y":       true,
-		"Do":      true,
-		"Do$1":    true,
-		"Do$1$1":  true,
-		"debug":   true,
-		"A.Foo":   true,
-		"B.Foo":   true,
-	}
-	if !reflect.DeepEqual(want, fs) {
-		t.Errorf("want %v; got %v", want, fs)
-	}
-}
diff --git a/vulndb/internal/audit/testdata/a_dep.go b/vulndb/internal/audit/testdata/a_dep.go
deleted file mode 100644
index 56e3664..0000000
--- a/vulndb/internal/audit/testdata/a_dep.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// go:build ignore
-
-package A
-
-import (
-	"thirdparty.org/vulnerabilities/vuln"
-)
-
-type I interface {
-	Vuln()
-}
-
-func A1() I {
-	v := vuln.VulnData{}
-	v.Vuln() // vuln use
-	return v
-}
-
-func A2() func() {
-	return vuln.Vuln
-}
-
-func A3() func() {
-	return func() {}
-}
-
-type vulnWrap struct {
-	V I
-}
-
-func A4(f func(i I)) vulnWrap {
-	f(vuln.VulnData{})
-	return vulnWrap{}
-}
-
-func doWrap(i I) {
-	w := vulnWrap{}
-	w.V = i
-}
-
-// Part of a test program consisting of packages found
-// in top_package.go, b_dep.go, and vuln.go. For more
-// details, see testProgAndEnv function in helpers_test.go.
diff --git a/vulndb/internal/audit/testdata/b_dep.go b/vulndb/internal/audit/testdata/b_dep.go
deleted file mode 100644
index 2090059..0000000
--- a/vulndb/internal/audit/testdata/b_dep.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// go:build ignore
-
-package B
-
-import (
-	"a.org/A"
-)
-
-type internal struct{}
-
-func (i internal) Vuln() {}
-
-func B1() {
-	A.A1() // transitive vuln use but should not be reported
-	var i A.I
-	i = internal{}
-	i.Vuln() // no vuln use
-}
-
-// Part of a test program consisting of packages found in
-// vuln.go, a_dep.go, and b_dep.go. For more details, see
-// testProgAndEnv function in helpers_test.go.
diff --git a/vulndb/internal/audit/testdata/slice.go b/vulndb/internal/audit/testdata/slice.go
deleted file mode 100644
index 5fbbe68..0000000
--- a/vulndb/internal/audit/testdata/slice.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// go:build ignore
-
-package testdata
-
-func X() {}
-func Y() {}
-
-// not reachable
-func id(i int) int {
-	return i
-}
-
-// not reachable
-func inc(i int) int {
-	return i + 1
-}
-
-func Apply(b bool, h func()) {
-	if b {
-		func() {
-			print("applied")
-		}()
-		return
-	}
-	h()
-}
-
-type I interface {
-	Foo()
-}
-
-type A struct{}
-
-func (a A) Foo() {}
-
-// not reachable
-func (a A) Bar() {}
-
-type B struct{}
-
-func (b B) Foo() {}
-
-func debug(s string) {
-	print(s)
-}
-
-func Do(i I, input string) {
-	debug(input)
-
-	i.Foo()
-
-	func(x string) {
-		func(l int) {
-			print(l)
-		}(len(x))
-	}(input)
-}
diff --git a/vulndb/internal/audit/testdata/top_package.go b/vulndb/internal/audit/testdata/top_package.go
deleted file mode 100644
index 8b045b8..0000000
--- a/vulndb/internal/audit/testdata/top_package.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// go:build ignore
-
-package T
-
-import (
-	"a.org/A"
-	"b.org/B"
-	"thirdparty.org/vulnerabilities/vuln"
-)
-
-func T1(x bool) {
-	print(vuln.VG) // vuln use
-	if x {
-		A.A1().Vuln() // vuln use
-	} else {
-		B.B1() // no vuln use
-	}
-}
-
-func T2(x bool) {
-	if x {
-		A.A2()() // vuln use. The return value of A.A2() is stored in register t0
-	} else {
-		A.A3()()
-		w := A.A4(benign)
-		w.V.Vuln() // no vuln use with vta-vta
-	}
-}
-
-func benign(i A.I) {}
-
-// Part of a test program consisting of packages found in
-// vuln.go, a_dep.go, and b_dep.go. For more details,
-// see testProgAndEnv function in helpers_test.go
diff --git a/vulndb/internal/audit/testdata/vuln.go b/vulndb/internal/audit/testdata/vuln.go
deleted file mode 100644
index c981eff..0000000
--- a/vulndb/internal/audit/testdata/vuln.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// go:build ignore
-
-package vuln
-
-var VG int
-
-type VulnData struct{}
-
-func (v VulnData) Vuln() {}
-
-func Vuln() {
-	print(VG)
-}
-
-// Part of a test program consisting of packages found in
-// top_package.go, a_dep.go, and b_dep.go. For more details,
-// see testProgAndEnv function in helpers_test.go.
diff --git a/vulndb/internal/audit/utils.go b/vulndb/internal/audit/utils.go
deleted file mode 100644
index 76394ef..0000000
--- a/vulndb/internal/audit/utils.go
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"bytes"
-	"fmt"
-	"go/token"
-	"go/types"
-	"strings"
-
-	"golang.org/x/tools/go/callgraph"
-	"golang.org/x/tools/go/types/typeutil"
-
-	"golang.org/x/tools/go/ssa"
-
-	"golang.org/x/vuln/osv"
-)
-
-// instrPosition gives the position of `instr`. Returns empty token.Position
-// if no file information on `instr` is available.
-func instrPosition(instr ssa.Instruction) *token.Position {
-	pos := instr.Parent().Prog.Fset.Position(instr.Pos())
-	return &pos
-}
-
-// valPosition gives the position of `v` inside of `f`. Assumes `v` is used in
-// `f`. Returns empty token.Position if no file information on `f` is available.
-func valPosition(v ssa.Value, f *ssa.Function) *token.Position {
-	pos := f.Prog.Fset.Position(v.Pos())
-	return &pos
-}
-
-// funcPosition gives the position of `f`. Returns empty token.Position
-// if no file information on `f` is available.
-func funcPosition(f *ssa.Function) *token.Position {
-	pos := f.Prog.Fset.Position(f.Pos())
-	return &pos
-}
-
-// siteCallees computes a set of callees for call site `call` given program `callgraph`.
-func siteCallees(call ssa.CallInstruction, callgraph *callgraph.Graph) []*ssa.Function {
-	var matches []*ssa.Function
-
-	node := callgraph.Nodes[call.Parent()]
-	if node == nil {
-		return nil
-	}
-
-	for _, edge := range node.Out {
-		callee := edge.Callee.Func
-		// Some callgraph analyses, such as CHA, might return synthetic (interface)
-		// methods as well as the concrete methods. Skip such synthetic functions.
-		if edge.Site == call {
-			matches = append(matches, callee)
-		}
-	}
-	return matches
-}
-
-func callName(call ssa.CallInstruction) string {
-	if !call.Common().IsInvoke() {
-		return fmt.Sprintf("%s.%s", call.Parent().Pkg.Pkg.Path(), call.Common().Value.Name())
-	}
-	buf := new(bytes.Buffer)
-	types.WriteType(buf, call.Common().Value.Type(), nil)
-	return fmt.Sprintf("%s.%s", buf, call.Common().Method.Name())
-}
-
-func unresolved(call ssa.CallInstruction) bool {
-	if call == nil {
-		return false
-	}
-	return call.Common().StaticCallee() == nil
-}
-
-// pkgsProgram returns the single common program to which all pkgs belong, if such.
-// Otherwise, returns nil.
-func pkgsProgram(pkgs []*ssa.Package) *ssa.Program {
-	var prog *ssa.Program
-	for _, pkg := range pkgs {
-		if prog == nil {
-			prog = pkg.Prog
-		} else if prog != pkg.Prog {
-			return nil
-		}
-	}
-	return prog
-}
-
-// globalUses returns a list of global uses by an instruction.
-// Global function callees are disregarded as they are preferred as call uses.
-func globalUses(instr ssa.Instruction) []*ssa.Value {
-	ops := instr.Operands(nil)
-	if _, ok := instr.(ssa.CallInstruction); ok {
-		ops = ops[1:]
-	}
-
-	var glbs []*ssa.Value
-	for _, o := range ops {
-		if _, ok := (*o).(*ssa.Global); ok {
-			glbs = append(glbs, o)
-		}
-	}
-	return glbs
-}
-
-// Computes function name consistent with the function namings used in vulnerability
-// databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
-//
-// Examples:
-//   func (a A) foo (...) {...}  -> A.foo
-//   func foo(...) {...}         -> foo
-//   func (b *B) bar (...) {...} -> B.bar
-func dbFuncName(f *ssa.Function) string {
-	var typeFormat func(t types.Type) string
-	typeFormat = func(t types.Type) string {
-		switch tt := t.(type) {
-		case *types.Pointer:
-			return typeFormat(tt.Elem())
-		case *types.Named:
-			return tt.Obj().Name()
-		default:
-			return types.TypeString(t, func(p *types.Package) string { return "" })
-		}
-	}
-	selectBound := func(f *ssa.Function) types.Type {
-		// If f is a "bound" function introduced by ssa for a given type, return the type.
-		// When "f" is a "bound" function, it will have 1 free variable of that type within
-		// the function. This is subject to change when ssa changes.
-		if len(f.FreeVars) == 1 && strings.HasPrefix(f.Synthetic, "bound ") {
-			return f.FreeVars[0].Type()
-		}
-		return nil
-	}
-	selectThunk := func(f *ssa.Function) types.Type {
-		// If f is a "thunk" function introduced by ssa for a given type, return the type.
-		// When "f" is a "thunk" function, the first parameter will have that type within
-		// the function. This is subject to change when ssa changes.
-		params := f.Signature.Params() // params.Len() == 1 then params != nil.
-		if strings.HasPrefix(f.Synthetic, "thunk ") && params.Len() >= 1 {
-			if first := params.At(0); first != nil {
-				return first.Type()
-			}
-		}
-		return nil
-	}
-	var qprefix string
-	if recv := f.Signature.Recv(); recv != nil {
-		qprefix = typeFormat(recv.Type())
-	} else if btype := selectBound(f); btype != nil {
-		qprefix = typeFormat(btype)
-	} else if ttype := selectThunk(f); ttype != nil {
-		qprefix = typeFormat(ttype)
-	}
-
-	if qprefix == "" {
-		return f.Name()
-	}
-	return qprefix + "." + f.Name()
-}
-
-// memberFuncs returns functions associated with the `member`:
-// 1) `member` itself if `member` is a function
-// 2) `member` methods if `member` is a type
-// 3) empty list otherwise
-func memberFuncs(member ssa.Member, prog *ssa.Program) []*ssa.Function {
-	switch t := member.(type) {
-	case *ssa.Type:
-		methods := typeutil.IntuitiveMethodSet(t.Type(), &prog.MethodSets)
-		var funcs []*ssa.Function
-		for _, m := range methods {
-			if f := prog.MethodValue(m); f != nil {
-				funcs = append(funcs, f)
-			}
-		}
-		return funcs
-	case *ssa.Function:
-		return []*ssa.Function{t}
-	default:
-		return nil
-	}
-}
-
-// Returns the path of a package `f` belongs to. Covers both
-// the case when `f` is an anonymous and a synthetic function.
-func pkgPath(f *ssa.Function) string {
-	// Handle all user defined functions.
-	if p := f.Package(); p != nil && p.Pkg != nil {
-		return p.Pkg.Path()
-	}
-	// Cover synthetic functions as well.
-	if o := f.Object(); o != nil && o.Pkg() != nil {
-		return o.Pkg().Path()
-	}
-	// Not reachable in principle.
-	return ""
-}
-
-// serialize transforms []*osv.Entry into []osv.Entry as to
-// allow serialization of Finding.
-func serialize(vulns []*osv.Entry) []osv.Entry {
-	var vs []osv.Entry
-	for _, v := range vulns {
-		vs = append(vs, *v)
-	}
-	return vs
-}
diff --git a/vulndb/internal/audit/vulnerability.go b/vulndb/internal/audit/vulnerability.go
deleted file mode 100644
index ea1125c..0000000
--- a/vulndb/internal/audit/vulnerability.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"go/build"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/client"
-)
-
-// FetchVulnerabilities fetches vulnerabilities that affect the supplied modules.
-func FetchVulnerabilities(client client.Client, modules []*packages.Module) (ModuleVulnerabilities, error) {
-	mv := ModuleVulnerabilities{}
-	for _, mod := range modules {
-		modPath := mod.Path
-		if mod.Replace != nil {
-			modPath = mod.Replace.Path
-		}
-
-		// skip loading vulns for local imports
-		if isLocal(mod) {
-			// TODO: what if client has its own db
-			// with local vulns?
-			continue
-		}
-		vulns, err := client.GetByModule(modPath)
-		if err != nil {
-			return nil, err
-		}
-		if len(vulns) == 0 {
-			continue
-		}
-		mv = append(mv, modVulns{
-			mod:   mod,
-			vulns: vulns,
-		})
-	}
-	return mv, nil
-}
-
-func isLocal(mod *packages.Module) bool {
-	modDir := mod.Dir
-	if mod.Replace != nil {
-		modDir = mod.Replace.Dir
-	}
-	return modDir != "" && !strings.HasPrefix(modDir, modCacheDirectory())
-}
-
-func modCacheDirectory() string {
-	var modCacheDir string
-	// TODO: define modCacheDir using cmd/go/internal/cfg.GOMODCACHE
-	if modCacheDir = os.Getenv("GOMODCACHE"); modCacheDir == "" {
-		if modCacheDir = os.Getenv("GOPATH"); modCacheDir == "" {
-			modCacheDir = build.Default.GOPATH
-		}
-		modCacheDir = filepath.Join(modCacheDir, "pkg", "mod")
-	}
-	return modCacheDir
-}
diff --git a/vulndb/internal/audit/vulnerability_test.go b/vulndb/internal/audit/vulnerability_test.go
deleted file mode 100644
index 5761772..0000000
--- a/vulndb/internal/audit/vulnerability_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2021 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 audit
-
-import (
-	"reflect"
-	"testing"
-
-	"golang.org/x/tools/go/packages"
-	"golang.org/x/vuln/client"
-	"golang.org/x/vuln/osv"
-)
-
-type mockClient struct {
-	client.Client
-	ret map[string][]*osv.Entry
-}
-
-func (mc *mockClient) GetByModule(a string) ([]*osv.Entry, error) {
-	return mc.ret[a], nil
-}
-
-func TestFetchVulnerabilities(t *testing.T) {
-	mc := &mockClient{
-		ret: map[string][]*osv.Entry{
-			"example.mod/a": {{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}}},
-			"example.mod/b": {{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.1.1"}}}}}}}},
-			"example.mod/d": {{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}}},
-			"example.mod/e": {{ID: "e", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/e"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.2.0"}}}}}}}},
-		},
-	}
-
-	mv, err := FetchVulnerabilities(mc, []*packages.Module{
-		{Path: "example.mod/a", Dir: modCacheDirectory(), Version: "v1.0.0"},
-		{Path: "example.mod/b", Dir: modCacheDirectory(), Version: "v1.0.4"},
-		{Path: "example.mod/c", Replace: &packages.Module{Path: "example.mod/d", Dir: modCacheDirectory(), Version: "v1.0.0"}, Version: "v2.0.0"},
-		{Path: "example.mod/e", Replace: &packages.Module{Path: "../local/example.mod/d", Dir: modCacheDirectory(), Version: "v1.0.1"}, Version: "v2.1.0"},
-	})
-	if err != nil {
-		t.Fatalf("FetchVulnerabilities failed: %s", err)
-	}
-
-	expected := ModuleVulnerabilities{
-		{
-			mod: &packages.Module{Path: "example.mod/a", Dir: modCacheDirectory(), Version: "v1.0.0"},
-			vulns: []*osv.Entry{
-				{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{Path: "example.mod/b", Dir: modCacheDirectory(), Version: "v1.0.4"},
-			vulns: []*osv.Entry{
-				{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.1.1"}}}}}}},
-			},
-		},
-		{
-			mod: &packages.Module{Path: "example.mod/c", Replace: &packages.Module{Path: "example.mod/d", Dir: modCacheDirectory(), Version: "v1.0.0"}, Version: "v2.0.0"},
-			vulns: []*osv.Entry{
-				{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
-			},
-		},
-	}
-	if !reflect.DeepEqual(mv, expected) {
-		t.Fatalf("FetchVulnerabilities returned unexpected results, got:\n%s\nwant:\n%s", moduleVulnerabilitiesToString(mv), moduleVulnerabilitiesToString(expected))
-	}
-}
diff --git a/vulndb/internal/binscan/exe.go b/vulndb/internal/binscan/exe.go
deleted file mode 100644
index e705ebe..0000000
--- a/vulndb/internal/binscan/exe.go
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2021 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 binscan
-
-// This file is a somewhat modified version of cmd/go/internal/version/exe.go
-// that adds functionality for extracting the PCLN table.
-
-import (
-	"bytes"
-	"debug/elf"
-	"debug/macho"
-	"debug/pe"
-	"encoding/binary"
-	"fmt"
-
-	// "internal/xcoff"
-	"io"
-	"os"
-)
-
-// An exe is a generic interface to an OS executable (ELF, Mach-O, PE, XCOFF).
-type exe interface {
-	// Close closes the underlying file.
-	Close() error
-
-	// ReadData reads and returns up to size byte starting at virtual address addr.
-	ReadData(addr, size uint64) ([]byte, error)
-
-	// DataStart returns the writable data segment start address.
-	DataStart() uint64
-
-	PCLNTab() ([]byte, uint64)
-}
-
-// openExe opens file and returns it as an exe.
-func openExe(file string) (exe, error) {
-	f, err := os.Open(file)
-	if err != nil {
-		return nil, err
-	}
-	data := make([]byte, 16)
-	if _, err := io.ReadFull(f, data); err != nil {
-		return nil, err
-	}
-	f.Seek(0, 0)
-	if bytes.HasPrefix(data, []byte("\x7FELF")) {
-		e, err := elf.NewFile(f)
-		if err != nil {
-			f.Close()
-			return nil, err
-		}
-		return &elfExe{f, e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("MZ")) {
-		e, err := pe.NewFile(f)
-		if err != nil {
-			f.Close()
-			return nil, err
-		}
-		return &peExe{f, e}, nil
-	}
-	if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
-		e, err := macho.NewFile(f)
-		if err != nil {
-			f.Close()
-			return nil, err
-		}
-		return &machoExe{f, e}, nil
-	}
-	// TODO(rolandshoemaker): we cannot support XCOFF files due to the usage of internal/xcoff.
-	// Once this code is moved into the stdlib, this support can be re-enabled.
-	// if bytes.HasPrefix(data, []byte{0x01, 0xDF}) || bytes.HasPrefix(data, []byte{0x01, 0xF7}) {
-	// 	e, err := xcoff.NewFile(f)
-	// 	if err != nil {
-	// 		f.Close()
-	// 		return nil, err
-	// 	}
-	// 	return &xcoffExe{f, e}, nil
-
-	// }
-	return nil, fmt.Errorf("unrecognized executable format")
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
-	os *os.File
-	f  *elf.File
-}
-
-func (x *elfExe) Close() error {
-	return x.os.Close()
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, prog := range x.f.Progs {
-		if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
-			n := prog.Vaddr + prog.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *elfExe) DataStart() uint64 {
-	for _, s := range x.f.Sections {
-		if s.Name == ".go.buildinfo" {
-			return s.Addr
-		}
-	}
-	for _, p := range x.f.Progs {
-		if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
-			return p.Vaddr
-		}
-	}
-	return 0
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
-	var offset uint64
-	text := x.f.Section(".text")
-	if text != nil {
-		offset = text.Offset
-	}
-	pclntab := x.f.Section(".gopclntab")
-	if pclntab == nil {
-		pclntab = x.f.Section(".data.rel.ro.gopclntab")
-		if pclntab == nil {
-			pclntab = x.f.Section(".data.rel.ro")
-			if pclntab == nil {
-				return nil, 0
-			}
-			// Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
-			// its own section header. We can search for for the start by looking for the four
-			// byte magic and the go magic.
-			b, err := pclntab.Data()
-			if err != nil {
-				return nil, 0
-			}
-			// TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
-			// actually correct. During testing it worked, but that may be because I got lucky
-			// with the binary I was using, and we need to do four byte jumps to exhaustively
-			// search the section?
-			for i := 0; i < len(b); i += 16 {
-				if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
-					(b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
-					(b[i+7] == 4 || b[i+7] == 8) {
-					// Also check for the go magic
-					leMagic := binary.LittleEndian.Uint32(b[i:])
-					beMagic := binary.BigEndian.Uint32(b[i:])
-					switch {
-					case leMagic == go12magic:
-						fallthrough
-					case beMagic == go12magic:
-						fallthrough
-					case leMagic == go116magic:
-						fallthrough
-					case beMagic == go116magic:
-						return b[i:], offset
-					}
-				}
-			}
-		}
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, offset
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
-	os *os.File
-	f  *pe.File
-}
-
-func (x *peExe) Close() error {
-	return x.os.Close()
-}
-
-func (x *peExe) imageBase() uint64 {
-	switch oh := x.f.OptionalHeader.(type) {
-	case *pe.OptionalHeader32:
-		return uint64(oh.ImageBase)
-	case *pe.OptionalHeader64:
-		return oh.ImageBase
-	}
-	return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
-	addr -= x.imageBase()
-	for _, sect := range x.f.Sections {
-		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-			n := uint64(sect.VirtualAddress+sect.Size) - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *peExe) DataStart() uint64 {
-	// Assume data is first writable section.
-	const (
-		IMAGE_SCN_CNT_CODE               = 0x00000020
-		IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
-		IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
-		IMAGE_SCN_MEM_EXECUTE            = 0x20000000
-		IMAGE_SCN_MEM_READ               = 0x40000000
-		IMAGE_SCN_MEM_WRITE              = 0x80000000
-		IMAGE_SCN_MEM_DISCARDABLE        = 0x2000000
-		IMAGE_SCN_LNK_NRELOC_OVFL        = 0x1000000
-		IMAGE_SCN_ALIGN_32BYTES          = 0x600000
-	)
-	for _, sect := range x.f.Sections {
-		if sect.VirtualAddress != 0 && sect.Size != 0 &&
-			sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
-			return uint64(sect.VirtualAddress) + x.imageBase()
-		}
-	}
-	return 0
-}
-
-func (x *peExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	for _, section := range x.f.Sections {
-		if section.Name == ".text" {
-			textOffset = uint64(section.Offset)
-			break
-		}
-	}
-	var start, end int64
-	var section int
-	for _, symbol := range x.f.Symbols {
-		if symbol.Name == "runtime.pclntab" {
-			start = int64(symbol.Value)
-			section = int(symbol.SectionNumber - 1)
-		} else if symbol.Name == "runtime.epclntab" {
-			end = int64(symbol.Value)
-			break
-		}
-	}
-	if start == 0 || end == 0 {
-		return nil, 0
-	}
-	offset := int64(x.f.Sections[section].Offset) + start
-	size := end - start
-
-	pclntab := make([]byte, size)
-	if _, err := x.os.ReadAt(pclntab, offset); err != nil {
-		return nil, 0
-	}
-
-	return pclntab, textOffset
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
-	os *os.File
-	f  *macho.File
-}
-
-func (x *machoExe) Close() error {
-	return x.os.Close()
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if !ok {
-			continue
-		}
-		if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
-			if seg.Name == "__PAGEZERO" {
-				continue
-			}
-			n := seg.Addr + seg.Filesz - addr
-			if n > size {
-				n = size
-			}
-			data := make([]byte, n)
-			_, err := seg.ReadAt(data, int64(addr-seg.Addr))
-			if err != nil {
-				return nil, err
-			}
-			return data, nil
-		}
-	}
-	return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *machoExe) DataStart() uint64 {
-	// Look for section named "__go_buildinfo".
-	for _, sec := range x.f.Sections {
-		if sec.Name == "__go_buildinfo" {
-			return sec.Addr
-		}
-	}
-	// Try the first non-empty writable segment.
-	const RW = 3
-	for _, load := range x.f.Loads {
-		seg, ok := load.(*macho.Segment)
-		if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
-			return seg.Addr
-		}
-	}
-	return 0
-}
-
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
-	var textOffset uint64
-	text := x.f.Section("__text")
-	if text != nil {
-		textOffset = uint64(text.Offset)
-	}
-	pclntab := x.f.Section("__gopclntab")
-	if pclntab == nil {
-		return nil, 0
-	}
-	b, err := pclntab.Data()
-	if err != nil {
-		return nil, 0
-	}
-	return b, textOffset
-}
-
-// TODO(rolandshoemaker): we cannot support XCOFF files due to the usage of internal/xcoff.
-// Once this code is moved into the stdlib, this support can be re-enabled.
-
-// // xcoffExe is the XCOFF (AIX eXtended COFF) implementation of the exe interface.
-// type xcoffExe struct {
-// 	os *os.File
-// 	f  *xcoff.File
-// }
-//
-// func (x *xcoffExe) Close() error {
-// 	return x.os.Close()
-// }
-//
-// func (x *xcoffExe) ReadData(addr, size uint64) ([]byte, error) {
-// 	for _, sect := range x.f.Sections {
-// 		if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-// 			n := uint64(sect.VirtualAddress+sect.Size) - addr
-// 			if n > size {
-// 				n = size
-// 			}
-// 			data := make([]byte, n)
-// 			_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-// 			if err != nil {
-// 				return nil, err
-// 			}
-// 			return data, nil
-// 		}
-// 	}
-// 	return nil, fmt.Errorf("address not mapped")
-// }
-//
-// func (x *xcoffExe) DataStart() uint64 {
-// 	return x.f.SectionByType(xcoff.STYP_DATA).VirtualAddress
-// }
diff --git a/vulndb/internal/binscan/scan.go b/vulndb/internal/binscan/scan.go
deleted file mode 100644
index a88740d..0000000
--- a/vulndb/internal/binscan/scan.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2021 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 binscan contains methods for parsing Go binary files for the purpose
-// of extracting module dependency and symbol table information.
-package binscan
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
-	"bytes"
-	"debug/gosym"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"net/url"
-	"runtime/debug"
-	"strings"
-
-	"golang.org/x/tools/go/packages"
-)
-
-// buildInfoMagic, findVers, and readString are copied from
-// cmd/go/internal/version
-
-// The build info blob left by the linker is identified by
-// a 16-byte header, consisting of buildInfoMagic (14 bytes),
-// the binary's pointer size (1 byte),
-// and whether the binary is big endian (1 byte).
-var buildInfoMagic = []byte("\xff Go buildinf:")
-
-// findVers finds and returns the Go version and module version information
-// in the executable x.
-func findVers(x exe) string {
-	// Read the first 64kB of text to find the build info blob.
-	text := x.DataStart()
-	data, err := x.ReadData(text, 64*1024)
-	if err != nil {
-		return ""
-	}
-	for ; !bytes.HasPrefix(data, buildInfoMagic); data = data[32:] {
-		if len(data) < 32 {
-			return ""
-		}
-	}
-
-	// Decode the blob.
-	ptrSize := int(data[14])
-	bigEndian := data[15] != 0
-	var bo binary.ByteOrder
-	if bigEndian {
-		bo = binary.BigEndian
-	} else {
-		bo = binary.LittleEndian
-	}
-	var readPtr func([]byte) uint64
-	if ptrSize == 4 {
-		readPtr = func(b []byte) uint64 { return uint64(bo.Uint32(b)) }
-	} else {
-		readPtr = bo.Uint64
-	}
-	vers := readString(x, ptrSize, readPtr, readPtr(data[16:]))
-	if vers == "" {
-		return ""
-	}
-	mod := readString(x, ptrSize, readPtr, readPtr(data[16+ptrSize:]))
-	if len(mod) >= 33 && mod[len(mod)-17] == '\n' {
-		// Strip module framing.
-		mod = mod[16 : len(mod)-16]
-	} else {
-		mod = ""
-	}
-	return mod
-}
-
-// readString returns the string at address addr in the executable x.
-func readString(x exe, ptrSize int, readPtr func([]byte) uint64, addr uint64) string {
-	hdr, err := x.ReadData(addr, uint64(2*ptrSize))
-	if err != nil || len(hdr) < 2*ptrSize {
-		return ""
-	}
-	dataAddr := readPtr(hdr)
-	dataLen := readPtr(hdr[ptrSize:])
-	data, err := x.ReadData(dataAddr, dataLen)
-	if err != nil || uint64(len(data)) < dataLen {
-		return ""
-	}
-	return string(data)
-}
-
-// readBuildInfo is copied from runtime/debug
-func readBuildInfo(data string) (*debug.BuildInfo, bool) {
-	if len(data) == 0 {
-		return nil, false
-	}
-
-	const (
-		pathLine = "path\t"
-		modLine  = "mod\t"
-		depLine  = "dep\t"
-		repLine  = "=>\t"
-	)
-
-	readEntryFirstLine := func(elem []string) (debug.Module, bool) {
-		if len(elem) != 2 && len(elem) != 3 {
-			return debug.Module{}, false
-		}
-		sum := ""
-		if len(elem) == 3 {
-			sum = elem[2]
-		}
-		return debug.Module{
-			Path:    elem[0],
-			Version: elem[1],
-			Sum:     sum,
-		}, true
-	}
-
-	var (
-		info = &debug.BuildInfo{}
-		last *debug.Module
-		line string
-		ok   bool
-	)
-	// Reverse of cmd/go/internal/modload.PackageBuildInfo
-	for len(data) > 0 {
-		i := strings.IndexByte(data, '\n')
-		if i < 0 {
-			break
-		}
-		line, data = data[:i], data[i+1:]
-		switch {
-		case strings.HasPrefix(line, pathLine):
-			elem := line[len(pathLine):]
-			info.Path = elem
-		case strings.HasPrefix(line, modLine):
-			elem := strings.Split(line[len(modLine):], "\t")
-			last = &info.Main
-			*last, ok = readEntryFirstLine(elem)
-			if !ok {
-				return nil, false
-			}
-		case strings.HasPrefix(line, depLine):
-			elem := strings.Split(line[len(depLine):], "\t")
-			last = new(debug.Module)
-			info.Deps = append(info.Deps, last)
-			*last, ok = readEntryFirstLine(elem)
-			if !ok {
-				return nil, false
-			}
-		case strings.HasPrefix(line, repLine):
-			elem := strings.Split(line[len(repLine):], "\t")
-			if len(elem) != 3 {
-				return nil, false
-			}
-			if last == nil {
-				return nil, false
-			}
-			last.Replace = &debug.Module{
-				Path:    elem[0],
-				Version: elem[1],
-				Sum:     elem[2],
-			}
-			last = nil
-		}
-	}
-	return info, true
-}
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
-	packagesModules := make([]*packages.Module, len(debugModules))
-	for i, mod := range debugModules {
-		packagesModules[i] = &packages.Module{
-			Path:    mod.Path,
-			Version: mod.Version,
-		}
-		if mod.Replace != nil {
-			packagesModules[i].Replace = &packages.Module{
-				Path:    mod.Replace.Path,
-				Version: mod.Replace.Version,
-			}
-		}
-	}
-	return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts the symbols, packages, and their associated module versions
-// from a Go binary. Stripped binaries are not supported.
-func ExtractPackagesAndSymbols(binPath string) ([]*packages.Module, map[string][]string, error) {
-	x, err := openExe(binPath)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	pclntab, textOffset := x.PCLNTab()
-	if pclntab == nil {
-		// TODO(roland): if we have build information, but not PCLN table, we should be able to
-		// fall back to much higher granularity vulnerability checking.
-		return nil, nil, errors.New("unable to load the PCLN table")
-	}
-	lineTab := gosym.NewLineTable(pclntab, textOffset)
-	if lineTab == nil {
-		return nil, nil, errors.New("invalid line table")
-	}
-	tab, err := gosym.NewTable(nil, lineTab)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	packageSymbols := map[string][]string{}
-	for _, f := range tab.Funcs {
-		if f.Func == nil {
-			continue
-		}
-		symName := f.Func.BaseName()
-		if r := f.Func.ReceiverName(); r != "" {
-			if strings.HasPrefix(r, "(*") {
-				r = strings.Trim(r, "(*)")
-			}
-			symName = fmt.Sprintf("%s.%s", r, symName)
-		}
-
-		pkgName := f.Func.PackageName()
-		if pkgName == "" {
-			continue
-		}
-		pkgName, err := url.PathUnescape(pkgName)
-		if err != nil {
-			return nil, nil, err
-		}
-
-		packageSymbols[pkgName] = append(packageSymbols[pkgName], symName)
-	}
-
-	bi, ok := readBuildInfo(findVers(x))
-	if !ok {
-		return nil, nil, err
-	}
-
-	return debugModulesToPackagesModules(bi.Deps), packageSymbols, nil
-}