@conterra/vuln-scan
v0.0.34
Published
con terra vulnerability scan process
Keywords
Readme
ct-vuln-scan
The utility is a wrapper around the following tools:
- grype - Vulnerability scanner for container images and filesystems.
- trivy - Comprehensive and versatile security scanner
- oss index - Free catalogue of open source components and scanning tools to help developers identify vulnerabilities
It also supports the OpenVex specification for vulnerability status and justification.
Pre-Requisites
You need to have docker and node/npm installed on your machine.
Installation
The utility is available as an npm package it can be installed globally or locally.
For global installation use:
$ npm install -g @conterra/vuln-scanFor local installation use:
$ npm install @conterra/vuln-scanor reference it in your package.json file:
{
"dependencies": {
"@conterra/vuln-scan": "<current version>"
}
}After that you have following commands available:
ct-vuln-scan- Triggers the vulnerability scan
ct-vuln-add-vex- Triggers a process to add a new vex statement to a file
ct-vuln-add-project- Adds a new project to the configuration file based on an existing project entry and adds it to all vex statements
ct-vuln-remove-project- Removes a project from the configuration file and all vex statements related to the project.
- Or removes a project from all vex statements matching a given vulnerability id.
Vulnerability scan
The ct-vuln-scan command can be used to scan one or many projects for vulnerabilities.
It uses the configured scanners to analyze a projects sbom file and produces aggregated results.
The sbom file can be provided as a local file or fetched from a maven repository.
You might for example prepare a folder structure like this:
/vuln-scan/ # root folder
├── vuln-scan-conf.json # configuration file for projects to scan
├── input # input to be processed by the scanners
│ └── sbom # sbom files
│ └── vex # vex files
│── output # folder for aggregated scan resultsRunning the command ct-vuln-scan from the root folder will scan all projects defined in the vuln-scan-conf.json file.
By default, output will created in the output folder per project.
In the output folder different files per project are generated, see below. There are also tow summary files directly in the output folder:
scan-summary.txt- A text file with a summary of the scan results.
- It contains the console "scan summary" output, which is printed to the console during the scan.
scan-summary.json- A json file with a summary of the scan results.
- This can be used to post-process the scan results or to integrate them into other tools.
- Example:
{ "errors": [{ "project": "[email protected]", "error": "Failed to fetch sbom file from maven repository: https://repository.conterra.de/repository/maven-mirror-ct/de/conterra/mapapps/ct-mapapps-rollout/4.18.2/ct-mapapps-rollout-4.18.2-sbom.cdx.json" }], "vulnerabilities": { "CVE-2025-48988": { "id": "CVE-2025-48988", "severity": "HIGH", "title": "tomcat: Apache Tomcat DoS in multipart upload", "description": "Allocation of Resources Without Limits or Throttling vulnerability in Apache Tomcat.\n\nThis issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.7, from 10.1.0-M1 through 10.1.41, from 9.0.0.M1 through 9.0.105.\n\nUsers are recommended to upgrade to version 11.0.8, 10.1.42 or 9.0.106, which fix the issue.", "components": [ "pkg:maven/org.apache.tomcat.embed/[email protected]" ], "refs": [ "https://avd.aquasec.com/nvd/cve-2025-48988", "https://github.com/advisories/GHSA-h3gc-qfqq-6h8f" ] }, "CVE-2025-49125": { "id": "CVE-2025-49125", "severity": "MEDIUM", "title": "tomcat: Apache Tomcat: Security constraint bypass for pre/post-resources", "description": "Authentication Bypass Using an Alternate Path or Channel vulnerability in Apache Tomcat. When using PreResources or PostResources mounted other than at the root of the web application, it was possible to access those resources via an unexpected path. That path was likely not to be protected by the same security constraints as the expected path, allowing those security constraints to be bypassed.\n\nThis issue affects Apache Tomcat: from 11.0.0-M1 through 11.0.7, from 10.1.0-M1 through 10.1.41, from 9.0.0.M1 through 9.0.105.\n\nUsers are recommended to upgrade to version 11.0.8, 10.1.42 or 9.0.106, which fix the issue.", "components": [ "pkg:maven/org.apache.tomcat.embed/[email protected]" ], "refs": [ "https://avd.aquasec.com/nvd/cve-2025-49125", "https://github.com/advisories/GHSA-wc4r-xq3c-5cf3" ] } }, "vulnerabilityToProject": { "CVE-2025-48988": [ "[email protected]" ], "CVE-2025-49125": [ "[email protected]" ] }, "projectToVulnerability": { "[email protected]": [ "CVE-2025-48988", "CVE-2025-49125" ] }, "noLongerDetectedVulnerabilities": { "CVE-2023-52070": [ "[email protected]", "[email protected]" ] } }
Configuration
You need to create a vuln-scan-conf.json file in the root of your project.
A minimal configuration file specifies only the project to scan:
{
"$schema": "./node_modules/@conterra/vuln-scan/dist/schema/conf-schema.json",
"projects": [
{
"name": "mapapps",
"version": "4.18.2",
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
"sbomFile": "./input/sboms/mapapps-4.18.2.cdx.json"
}
]
}The following sample lists all available options with their default values:
{
"$schema": "./node_modules/@conterra/vuln-scan/dist/schema/conf-schema.json",
/* Defines if the process should fail or only log a warning or ignore vulnerabilities.
If "fail" exit 1 is called.
If "warn" the log statement "##vso[task.complete result=SucceededWithIssues;] is issued.
If "ignore" nothing happens.
*/
"onNewVulnerabilities": "fail",
/* Defines if the process should fail or only log a warning or ignore no longer detected vulnerabilities.
If "fail" exit 1 is called.
If "warn" the log statement "##vso[task.complete result=SucceededWithIssues;] is issued.
If "ignore" nothing happens.
*/
"onNoLongerDetectedVulnerabilities": "ignore",
/* The maven repository to fetch sboms from.
If the maven repository requires authentication, the environment variables MAVEN_REPO_USER and MAVEN_REPO_PW must be set.
*/
"mavenRepo": "https://repository.conterra.de/repository/maven-mirror-ct",
/* The list of scanners to use. Possible values are "grype", "trivy" and "ossindex". */
"scanners": ["grype", "trivy", "ossindex"],
/* (optional) The list of vex files to download. Default is empty array. */
"vexUrls": [
"https://example.com/my-vex.json"
],
/* The directory where the vex files are stored. */
"vexDir": "./input/vex",
/* The directory where the scan results are written to. */
"outDir": "./output",
/* The directory where the cache of the grype and trivy is stored. Both tools maintain databases, which are downloaded and stored in the cache directory. */
"cacheDir": "./cache",
/* Flag if true then for each project a sub directory is created in the output directory.
If false all files are directly stored in the output dir without a subfolder structure.
*/
"createSubDirsForProject": true,
/* (optional) Defines how the console output is reported.
Possible values are:
- "BY_PROJECT_DETAILED" (default): order by project and print cve details
- "BY_PROJECT" : order by project but do not print cve details
- "BY_CVE" : order by cve and print cve details
- "BY_CVE_DETAILED": order by cve but do not print cve details
*/
"consoleReport": "BY_PROJECT_DETAILED",
/* The list of projects to scan. */
"projects": [
{
"name": "mapapps",
"version": "4.18.3",
/* identifier of the project in the vex files, used to filter the vex statements. */
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
/* The maven coordinates of the sbom file, used to download the file from the maven remote repository. */
"sbomMavenCoordinates": "de.conterra.mapapps:ct-mapapps-rollout:4.18.3:sbom"
},
{
"name": "mapapps",
"version": "4.18.2",
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
/* The location of the sbom file. */
"sbomFile": "./input/sboms/mapapps-4.18.2.cdx.json"
},
{
"name": "mapapps-sample-disabled",
"version": "4.17.0",
/* this project is disabled and not scanned */
"enabled": false,
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
"sbomFile": "./input/sboms/mapapps-4.17.0.cdx.json"
},
{
"name": "mapapps-sample-silent",
"version": "4.17.2",
/* this project is scanned, but detected vulnerabilities are ignored and will never break the build */
"silent": true,
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
"sbomFile": "./input/sboms/mapapps-4.17.2.cdx.json"
},
{
"name": "mapapps-sample-with-minium-severity",
"version": "4.17.2",
/* This project is scanned, but only vulnerabilities with a severity >= HIGH will break the build
Available values are: "CRITICAL", "HIGH", "MEDIUM", "LOW", "UNKNOWN"
*/
"minimumSeverity": "HIGH",
"purl": "pkg:maven/de.conterra.mapapps/[email protected]",
"sbomFile": "./input/sboms/mapapps-4.17.2.cdx.json"
}
]
}Usage - Scan
To scan all projects run following command in the directory where the configuration file is located:
$ ct-vuln-scanTo scan a specific project run following command:
$ ct-vuln-scan mapapps 4.18.2To scan all versions of a project run:
$ ct-vuln-scan mapappsYou may need following environment variables for a successful scan:
# (optional) to fetch sboms from maven repository
MAVEN_REPO_USER=[username]
MAVEN_REPO_PW=[password]
# (optional) for oss index authenticated api
OSS_INDEX_API_USER=[username]
OSS_INDEX_API_TOKEN=[token]
# (optional) for authentication downloading vex files specified by vexUrls option
VEX_URLS_USER=[username]
VEX_URLS_PW=[password]
# (optional) helps to fix the rate limit issue during downloading the trivy database from github
# See <https://aquasecurity.github.io/trivy/v0.38/docs/references/troubleshooting/#github-rate-limiting>
TRIVY_GITHUB_TOKEN=[token]
# (optional) to enable verbose logging, otherwise only scan results are printed
VERBOSE=true
# (optional) flag to enable automatic removal of unused statements in the vex files, during a scan.
AUTO_REMOVE_UNUSED_STATEMENTS=true
NOTE: This variables can be set in the .env file in the root of the project.
For each project following files are created in the output folder:
<project-name>-<project-version>-sbom.cdx.json- Copy of the sbom file.
<project-name>-<project-version>-scan-grype-results.json- Result of the grype scanner in the grype json format.
<project-name>-<project-version>-scan-trivy-results.json- Result of the trivy scanner in the trivy json format.
<project-name>-<project-version>-scan-ossindex-results.json- Result of the sonatype oss index api requests in json format.
<project-name>-<project-version>-scan-aggregated-results.json- Aggregations of the results of all scanners in an own
@conterra/vuln-scanjson format.
- Aggregations of the results of all scanners in an own
<project-name>-<project-version>-scan-aggregated-results.sarif.json- Aggregations of the results of all scanners in an own sarif json format.
<project-name>-<project-version>-openvex.vex.json- Aggregation of all vex statements available for the project.
If the createSubDirsForProject flag is set to true, the scanner will create a sub directory in the output folder named <project-name>-<project-version> for each project scanned.
Azure DevOps Pipelines Integration
Attach the output directory as build artifact CodeAnalysisLogs.
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: "output"
ArtifactName: "CodeAnalysisLogs"Make sure that your Azure DevOps organization has the extension SARIF SAST Scans Tab installed.
This extension visualizes the .sarif.json files which are part of the CodeAnalysisLogs.
If the configuration option failOnNewVulnerabilities flag is set to false, the pipeline will be set to SucceededWithIssues if vulnerabilities are found with no matching vex statement.
Otherwise the pipeline will be set to Failed (because of exit code 1).
Usage - Add Vex
This is a currently experimental maintenance workflow, where you want to make a decision if a vulnerability is affecting your project or not or if you currently investigating a vulnerability.
To add a new CVE-<>.json file in the vexDir, run:
$ ct-vuln-add-vexAnd follow the instructions.
This will create a new CVE-[id].json file in the vexDir folder.
A CVE-2023-52070.json file may look like this:
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "https://openvex.dev/docs/public/vex-fc763e6eb63bfbcda20b7cbbddd4e9f8feaaa317fe8d8a6f51a5663a1180343e",
"author": "conterra",
"timestamp": "2024-10-01T18:54:23.3233227+02:00",
"last_updated": "2024-10-01T19:58:13.2159221+02:00",
"version": 2,
"statements": [
{
"vulnerability": {
"name": "CVE-2023-52070"
},
"timestamp": "2024-10-01T19:58:13.2159221+02:00",
"products": [
{
"@id": "pkg:maven/de.conterra.mapapps/[email protected]"
},
{
"@id": "pkg:maven/de.conterra.mapapps/[email protected]"
}
],
"status": "not_affected",
"impact_statement": "Reported to JFreeChart library. The CVE was created by an LLM and valued by the JFreeChart team as invalid and bogus. See https://github.com/jfree/jfreechart/issues/396 for more information."
}
]
}For more information about the OpenVex specification, please refer to the OpenVex Spec.
Here some valid values for the status field:
| Status | Description | | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | not_affected | This product is known to be not affected by this vulnerability. | | affected | This product is known to be affected by this vulnerability. | | fixed | This product contains a fix for this vulnerability. | | under_investigation | It is not known yet whether these versions are or are not affected by the vulnerability. However, it is still under investigation. |
Here some valid values for the justification field (if status is not_affected):
| Justification | Description | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | component_not_present | The vulnerable component is not present in the product. | | vulnerable_code_not_present | The vulnerable code is not present. Typically this case occurs when source code is configured or built in a way that excludes the vulnerable code. | | vulnerable_code_not_in_execute_path | The vulnerable code can not be executed. Typically this case occurs when the product includes the vulnerable code but does not call or use the vulnerable code. | | vulnerable_code_cannot_be_controlled_by_adversary | The vulnerable code cannot be controlled by an attacker to exploit the vulnerability. | | inline_mitigations_already_exist | The product includes built-in protections or features that prevent exploitation of the vulnerability. These built-in protections cannot be subverted by the attacker and cannot be configured or disabled by the user. These mitigations completely prevent exploitation based on known attack vectors. |
Usage - Add Project
To add a new project to the configuration file and all vex statements, run:
$ ct-vuln-add-project <project-name> <project-version> <project-version-to-add>for example:
$ ct-vuln-add-project mapapps 4.18.2-SNAPSHOT 4.18.2This will add a new project entry mapapps with version 4.18.2 to the configuration file clone all options from the reference project mapapps with version 4.18.2-SNAPSHOT. It will also add the product-id to all vex statements, where the reference project it listed, too.
This is useful if you release a snapshot version.
Usage - Remove Project
To remove a project from the configuration file and all vex statements, run:
$ ct-vuln-remove-project <project-name> <project-version>for example:
$ ct-vuln-remove-project mapapps 4.18.2-SNAPSHOTThis will remove the project entry mapapps with version 4.18.2-SNAPSHOT from the configuration file and remove the product-id from all vex statements, where the project is listed.
Usage - Remove Project from vex files matching a vulnerability id
To remove a project from all vex statements matching a vulnerability id, run:
$ ct-vuln-remove-project <project-name> <project-version> <vuln-id>for example:
$ ct-vuln-remove-project mapapps 4.18.2-SNAPSHOT CVE-2024-38820This will remove the product-id from all vex statements matching the given vulnerability. This is useful if a vulnerability is no longer detected for a project and you like to remove an existing statement.
Usage - Simulate a version release with preparation of the next dev version
By combining the ct-vuln-add-project and ct-vuln-remove-project commands, you can simulate a version release.
For example, you have a project mapapps with version 4.18.3-SNAPSHOT and you want to release version 4.18.3
and prepare the next dev version 4.18.4-SNAPSHOT, then you can run following commands:
$ ct-vuln-add-project mapapps 4.18.3-SNAPSHOT 4.18.3
$ ct-vuln-remove-project mapapps 4.18.3-SNAPSHOT
$ ct-vuln-add-project mapapps 4.18.3 4.18.4-SNAPSHOTDev Notes
Setup:
- Checkout via git
- Run
pnpm install
Run tests (vitest): pnpm test (watch mode)
To run tests once (without watch), use pnpm test run.
Build the project (esbuild): pnpm run build (or watch)
