Sonatype Scan Gradle
Official plugin for scanning Gradle project dependencies using IQ Server.
The Sonatype for Gradle plugin is available on the Gradle Plugin Portal and Maven Central.
Supported Programming Languages
Java
Kotlin
Scala
Groovy
Using Sonatype Scan Gradle
Create/Clone/Download any Gradle project.
Edit the
build.gradlefile by adding the following:plugins { id 'org.sonatype.gradle.plugins.scan' version '4.0.0' // Update the version as needed }Or
build.gradle.kts:plugins { id ("org.sonatype.gradle.plugins.scan") version "4.0.0" // Update the version as needed }
Note
Run the plugin tasks with the log level set to INFO using -i or --info to display results in the console:
./gradlew ossIndexAudit --info ./gradlew nexusIQScan --info
IQ Server Scan Task Usage
Start a local instance of IQ Server, or get the URL and credentials of a remote one.
Configure IQ Server settings inside the
nexusIQScanconfiguration on the filebuild.gradlee.g.Groovy:
nexusIQScan { username = 'admin' password = 'pass' serverUrl = 'http://localhost:8070' applicationId = 'app' organizationId = 'orgId' stage = 'build' allConfigurations = false resultFilePath = 'results.json' modulesExcluded = ['module-1', 'module-2'] dirExcludes = 'some-ant-pattern' dirIncludes = 'some-ant-pattern' variantAttributes = ['com.android.build.api.attributes.ProductFlavor:version': 'prod'] scanTargets = ['package-lock.json', '**/*.lock'] excludeCompileOnly = true }Kotlin:
nexusIQScan { username = "admin" password = "pass" serverUrl = "http://localhost:8070" applicationId = "app" organizationId = "orgId" stage = "build" isAllConfigurations = false resultFilePath = "results.json" modulesExcluded = listOf("module-1", "module-2") dirExcludes = "some-ant-pattern" dirIncludes = "some-ant-pattern" variantAttributes = mapOf("com.android.build.api.attributes.ProductFlavor:version" to "prod") scanTargets = listOf("package-lock.json", "**/*.lock") excludeCompileOnly = true }Open the console on the project's root and run
gradle nexusIQScanor./gradlew nexusIQScan. You should see the scan report URL.
Supported Task Properties
Property | Required | Description |
|---|---|---|
| yes | IQ Server username. Make sure to use a user with the role 'Application Evaluator' in the given IQ Server application. |
| yes | IQ Server password. |
| yes | IQ Server URL. |
| yes | IQ Server application ID. |
| no | IQ Server organization ID. If provided, a validation will be done to check if the given application ID exists under the organization ID (please note this is different from the organization name). If the application doesn't exist, then it will be created under the organization. |
| no | IQ Server stage. Default value: build. |
| no | If set to true, the scan includes the dependencies in all resolvable configurations. By default is false, meaning only 'compileClasspath', 'runtimeClasspath', 'releaseCompileClasspath' and 'releaseRuntimeClasspath' are considered. |
| no | Path to a JSON file that will contain the results of the evaluation. |
| no | For multi-module projects, the names of the sub-modules to be excluded from scanning and evaluation. Default value: empty. |
| no | Comma separated ant-like glob patterns to select directories/archives that should be excluded. Suggested for Android projects: '**/classes.jar, **/annotations.zip, **/lint.jar, **/internal_impl-*.jar'. |
| no | Comma separated ant-like glob patterns to select directories/archives that should be examined. |
| no | For projects using multiple custom variants for the release distribution, a Map can be set with the attributes names and values to match the specific variant. See more at How to Deal with Multiple Release Variants. Use it only when the plugin can't match a variant on its own |
| no | Ant-like glob patterns for relative paths (to the project's folder) to select additional files to be scanned and evaluated. |
| no | If set to true then dependencies under the 'compileOnly' configuration will be ignored. Default value: false |
IQ Index Task Usage
Allows you to save information about the dependencies of a project into module information (module.xml) files that Sonatype CI tools can use to include these dependencies in a scan.
Open the console on the project's root and run
gradle nexusIQIndexor./gradlew nexusIQIndex.
For multi-module projects, you can configure a list of sub-modules to exclude from indexing.
Groovy:
nexusIQIndex {
modulesExcluded = ['module-1', 'module-2']
excludeCompileOnly = true
}Kotlin:
nexusIQIndex {
modulesExcluded = listOf("module-1", "module-2")
excludeCompileOnly = true
}Supported Task Properties
Property | Required | Description |
|---|---|---|
| no | For multi-module projects, the names of the sub-modules to be excluded from scanning and evaluation. Default value: empty |
| no | If set to true, dependencies under the 'compileOnly' configuration will be ignored. Default value: false |
OSS Index Audit Task Usage
OSS Index is transitioning to Sonatype Guide. OSS Index can be used without any extra configuration, but to avoid reaching the limit for anonymous queries every user is encouraged to review the OSS Index Migration to Sonatype Guide guidance and the Sonatype Guide + OSS Index | Evolving Open Source Intelligence page, and use this plugin with your credentials.
Cache can be configured optionally.
If you are using Groovy (build.gradle file):
ossIndexAudit {
username = 'email'
password = 'pass'
allConfigurations = false
useCache = true
cacheDirectory = 'some/path'
cacheExpiration = 'PT12H'
proxyConfiguration {
protocol = 'http'
host = 'proxy-host'
port = 8080
authConfiguration.username = 'username'
authConfiguration.password = 'password'
}
modulesIncluded = ['module-1', 'module-2']
modulesExcluded = ['module-1', 'module-2']
variantAttributes = ['com.android.build.api.attributes.ProductFlavor:version': 'prod']
excludeVulnerabilityIds = ['39d74cc8-457a-4e57-89ef-a258420138c5']
excludeCoordinates = ['commons-fileupload:commons-fileupload:1.3']
excludeCompileOnly = true
failOnDetection = true
outputFormat = 'DEFAULT'
cycloneDxComponentType = 'LIBRARY'
isColorEnabled = false
showAll = false
printBanner = true
}Or if you are using Kotlin (build.gradle.kts file):
ossIndexAudit {
username = "email"
password = "pass"
isAllConfigurations = false
isUseCache = true
cacheDirectory = "some/path"
cacheExpiration = "PT12H"
proxyConfiguration {
protocol = "http"
host = "proxy-host"
port = 8080
authConfiguration.username = "username"
authConfiguration.password = "password"
}
modulesIncluded = listOf("module-1", "module-2")
modulesExcluded = listOf("module-1", "module-2")
variantAttributes = mapOf("com.android.build.api.attributes.ProductFlavor:version" to "prod")
excludeVulnerabilityIds = listOf("39d74cc8-457a-4e57-89ef-a258420138c5")
excludeCoordinates = listOf("commons-fileupload:commons-fileupload:1.3")
excludeCompileOnly = true
failOnDetection = true
outputFormat = "DEFAULT"
cycloneDxComponentType = "LIBRARY"
isColorEnabled = false
isShowAll = false
isPrintBanner = true
}Open the console in the project's root and run:
gradle ossIndexAuditor./gradlew ossIndexAudit. You should see the audit result.
Supported Task Properties
Property | Required | Description |
|---|---|---|
| no | OSS Index username. If not provided, anonymous queries will be made. |
| no | OSS Index password. If not provided, anonymous queries will be made. |
| no | If true, the scan includes the dependencies in all resolvable configurations. By default is false, meaning only 'compileClasspath', 'runtimeClasspath', 'releaseCompileClasspath' and 'releaseRuntimeClasspath' are considered. |
| no | Default value: true. |
| no | By default it uses the user data directory (according to your OS). |
| no | It must follow the Joda Time specification at joda-time Duration specs. Default value: PT12H (12 hours) |
| no | Extra configuration when running behind a proxy without direct internet access. |
| no | It can be 'http' (default) or 'https'. |
| no | Hostname for the proxy. |
| no | Proxy port. |
| no | The username for the proxy authentication (if credentials are required). |
| no | The password for the proxy authentication (if credentials are required). |
| no | For multi-module projects, the names of the sub-modules to include for auditing. If not specified all modules are included. Default value: empty |
| no | For multi-module projects, the names of the sub-modules to be excluded from auditing. If not specified no modules are excluded. This value is processed after 'modulesIncluded' if both are specified. Default value: empty |
| no | For projects using multiple custom variants for the release distribution, a Map can be set with the attributes names and values to match the specific variant. See more at How to Deal with Multiple Release Variants. Use it only when the plugin can't match a variant on its own |
| no | The list containing vulnerabilityIDs to be ignored - ossIndexAudit can be configured to exclude vulnerabilities from matching. Default value: empty |
| no | The list contains the coordinates of components which, if vulnerable, should be ignored. Default value: empty |
| no | If set to true, dependencies under the 'compileOnly' configuration will be ignored. Default value: false |
| no | By default, the audit scan will fail the task/build if any vulnerabilities are found. Set this to 'false' to allow the task to succeed even when vulnerabilities are detected. Use this option only if you rely on an external tool to further process the output of this plugin (see below for output options). |
| no | Accepted values: 'DEFAULT', 'DEPENDENCY_GRAPH' - prints dependency graph showing direct/transitive dependencies, 'JSON_CYCLONE_DX_1_4' - prints a CycloneDX 1.4 SBOM in JSON format. Default value: DEFAULT |
| no | Only used when outputFormat = 'JSON_CYCLONE_DX_1_4' to define the type of component this project is for the BOM metadata with possible values: 'LIBRARY', 'APPLICATION', 'FRAMEWORK', 'CONTAINER', 'OPERATING_SYSTEM', 'DEVICE', 'FIRMWARE' and 'FILE'. Default value: LIBRARY |
| no | If set and outputFormat \= "DEFAULT", it prints vulnerability description in color. Default value: true |
| no | If true, it prints out all dependencies. Default value: false - only dependencies with vulnerabilities will be printed out. |
| no | If true, it will print an ASCII text banner. Default value: true |
Sensitive Data - Usage Example
Sometimes it's not desirable to keep sensitive data stored on build.gradle. For such cases it's possible to use project properties (-P arguments) or system properties (-D arguments or injected from a tool) from command line or environment variables when running the nexusIQScan or ossIndexAudit tasks.
Here is an example using project properties for the credentials.
Groovy:
nexusIQScan {
username = project['username']
password = project['password']
serverUrl = 'http://localhost:8070'
applicationId = 'app'
}
ossIndexAudit {
username = project['username']
password = project['password']
}Kotlin:
nexusIQScan {
username = project["username"]
password = project["password"]
serverUrl = "http://localhost:8070"
applicationId = "app"
}
ossIndexAudit {
username = project["username"]
password = project["password"]
}On command line:
./gradlew nexusIQScan -Pusername=admin -Ppassword=pass ./gradlew ossIndexAudit -Pusername=admin -Ppassword=pass
Each property name can be set as needed.
Here is an example using system properties for the credentials (Groovy):
nexusIQScan {
username = System.properties['username']
password = System.properties['password']
serverUrl = 'http://localhost:8070'
applicationId = 'app'
}
ossIndexAudit {
username = System.properties['username']
password = System.properties['password']
}As mentioned above the values can be set from the command line using -D arguments or injected via a tool (CI/CD for instance).
Finally, this is how environment variables can be used (usually values are injected from the local environment or by a CI tool).
Groovy:
nexusIQScan {
username = System.getenv('username')
password = System.getenv('password')
serverUrl = 'http://localhost:8070'
applicationId = 'app'
}
ossIndexAudit {
username = System.getenv('username')
password = System.getenv('password')
}Kotlin:
nexusIQScan {
username = System.getenv("username")
password = System.getenv("password")
serverUrl = "http://localhost:8070"
applicationId = "app"
}
ossIndexAudit {
username = System.getenv("username")
password = System.getenv("password")
}Multi-module projects
Just apply the plugin on the root project and all sub-modules will be processed and the output will be a single report with all components found in each module. This includes Android projects.
How to Deal with Multiple Release Variants
This plugin makes its best effort to find the release (production) configuration and variant to get the dependencies to analyze.
However, a Gradle project can have multiple custom release variants and the plugin might not be able to tell Gradle which one to pick, resulting in an error like this:
> Could not resolve all dependencies for configuration 'sonatypeCopyConfiguration0'.
> Could not resolve project :common-lib.
Required by:
project :app
> The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'release'. However we cannot choose between the following variants of project :baseapp:
- ciReleaseRuntimeElements
- prodReleaseRuntimeElements
All of them match the consumer attributes:
- Variant 'ciReleaseRuntimeElements' capability common-lib:1.0.0 declares a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'release':
- Unmatched attributes:
- Provides attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.2.2' but the consumer didn't ask for it
- Provides attribute 'com.android.build.api.attributes.ProductFlavor:version' with value 'ci' but the consumer didn't ask for it
- Provides attribute 'com.android.build.gradle.internal.attributes.VariantAttr' with value 'ciRelease' but the consumer didn't ask for it
- Provides a library but the consumer didn't ask for it
- Provides attribute 'org.gradle.jvm.environment' with value 'android' but the consumer didn't ask for it
- Variant 'prodReleaseRuntimeElements' capability common-lib:1.0.0 declares a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'release':
- Unmatched attributes:
- Provides attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.2.2' but the consumer didn't ask for it
- Provides attribute 'com.android.build.api.attributes.ProductFlavor:version' with value 'prod' but the consumer didn't ask for it
- Provides attribute 'com.android.build.gradle.internal.attributes.VariantAttr' with value 'prodRelease' but the consumer didn't ask for it
- Provides a library but the consumer didn't ask for it
- Provides attribute 'org.gradle.jvm.environment' with value 'android' but the consumer didn't ask for itFrom that output we can see the value of the attribute com.android.build.api.attributes.ProductFlavor:version can be used to distinguish between the available variants.
Since attribute names and values can be customized on each project, this plugin allows you to set the attributes needed to match the right variant using the property variantAttributes.
In the example above, the following configuration would allow the plugin to choose the prodReleaseRuntimeElements variant:
Groovy:
nexusIQScan {
variantAttributes = ['com.android.build.api.attributes.ProductFlavor:version': 'prod']
}
ossIndexAudit {
variantAttributes = ['com.android.build.api.attributes.ProductFlavor:version': 'prod']
}Kotlin:
nexusIQScan {
variantAttributes = mapOf("com.android.build.api.attributes.ProductFlavor:version" to "prod")
}
ossIndexAudit {
variantAttributes = mapOf("com.android.build.api.attributes.ProductFlavor:version" to "prod")
}For more information about attributes matching for variant selection, see: https://docs.gradle.org/current/userguide/variant_model.html#sec:variant-select-errors