├── docs
├── SUPPORT.txt
├── NOTICE
├── CODE_OF_CONDUCT.md
└── CONTRIBUTING.md
├── .github
├── ISSUE_TEMPLATE.txt
├── PULL_REQUEST_TEMPLATE.txt
├── dependabot.yml
└── workflows
│ ├── jenkins-maven-cd.yaml
│ ├── jenkins-security-scan.yml
│ └── inspector-scan.yaml
├── .mvn
├── maven.config
└── extensions.xml
├── .gitignore
├── src
├── main
│ ├── resources
│ │ ├── index.jelly
│ │ └── com
│ │ │ └── amazon
│ │ │ └── inspector
│ │ │ └── jenkins
│ │ │ └── amazoninspectorbuildstep
│ │ │ └── AmazonInspectorBuilder
│ │ │ ├── help-credentialId.html
│ │ │ ├── help-isLicenseCollectionEnabled.html
│ │ │ ├── help-isEpssThresholdEnabled.html
│ │ │ ├── help-reportArtifactName.html
│ │ │ ├── help-isSeverityThresholdEnabled.html
│ │ │ ├── help-sbomgenSkipFiles.html
│ │ │ ├── help-isSuppressedCveEnabled.html
│ │ │ ├── help-isAutoFailCveEnabled.html
│ │ │ ├── help-archivePath.html
│ │ │ ├── help-awsCredentialId.html
│ │ │ ├── help-sbomgenSelection.html
│ │ │ ├── help-isThresholdEnabled.html
│ │ │ ├── help-autoFailCves.html
│ │ │ ├── help-suppressedCves.html
│ │ │ └── config.jelly
│ └── java
│ │ └── com
│ │ └── amazon
│ │ └── inspector
│ │ └── jenkins
│ │ └── amazoninspectorbuildstep
│ │ ├── models
│ │ ├── sbom
│ │ │ ├── Components
│ │ │ │ ├── Advisory.java
│ │ │ │ ├── Affect.java
│ │ │ │ ├── Reference.java
│ │ │ │ ├── Metadata.java
│ │ │ │ ├── Tool.java
│ │ │ │ ├── Source.java
│ │ │ │ ├── Property.java
│ │ │ │ ├── Rating.java
│ │ │ │ ├── Component.java
│ │ │ │ └── Vulnerability.java
│ │ │ ├── SbomData.java
│ │ │ └── Sbom.java
│ │ ├── html
│ │ │ ├── components
│ │ │ │ ├── ImageMetadata.java
│ │ │ │ ├── HtmlVulnerability.java
│ │ │ │ ├── SeverityValues.java
│ │ │ │ └── DockerVulnerability.java
│ │ │ └── HtmlData.java
│ │ └── requests
│ │ │ └── SdkRequests.java
│ │ ├── exception
│ │ ├── SbomgenNotFoundException.java
│ │ ├── MalformedScanOutputException.java
│ │ └── RetriesExceededLimitException.java
│ │ ├── csvconversion
│ │ ├── CsvData.java
│ │ └── CsvConverter.java
│ │ ├── utils
│ │ ├── Sanitizer.java
│ │ ├── InspectorRegions.java
│ │ ├── SbomgenProcessing.java
│ │ └── ConversionUtils.java
│ │ ├── sbomparsing
│ │ ├── Severity.java
│ │ ├── SeverityCounts.java
│ │ └── SbomOutputParser.java
│ │ ├── html
│ │ ├── HtmlJarHandler.java
│ │ └── HtmlConversionUtils.java
│ │ └── sbomgen
│ │ ├── DownloaderCallable.java
│ │ ├── SbomgenUtils.java
│ │ ├── SbomgenDownloader.java
│ │ └── SbomgenRunner.java
└── test
│ ├── java
│ └── com
│ │ └── amazon
│ │ └── inspector
│ │ └── jenkins
│ │ └── amazoninspectorbuildstep
│ │ ├── utils
│ │ ├── SanitizerTest.java
│ │ └── ConversionUtilsTest.java
│ │ ├── TestUtils.java
│ │ ├── sbomgen
│ │ ├── SbomgenUtilsTest.java
│ │ ├── SbomgenDownloaderTest.java
│ │ └── SbomgenRunnerTest.java
│ │ ├── sbomparsing
│ │ └── SbomOutputParserTest.java
│ │ ├── csvconversion
│ │ └── CsvConverterTest.java
│ │ ├── html
│ │ └── HtmlConversionUtilsTest.java
│ │ └── AmazonInspectorBuilderTest.java
│ └── resources
│ └── data
│ ├── SbomOutputExampleNullVuln.json
│ └── bomermanOutput.json
├── Jenkinsfile
├── README.md
├── pom.xml
└── LICENSE
/docs/SUPPORT.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 |
--------------------------------------------------------------------------------
/.mvn/maven.config:
--------------------------------------------------------------------------------
1 | -Pconsume-incrementals
2 | -Pmight-produce-incrementals
3 | -Dchangelist.format=%d.v%s
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /annotation-generated-src/
2 | /annotation-generated-tst/
3 | /work/
4 | /workspace/
5 | /.idea/
6 | /target/
7 | /build/
8 | /lib/
9 | .DS_Store
10 | .crux_dry_run_build
11 | *.jar
--------------------------------------------------------------------------------
/src/main/resources/index.jelly:
--------------------------------------------------------------------------------
1 |
2 |
5 |
properties;
12 | }
13 |
--------------------------------------------------------------------------------
/.github/workflows/jenkins-maven-cd.yaml:
--------------------------------------------------------------------------------
1 | name: Jenkins Maven Release
2 | on:
3 | workflow_dispatch:
4 | check_run:
5 | types:
6 | - completed
7 |
8 | jobs:
9 | maven-cd:
10 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
11 | secrets:
12 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
13 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Tool.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | @Getter
7 | @Setter
8 | public class Tool {
9 | private String name;
10 | private String vendor;
11 | private String version;
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Source.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | @Getter
8 | @Setter
9 | @Builder
10 | public class Source {
11 | private String name;
12 | private String url;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Property.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | @Getter
8 | @Setter
9 | @Builder
10 | public class Property {
11 | private String name;
12 | private String value;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isLicenseCollectionEnabled.html:
--------------------------------------------------------------------------------
1 |
2 | Collects license information for packages in your SBOM artifact.
3 |
4 | Requirements: Bomerman v1.8.0+ required.
5 |
6 | License data will be included in the SBOM output for compliance and reporting purposes.
7 |
8 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/SbomData.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 |
8 | @AllArgsConstructor
9 | @Builder
10 | @Getter
11 | @Setter
12 | public class SbomData {
13 | private String status;
14 | private Sbom sbom;
15 | }
16 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | io.jenkins.tools.incrementals
4 | git-changelist-maven-extension
5 | 1.8
6 |
7 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/html/components/HtmlVulnerability.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components;
2 |
3 | import lombok.Builder;
4 |
5 | @Builder
6 | public class HtmlVulnerability {
7 | public String title;
8 | public String vulnerabilityId;
9 | public double cvss;
10 | public String severity;
11 | public String component;
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/html/components/SeverityValues.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import lombok.Builder;
5 |
6 | @Builder
7 | @SuppressFBWarnings
8 | public class SeverityValues {
9 | public int critical;
10 | public int high;
11 | public int medium;
12 | public int low;
13 | public int other;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Rating.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | @Getter
8 | @Setter
9 | @Builder
10 | public class Rating {
11 | private Source source;
12 | private double score;
13 | private String severity;
14 | private String method;
15 | private String vector;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isEpssThresholdEnabled.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | /*
2 | See the documentation for more options:
3 | https://github.com/jenkins-infra/pipeline-library/
4 | */
5 | buildPlugin(
6 | forkCount: '1C', // run this number of tests in parallel for faster feedback. If the number terminates with a 'C', the value will be multiplied by the number of available CPU cores
7 | useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
8 | configurations: [
9 | [platform: 'linux', jdk: 21],
10 | [platform: 'windows', jdk: 17],
11 | ])
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/html/components/DockerVulnerability.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import lombok.Builder;
5 |
6 | @Builder
7 | @SuppressFBWarnings
8 | public class DockerVulnerability {
9 | public String id;
10 | public String severity;
11 | public String description;
12 | public String file;
13 | public String lines;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-reportArtifactName.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isSeverityThresholdEnabled.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-sbomgenSkipFiles.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isSuppressedCveEnabled.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isAutoFailCveEnabled.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Component.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 | import lombok.Builder;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 |
8 | import java.util.List;
9 |
10 | @Getter
11 | @Setter
12 | @Builder
13 |
14 | public class Component {
15 | @SerializedName("bom-ref")
16 | private String bomRef;
17 | private String type;
18 | private String name;
19 | private String purl;
20 | private List properties;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-archivePath.html:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/.github/workflows/jenkins-security-scan.yml:
--------------------------------------------------------------------------------
1 | name: Jenkins Security Scan
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | types: [ opened, synchronize, reopened ]
9 | workflow_dispatch:
10 |
11 | permissions:
12 | security-events: write
13 | contents: read
14 | actions: read
15 |
16 | jobs:
17 | security-scan:
18 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
19 | with:
20 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
21 | # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default.
22 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-awsCredentialId.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/csvconversion/CsvData.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.csvconversion;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | @Getter
8 | @Setter
9 | @Builder
10 | public class CsvData {
11 | private String vulnerabilityId;
12 | private String severity;
13 | private String epssScore;
14 | private String published;
15 | private String modified;
16 | private String description;
17 | private String packageInstalledVersion;
18 | private String packagePath;
19 | private String packageFixedVersion;
20 | private String cwes;
21 | private String exploitAvailable;
22 | private String exploitLastSeen;
23 | private String file;
24 | private String lines;
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-sbomgenSelection.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Automatic (Recommended): Allows the plugin to download the most recently released version of inspector-sbomgen.
4 | This ensures you always have the latest features, security updates, and bug fixes.
5 | Requires selection of the operating system and CPU architecture in use.
6 |
7 |
8 | Manual: Requires a path to a pre-downloaded version of inspector-sbomgen to be supplied.
9 |
10 |
11 | For more info:
12 |
13 | https://docs.aws.amazon.com/inspector/latest/user/sbom-generator.html
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Sbom.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components.Component;
4 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components.Metadata;
5 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components.Vulnerability;
6 | import lombok.Builder;
7 | import lombok.Getter;
8 | import lombok.Setter;
9 |
10 | import java.util.List;
11 |
12 | @Getter
13 | @Setter
14 | @Builder
15 | public class Sbom {
16 | private String bomFormat;
17 | private String specVersion;
18 | private int version;
19 | private String serialNumber;
20 | private Metadata metadata;
21 | private List components;
22 | private List vulnerabilities;
23 | }
--------------------------------------------------------------------------------
/src/test/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/utils/SanitizerTest.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils;
2 |
3 | import org.junit.Test;
4 |
5 | import java.net.MalformedURLException;
6 | import java.net.URISyntaxException;
7 |
8 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils.Sanitizer.sanitizeFilePath;
9 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils.Sanitizer.sanitizeText;
10 | import static org.junit.Assert.assertEquals;
11 |
12 | public class SanitizerTest {
13 | @Test
14 | public void testSanitizeFilePath() throws MalformedURLException, URISyntaxException {
15 | assertEquals(sanitizeFilePath("file:///test test/{}test"), "file:///test%20test/%7B%7Dtest");
16 | }
17 |
18 | @Test
19 | public void testSanitizeNonUrl() throws MalformedURLException, URISyntaxException {
20 | assertEquals(sanitizeText("test:test{}"), "test:test%7B%7D");
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/TestUtils.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Sbom;
4 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.SbomData;
5 | import com.google.gson.Gson;
6 | import com.google.gson.GsonBuilder;
7 |
8 | import java.io.IOException;
9 | import java.nio.charset.StandardCharsets;
10 | import java.nio.file.Files;
11 | import java.nio.file.Paths;
12 |
13 | public class TestUtils {
14 | public static String readStringFromFile(String filePath) throws IOException {
15 | return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
16 | }
17 |
18 | public static SbomData getSbomDataFromString(String rawSbom) {
19 | Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
20 | return SbomData.builder().sbom(gson.fromJson(rawSbom, Sbom.class)).build();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-isThresholdEnabled.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Enables vulnerability thresholds, EPSS assessment, and CVE ignore functionality for comprehensive security evaluation.
4 |
5 |
6 | Vulnerability Thresholds: Specifies whether scanned vulnerabilities exceeding a value will cause a build failure.
7 |
8 |
9 | EPSS Assessment: EPSS scores range from 0-1, enter a value between 0 and 1 (e.g., 0.6).
10 |
11 |
12 | Ignore CVE: Specify CVEs to exclude from threshold calculations and EPSS assessment. Ignored CVEs appear in reports but won't cause build failures.
13 |
14 |
15 | For more info: https://docs.aws.amazon.com/inspector/latest/user/cicd-jenkins.html
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Amazon Inspector is a vulnerability management service offered by AWS that scans container images for both operating system and programming language package vulnerabilities based on CVEs. For more information on Amazon Inspector’s CI/CD integration see [Integrating Amazon Inspector scans into your CI/CD pipeline](https://docs.aws.amazon.com/inspector/latest/user/scanning-cicd.html).
2 |
3 | This plugin gives you the ability to add Amazon Inspector vulnerability scans to your pipeline. These scans produce detailed reports at the end of your build so you can investigate and remediate risk before deployment. These scans can also be configured to pass or fail pipeline executions based on the number and severity of vulnerabilities detected.
4 |
5 | For a list of packages and container image formats the Inspector plugin supports see, [Supported packages and image formats](https://docs.aws.amazon.com/inspector/latest/user/sbom-generator.html#sbomgen-supported).
6 |
7 | For a list of steps describing how to set up this plugin, see https://docs.aws.amazon.com/inspector/latest/user/cicd-jenkins.html
8 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-autoFailCves.html:
--------------------------------------------------------------------------------
1 |
2 |
CVE auto-fail list
3 |
4 | Specify a list of CVE identifiers that will always fail the build when detected, regardless of other threshold settings.
5 |
6 |
7 |
Supported Formats:
8 |
9 | - Comma-separated: CVE-2023-9999, CVE-2024-0001
10 | - One per line:
11 | CVE-2023-9999
12 | CVE-2024-0001
13 |
14 | - Mixed format: CVE-2023-9999, CVE-2024-0001
CVE-2024-0002
15 |
16 |
17 |
Behavior:
18 |
19 | - Runs independently of vulnerability threshold settings
20 | - Takes precedence over the CVE suppression list
21 | - Immediately fails the build when any auto-fail CVE is detected
22 |
23 |
24 |
Note: CVE IDs must follow the format CVE-YYYY-NNNN (e.g., CVE-2023-1234)
25 |
26 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/html/HtmlData.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components.DockerVulnerability;
4 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components.HtmlVulnerability;
5 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components.ImageMetadata;
6 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.html.components.SeverityValues;
7 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
8 | import lombok.Builder;
9 |
10 | import java.util.List;
11 |
12 | @Builder
13 | @SuppressFBWarnings
14 | public class HtmlData {
15 | public String artifactsPath;
16 | public String bomFormat;
17 | public String specVersion;
18 | public String version;
19 | public String updatedAt;
20 | public ImageMetadata imageMetadata;
21 | public SeverityValues severityValues;
22 | public List vulnerabilities;
23 | public List docker;
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/test/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/sbomgen/SbomgenUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomgen;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.exception.MalformedScanOutputException;
4 | import org.junit.Test;
5 |
6 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomgen.SbomgenUtils.processSbomgenOutput;
7 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomgen.SbomgenUtils.stripProperties;
8 | import static org.junit.Assert.assertEquals;
9 | import static org.junit.Assert.assertFalse;
10 |
11 | public class SbomgenUtilsTest {
12 | @Test
13 | public void testProcessSbomgenOutput() throws MalformedScanOutputException {
14 | String sbom = "time=dwadaw file=wdadawdwada\n{\ntest\n}\nbdwadawdaw";
15 | assertEquals(processSbomgenOutput(sbom), "{\ntest\n}");
16 | }
17 |
18 | @Test
19 | public void testStripProperties() {
20 | String bom = "{\"components\": [{\"properties\": []}]}";
21 | assertFalse(stripProperties(bom).contains("\"properties\""));
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/utils/Sanitizer.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.AmazonInspectorBuilder;
4 |
5 | import java.net.URI;
6 | import java.net.URISyntaxException;
7 |
8 | public class Sanitizer {
9 | private Sanitizer() {}
10 |
11 | public static String sanitizeUrl(String rawUrl) throws URISyntaxException {
12 | URI uri = new URI(rawUrl);
13 | return uri.toASCIIString();
14 | }
15 |
16 | public static String sanitizeFilePath(String rawUrl) {
17 | try {
18 | String[] splitUrl = rawUrl.split(":");
19 | URI uri = new URI(splitUrl[0], splitUrl[1], null);
20 | return uri.toASCIIString();
21 | } catch(Exception e) {
22 | AmazonInspectorBuilder.logger.printf("%s in invalid format, using it as the path.", rawUrl);
23 | return rawUrl;
24 | }
25 |
26 | }
27 |
28 | public static String sanitizeText(String text) throws URISyntaxException {
29 | return sanitizeFilePath(text);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/models/sbom/Components/Vulnerability.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components;
2 |
3 | import lombok.Builder;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 |
7 | import java.util.List;
8 |
9 | @Getter
10 | @Setter
11 | @Builder
12 | public class Vulnerability {
13 | private String bomRef;
14 | private String id;
15 | private Source source;
16 | private List references;
17 | private List ratings;
18 | private List cwes;
19 | private String description;
20 | private List advisories;
21 | private String created;
22 | private String modified;
23 | private String updated;
24 | private List affects;
25 | private List properties;
26 |
27 | public Double getEpssScore() {
28 | if (ratings == null) {
29 | return null;
30 | }
31 | for (Rating rating : ratings) {
32 | if (rating.getSource() != null && "EPSS".equalsIgnoreCase(rating.getSource().getName())) {
33 | return rating.getScore();
34 | }
35 | }
36 | return null;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/sbomparsing/Severity.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing;
2 |
3 | import lombok.AllArgsConstructor;
4 |
5 | import java.util.Locale;
6 |
7 | @AllArgsConstructor
8 | public enum Severity {
9 | CRITICAL("critical", 4),
10 | HIGH("high", 3),
11 | MEDIUM("medium", 2),
12 | LOW("low", 1),
13 | OTHER("other", 0),
14 | UNTRIAGED("untriaged", -1);
15 |
16 | private String severityName;
17 | private int rating;
18 |
19 | public static Severity getHigherSeverity(Severity sevLeft, Severity sevRight) {
20 | if (sevLeft.rating > sevRight.rating) {
21 | return sevLeft;
22 | }
23 | return sevRight;
24 | }
25 |
26 | public static Severity getSeverityFromString(String severityName) {
27 | switch (severityName.toLowerCase(Locale.ROOT)) {
28 | case "critical":
29 | return CRITICAL;
30 | case "high":
31 | return HIGH;
32 | case "medium":
33 | return MEDIUM;
34 | case "low":
35 | return LOW;
36 | default:
37 | return OTHER;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/utils/InspectorRegions.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils;
2 |
3 | import java.util.List;
4 |
5 | public class InspectorRegions {
6 | public static final List INSPECTOR_REGIONS = List.of(
7 | "af-south-1",
8 | "ap-east-1",
9 | "ap-northeast-1",
10 | "ap-northeast-2",
11 | "ap-northeast-3",
12 | "ap-south-1",
13 | "ap-southeast-1",
14 | "ap-southeast-2",
15 | "ca-central-1",
16 | "eu-central-1",
17 | "eu-central-2",
18 | "eu-north-1",
19 | "eu-south-1",
20 | "eu-west-1",
21 | "eu-west-2",
22 | "eu-west-3",
23 | "me-south-1",
24 | "sa-east-1",
25 | "us-east-1",
26 | "us-east-2",
27 | "us-iso-east-1",
28 | "us-iso-east-1",
29 | "us-iso-west-1",
30 | "us-west-1",
31 | "us-west-2"
32 | );
33 |
34 | public static final List BETA_REGIONS = List.of(
35 | "us-east-1",
36 | "eu-west-1",
37 | "us-west-2"
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/resources/com/amazon/inspector/jenkins/amazoninspectorbuildstep/AmazonInspectorBuilder/help-suppressedCves.html:
--------------------------------------------------------------------------------
1 |
2 |
CVE suppression list
3 |
4 | Specify a list of CVE identifiers to exclude from vulnerability threshold calculations and EPSS assessment.
5 | These CVEs will be detected and reported but will not contribute to build failure decisions.
6 |
7 |
8 |
Supported Formats:
9 |
10 | - Comma-separated: CVE-2023-1234, CVE-2023-5678, CVE-2024-0001
11 | - One per line:
12 | CVE-2023-1234
13 | CVE-2023-5678
14 | CVE-2024-0001
15 |
16 | - Mixed format: CVE-2023-1234, CVE-2023-5678
CVE-2024-0001
17 |
18 |
19 |
Behavior:
20 |
21 | - Suppressed CVEs are subtracted from vulnerability threshold counts
22 | - Suppressed CVEs are excluded from EPSS threshold evaluation
23 | - CVEs will still appear in scan reports and artifacts
24 | - Detailed logging shows which CVEs were suppressed and their impact
25 |
26 |
27 |
Note: CVE IDs must follow the format CVE-YYYY-NNNN (e.g., CVE-2023-1234)
28 |
29 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/sbomparsing/SeverityCounts.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing;
2 |
3 | import lombok.Getter;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity.CRITICAL;
9 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity.HIGH;
10 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity.LOW;
11 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity.MEDIUM;
12 | import static com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity.OTHER;
13 |
14 | public class SeverityCounts {
15 |
16 | @Getter
17 | private Map counts = new HashMap<>();
18 |
19 | public SeverityCounts() {
20 | counts.put(CRITICAL, 0);
21 | counts.put(HIGH, 0);
22 | counts.put(MEDIUM, 0);
23 | counts.put(LOW, 0);
24 | counts.put(OTHER, 0);
25 | }
26 |
27 | public void increment(Severity severityToIncrement) {
28 | if (counts.containsKey(severityToIncrement)) {
29 | counts.put(severityToIncrement, counts.get(severityToIncrement) + 1);
30 | }
31 | }
32 |
33 | public String toString() {
34 | return String.format("Critical: %s, High: %s, Medium: %s, Low: %s, Other: %s",
35 | counts.get(CRITICAL), counts.get(HIGH), counts.get(MEDIUM), counts.get(LOW), counts.get(OTHER));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/resources/data/SbomOutputExampleNullVuln.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "SBOM parsed successfully, 1 vulnerabilities found",
3 | "sbom": {
4 | "bomFormat": "CycloneDX",
5 | "specVersion": "1.5",
6 | "version": 1,
7 | "serialNumber": "urn:uuid:0077b45b-ff1e-4dbb-8950-ded11d8242b1",
8 | "metadata": {
9 | "properties": [
10 | {
11 | "name": "amazon:inspector:sbom_scanner:critical_vulnerabilities",
12 | "value": "1"
13 | },
14 | {
15 | "name": "amazon:inspector:sbom_scanner:high_vulnerabilities",
16 | "value": "0"
17 | },
18 | {
19 | "name": "amazon:inspector:sbom_scanner:medium_vulnerabilities",
20 | "value": "0"
21 | },
22 | {
23 | "name": "amazon:inspector:sbom_scanner:low_vulnerabilities",
24 | "value": "0"
25 | }
26 | ],
27 | "tools": [
28 | {
29 | "name": "CycloneDX SBOM API",
30 | "vendor": "Amazon Inspector",
31 | "version": "empty:083c9b00:083c9b00:083c9b00"
32 | }
33 | ],
34 | "timestamp": "2023-06-28T14:15:53.760Z"
35 | },
36 | "components": [
37 | {
38 | "bom-ref": "comp-1",
39 | "type": "library",
40 | "name": "log4j-core",
41 | "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.12.1"
42 | },
43 | {
44 | "bom-ref": "comp-2",
45 | "type": "library",
46 | "name": "exampleComponent",
47 | "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.12.1"
48 | }
49 | ]
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/utils/SbomgenProcessing.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.IOException;
6 | import java.nio.charset.StandardCharsets;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class SbomgenProcessing {
11 | public static int findSbomgenStartLineIndex(List list) {
12 | for (int i = 0; i < list.size(); i++) {
13 | if (list.get(i).length() > 0 && list.get(i).charAt(0) == '{') {
14 | return i;
15 | }
16 | }
17 |
18 | return -1;
19 | }
20 |
21 | public static int findSbomgenEndLineIndex(List list) {
22 | for (int i = list.size() - 1; i > 0 ; i--) {
23 | if (list.get(i).length() > 0 && list.get(i).charAt(0) == '}') {
24 | return i;
25 | }
26 | }
27 |
28 | return -1;
29 | }
30 |
31 | public static String processSbomgenFile(File outFile) throws IOException {
32 | String rawFileContent = new String(new FileInputStream(outFile).readAllBytes(), StandardCharsets.UTF_8);
33 |
34 | String[] splitRawFileContent = rawFileContent.split("\n");
35 | List lines = new ArrayList<>();
36 |
37 | for (String line : splitRawFileContent) {
38 | lines.add(line.replaceAll("time=.+file=.+\"", ""));
39 | }
40 |
41 | lines = lines.subList(findSbomgenStartLineIndex(lines), findSbomgenEndLineIndex(lines)+1);
42 | return String.join("\n", lines);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/utils/ConversionUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.utils;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.TestUtils;
4 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.Components.Vulnerability;
5 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.models.sbom.SbomData;
6 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.Severity;
7 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.sbomparsing.SeverityCounts;
8 | import org.junit.Assert;
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 | import java.io.IOException;
13 | import java.util.Map;
14 |
15 | public class ConversionUtilsTest {
16 | SbomData sbomData;
17 |
18 | @Before
19 | public void setUp() throws IOException {
20 | String str = TestUtils.readStringFromFile("src/test/resources/data/SbomOutputExampleUbuntu.json");
21 | sbomData = TestUtils.getSbomDataFromString(str);
22 | }
23 |
24 | @Test
25 | public void testGetSeverities() {
26 | SeverityCounts severityCounts = new SeverityCounts();
27 |
28 | for (Vulnerability vulnerability : sbomData.getSbom().getVulnerabilities()) {
29 | Severity severity = ConversionUtils.getSeverity(vulnerability);
30 | severityCounts.increment(severity);
31 | }
32 |
33 | Map severityMap = severityCounts.getCounts();
34 | Assert.assertEquals(Integer.valueOf(47), severityMap.get(Severity.CRITICAL));
35 | Assert.assertEquals(Integer.valueOf(214), severityMap.get(Severity.HIGH));
36 | Assert.assertEquals(Integer.valueOf(110), severityMap.get(Severity.MEDIUM));
37 | Assert.assertEquals(Integer.valueOf(9), severityMap.get(Severity.LOW));
38 | Assert.assertEquals(Integer.valueOf(0), severityMap.get(Severity.OTHER));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.github/workflows/inspector-scan.yaml:
--------------------------------------------------------------------------------
1 | name: Inspector Security Scan
2 |
3 | on: [push]
4 | jobs:
5 | daily_job:
6 | runs-on: ubuntu-latest
7 |
8 | environment:
9 | name: InspectorScanSbom
10 |
11 | steps:
12 | - name: Configure AWS credentials
13 | uses: aws-actions/configure-aws-credentials@v5
14 | with:
15 | aws-region: ${{ secrets.AWS_REGION }}
16 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
17 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
18 | role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
19 |
20 | - name: Checkout repository
21 | uses: actions/checkout@v5
22 |
23 | - name: Scan project with Inspector
24 | id: inspector
25 | uses: aws-actions/vulnerability-scan-github-action-for-amazon-inspector@v1
26 | with:
27 | artifact_type: 'repository'
28 | artifact_path: './'
29 | display_vulnerability_findings: "enabled"
30 | critical_threshold: 1
31 | high_threshold: 2
32 | medium_threshold: 2
33 | low_threshold: 1
34 | other_threshold: 1
35 |
36 | - name: Display SBOM
37 | run: cat ${{ steps.inspector.outputs.artifact_sbom }}
38 |
39 | - name: Display vulnerability scan
40 | run: cat ${{ steps.inspector.outputs.inspector_scan_results }}
41 |
42 | - name: Display vulnerability scan (Markdown)
43 | run: cat ${{ steps.inspector.outputs.inspector_scan_results_markdown }}
44 |
45 | - name: Upload scan results
46 | uses: actions/upload-artifact@v4
47 | with:
48 | name: Inspector Vulnerability Scan Artifacts
49 | path: |
50 | ${{ steps.inspector.outputs.inspector_scan_results }}
51 | ${{ steps.inspector.outputs.artifact_sbom }}
52 | ${{ steps.inspector.outputs.inspector_scan_results_markdown }}
53 |
54 | - name: Fail if vulns detected
55 | run: exit ${{ steps.inspector.outputs.vulnerability_threshold_exceeded }}
56 |
--------------------------------------------------------------------------------
/src/main/java/com/amazon/inspector/jenkins/amazoninspectorbuildstep/html/HtmlJarHandler.java:
--------------------------------------------------------------------------------
1 | package com.amazon.inspector.jenkins.amazoninspectorbuildstep.html;
2 |
3 | import com.amazon.inspector.jenkins.amazoninspectorbuildstep.AmazonInspectorBuilder;
4 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
5 | import hudson.FilePath;
6 | import lombok.AllArgsConstructor;
7 | import org.apache.commons.io.IOUtils;
8 | import org.apache.commons.lang3.StringEscapeUtils;
9 |
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.nio.charset.StandardCharsets;
13 | import java.util.jar.JarEntry;
14 | import java.util.jar.JarFile;
15 |
16 | @AllArgsConstructor
17 | public class HtmlJarHandler {
18 | public String jarPath;
19 | public String htmlData;
20 |
21 | public FilePath copyHtmlToDir(FilePath workspace, String buildId) throws IOException, InterruptedException {
22 | String htmlFileName = "index.html";
23 | String htmlStr = readStringFromJarEntry(htmlFileName);
24 |
25 | String injectedHtmlStr = injectHtmlData(htmlStr);
26 | FilePath htmlFile = workspace.child(String.format("%s/%s", buildId, htmlFileName));
27 | htmlFile.write(injectedHtmlStr, "UTF-8");
28 | return htmlFile;
29 | }
30 |
31 | public String injectHtmlData(String htmlContent) throws IOException {
32 | String scriptStart = "