Go detection runs when one of the following files is found in the project:
go.mod
orgo.sum
Default Go detection depends on the following to successfully run:
- Go v1.11+.
Full dependency graph generation is supported if Go v1.11+ is present on the build agent. If no Go v1.11+ is present, fallback detection strategy is performed.
Go detection is performed by parsing output from executing
go list -mod=readonly -m -json all. To generate the graph, the command
go mod graph is executed. This only adds edges between the components
that were already registered by go list
.
The fallback detections trategy is known to overreport (see the known limitations). Read through the troubleshooting section for tips on how to ensure that the newer, more accurate default detection strategy runs successfully.
To force the fallback detection strategy, set the environment
variable: DisableGoCliScan=true
Go detection is performed by parsing any go.mod
or go.sum
found
under the scan directory.
Only root dependency information is generated in the fallback detection strategy. The full graph is not detected.
Go detection is performed by only scanning the go.mod
files. This
reduces over reporting dependencies. The go.mod
file contains all
dependencies, including transitive ones. [^3]
Similarly, no graph is generated.
The fallback detection strategy is known to overreport by nature of
parsing go.sum
files which contain historical component information.
If you are experiencing overdetection from go.sum
files or have
otherwise been made aware that you are using the fallback Go detection
strategy, search Component Detection output for the following to determine
what action is needed:
CD output | Solution |
---|---|
Go CLI was not found in the system |
Ensure that Go v1.17+ is installed |
#[error]Go CLI command "go list -m -json all" failed with error: |
Resolve go list errors |
Go cli scan was manually disabled, fallback strategy performed. |
Remove the DisableGoCliScan environment variable |
Timeouts in Go detection | Fetch Go modules |
If you do not believe that Go is used in your project but Go detection is running, it is likely that you need to clean up extraneous build files.
Install Go CLI tools v1.17+ and ensure that it is available at the Component Detection step.
If Go CLI tools are installed in a prior build step but Component Detection is not finding them, ensure that they are not cleaned up or installed inside a container.
Errors are logged in the Component Detection build task output and begin with
#[error]Go CLI command "go list -m -json all" failed with error:
. These errors
are typically caused by version resolution problems or incorrectly formatted go.mod
files.
The variable should not be set or should be set to false
.
If modules are not fetched, go list
will pull the modules and may
negatively impact performance at detection time.
If you are still experiencing timouts, the fallback strategy might be more appropriate for your project:
- Set
DisableGoCli=true
. - Run
go mod tidy
to clean yourgo.mod
andgo.sum
s to reduce overreporting. - Install Go v1.17+ to bypass go.sum scanning.
Go detection runs when a go.sum
or go.mod
file is encountered. If
you do not use Go in your project, search for the following in Component
Detection build output to find the paths to the Go files CD has detected.
Component Detection must be running in debug mode to see these logs:
##[debug]Found Go.mod:
or
##[debug]Found Go.sum:
When you have found the affected files, you may:
- Delete the files if they exist but are not necessary in your project.
- Add a clean-up step to your build to remove the files if they are generated prior to the Component Detection build step but are not related to your project.
- Exclude the directory if it should not be scanned by Component Detection.
-
If the default strategy is used and go modules are not present in the system before the detector is executed, the go cli will fetch all modules to generate the dependency graph. This will incur additional detector time execution.
-
Dev dependency tagging is not supported.
-
Go detection will fallback if no Go v1.11+ is present.
-
(Prior to Go 1.17) Due to the nature of
go.sum
containing references for all dependencies, including historical, no-longer-needed dependencies; the fallback strategy can result in over detection. Executing go mod tidy before detection via the fallback strategy is encouraged. -
Some legacy dependencies may report stale transitive dependencies in their manifests, in this case you can remove them safely from your binaries by using exclude directive.
If the environment variable DisableGoCliScan
is set to true
, the
Go detector forcibly executes the fallback strategy.
In the Go programming language, go.mod
and go.sum
files play a
vital role in managing dependencies and ensuring the reproducibility
and security of a Go project. These files are central to Go's module
system, introduced in Go version 1.11, which revolutionized how Go
manages external packages and dependencies.
The go.mod
file, short for "module file," is a fundamental component
of Go's module system.[^4] It serves several crucial purposes:
-
Module Definition: The
go.mod
file defines the module name, which uniquely identifies the project. The module name typically follows the format of a version control repository URL or a custom path, such asexample.com/myproject
. -
Dependency Declaration: Inside the
go.mod
file, you declare the specific versions of dependencies your project relies on. Dependencies are listed with their module paths and version constraints.go module example.com/myproject go 1.17 require ( github.com/somepackage v1.2.3 golang.org/x/someotherpackage v0.4.0 )
Here,
github.com/somepackage
andgolang.org/x/someotherpackage
are declared as project dependencies with specific version constraints. -
Semantic Versioning: Go uses Semantic Versioning (Semver) to specify version constraints for dependencies. You can specify constraints such as
v1.2.3
(exact version) or>=1.2.0, <2.0.0
(range of versions). -
Dependency Resolution: When you build your project or import new dependencies, Go uses the
go.mod
file to resolve and download the exact versions of dependencies that satisfy the specified constraints. -
Dependency Graph: The
go.mod
file implicitly constructs a dependency graph of your project's dependencies, allowing Go to ensure that all dependencies are compatible and can be built together.
The go.sum
file, short for "checksum file," is used for ensuring the
integrity and security of dependencies. It contains checksums
(cryptographic hashes) of specific versions of packages listed in the
go.mod
file.[^5] The go.sum
file serves the following purposes:
-
Cryptographic Verification: When Go downloads a package specified in the
go.mod
file, it verifies the downloaded package's integrity by comparing its checksum with the checksum recorded in thego.sum
file. If they don't match, it signals a potential security breach or data corruption. -
Dependency Pinning: The
go.sum
file pins the exact versions of dependencies used in the project. It ensures that the same package versions are consistently used across different builds and development environments, which aids in reproducibility. -
Security: By including checksums, the
go.sum
file helps protect against tampering with packages during transit or in case of compromised repositories. It adds a layer of trust in the packages being used.
Here's a simplified example of entries in a go.sum
file:
github.com/somepackage v1.2.3 h1:jh2u3r9z0wokljwesdczryhtnu1xf6wl4h7h2us9rj0=
github.com/anotherpackage v0.4.0 h1:rn2iw0z7liy6d87dwygfawxqvx86jxd4m8hkw6yaj88=
Each line contains the package path, version, and a cryptographic hash of the package contents.
-
Dependency Resolution: Dependency scanners use the information in
go.mod
to understand which packages and versions a Go project depends on. -
Security and Trust: The
go.sum
file ensures that dependencies are downloaded securely and have not been tampered with during transit. -
Build Reproducibility:
go.mod
andgo.sum
files contribute to build reproducibility by pinning exact versions of dependencies, making it possible to recreate the same build environment consistently.
The Go Component Detector follows a strategy that involves the following key steps:
-
File Discovery: The detector searches for go.mod and go.sum files within the project directory.
-
Filtering go.sum Files: The detector filters out go.sum files when there is no adjacent go.mod file or when the go.mod file specifies a Go version lower than 1.17. This filtering reduces the risk of over-reporting components. More on this later.
-
Go CLI Scanning (Optional): If the Go CLI (go) is available and not manually disabled, the detector attempts to use it to scan the project for dependencies and build a dependency graph. This step can significantly improve detection speed.
-
Fallback Detection: If Go CLI scanning is not possible or not successful, the detector falls back to parsing go.mod and go.sum files directly to identify components.
-
Parsing go.mod File: The detector parses the go.mod file to identify direct and transitive dependencies, recording their names and versions.
-
Parsing go.sum File: The detector parses the go.sum file, recording information about dependencies, including their names, versions, and hashes.
-
Dependency Graph Construction: If Go CLI scanning was successful, the detector constructs a dependency graph based on the information gathered. This graph helps identify relationships between components.
-
Recording Components: Throughout the detection process, the detector records identified components and their relationships.
-
Environment Variable Check: The detector checks for an environment variable (DisableGoCliScan) to determine whether Go CLI scanning should be disabled.
The logic for checking if the Go version present in the go.mod
file
is greater than or equal to 1.17 is relevant because it determines
whether the go.sum
file should be processed for detection.
This check is essential because Go introduced significant changes in
how it handles dependencies and the go.sum
file in Go version 1.17,
which have implications for dependency scanning.
Prior to Go 1.17, the go.mod
file primarily contained information
about direct dependencies, but it didn't include information about
transitive (indirect) dependencies. This made it challenging to
accurately detect and manage all dependencies in a project.
In Go 1.17 and later, Go introduced an important change: the go.mod
file now includes information about both direct and transitive
dependencies. This improvement enhances the clarity and completeness
of dependency information within the go.mod
file.
-
Accuracy of Dependency Detection: Checking the Go version in the
go.mod
file allows the Go Component Detector to determine whether the project is using the enhanced module system introduced in Go 1.17. If the Go version is 1.17 or higher, it indicates that thego.mod
file contains information about transitive dependencies. Processing this updatedgo.mod
file provides a more accurate and comprehensive view of the project's dependencies. -
Avoiding Over-Reporting: In projects using Go 1.17 and later, transitive dependencies are already listed in the
go.mod
file, and processing the correspondinggo.sum
file could lead to over-reporting components. By not processing thego.sum
file when it's not necessary (i.e., when thego.mod
file includes transitive dependencies), the detector avoids redundant or incorrect component detection. -
Minimizing Noise: Over-reporting components can result in unnecessary noise in the scan results.
The changes in the Go detector were validated by:
-
Unit tests: Sample
go.mod
andgo.sum
files were created and placed as unit tests. Other unit tests for go version less than 1.17 were still maintained to ensure there were no regressions. -
Local testing: Real
go.mod
andgo.sum
from the go CLI were created from a real test codebase and verified manually.
The main change for the go detector was not in the parsing of the
go.mod files, but rather simply filtering go.sum
files if an
adjacent go.mod
file specified a version higher than 1.17.