Skip to content

Commit

Permalink
Merge pull request #6 from neuvector/NVSHAS-8797-support-exempt-vulne…
Browse files Browse the repository at this point in the history
…rability

[NVSHAS-8797] Support NeuVector accepts vulnerability when using GitHub Actions scans
  • Loading branch information
becitsthere authored Mar 19, 2024
2 parents 0c499fb + dd00332 commit 3e1c586
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 23 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ FROM registry.suse.com/bci/bci-base:15.4
RUN zypper in -y jq docker && zypper clean

COPY run-scan.sh /usr/bin
COPY utils.sh /usr/bin

ENTRYPOINT ["/usr/bin/run-scan.sh"]
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,20 @@ The following inputs can be used in `step.with`:

<!-- start inputs -->

| **Input** | **Description** | **Default** | **Required** |
| ----------------------------- | ------------------------------------------------------------------------------------------- | -------------------------- | ------------ |
| **`image-registry`** | Registry of the image to scan, e.g. `https://registry.organization.com/` | | **false** |
| **`image-registry-username`** | Username for the registry authentication | | **false** |
| **`image-registry-password`** | Password for the registry authentication | | **false** |
| **`image-repository`** | Repository of the image to scan, e.g. `org/image-name` | | **true** |
| **`image-tag`** | Tag of the image to scan, e.g. `1.0.0` | | **true** |
| **`min-high-cves-to-fail`** | Minimum CVEs with high severity to fail the job | `0` | **false** |
| **`min-medium-cves-to-fail`** | Minimum CVEs with medium severity to fail the job | `0` | **false** |
| **`cve-names-to-fail`** | Comma-separated list of CVE names that make the job fail, e.g. `CVE-2021-4160,CVE-2022-0778 | | **false** |
| **`nv-scanner-image`** | NeuVector Scanner image to use for scanning | `neuvector/scanner:latest` | **false** |
| **`output`** | Output format, one of: `text`, `json`, `csv` | `text` | **false** |
| **`debug`** | Debug mode, on of: `true`, `false` | `false` | **false** |
| **Input** | **Description** | **Default** | **Required** |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------ |
| **`image-registry`** | Registry of the image to scan, e.g. `https://registry.organization.com/` | | **false** |
| **`image-registry-username`** | Username for the registry authentication | | **false** |
| **`image-registry-password`** | Password for the registry authentication | | **false** |
| **`image-repository`** | Repository of the image to scan, e.g. `org/image-name` | | **true** |
| **`image-tag`** | Tag of the image to scan, e.g. `1.0.0` | | **true** |
| **`min-high-cves-to-fail`** | Minimum CVEs with high severity to fail the job | `0` | **false** |
| **`min-medium-cves-to-fail`** | Minimum CVEs with medium severity to fail the job | `0` | **false** |
| **`cve-names-to-fail`** | Comma-separated list of CVE names(without spaces between the entries) that make the job fail, e.g. `CVE-2021-4160,CVE-2022-0778 | | **false** |
| **`cve-names-to-exempt`** | Comma-separated list of CVE names(without spaces between the entries) that exempt the job fail, e.g. `CVE-2021-4160,CVE-2022-0778 | | **false** |
| **`nv-scanner-image`** | NeuVector Scanner image to use for scanning | `neuvector/scanner:latest` | **false** |
| **`output`** | Output format, one of: `text`, `json`, `csv` | `text` | **false** |
| **`debug`** | Debug mode, on of: `true`, `false` | `false` | **false** |

<!-- end inputs -->

Expand Down Expand Up @@ -138,11 +139,16 @@ The following inputs can be used in `step.with`:
# Default: 0
min-medium-cves-to-fail: ""

# Comma-separated list of CVE names that make the job fail, e.g.
# `CVE-2021-4160,CVE-2022-0778
# Comma-separated list of CVE names(without spaces between the entries) that make
# the job fail, e.g. `CVE-2021-4160,CVE-2022-0778
# Default:
cve-names-to-fail: ""

# Comma-separated list of CVE names(without spaces between the entries) that
# exempt the job fail, e.g. `CVE-2021-4160,CVE-2022-0778
# Default:
cve-names-to-exempt: ""

# NeuVector Scanner image to use for scanning
# Default: neuvector/scanner:latest
nv-scanner-image: ""
Expand Down
7 changes: 6 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ inputs:
required: false
default: '0'
cve-names-to-fail:
description: 'Comma-separated list of CVE names that make the job fail, e.g. `CVE-2021-4160,CVE-2022-0778'
description: 'Comma-separated list of CVE names(without spaces between the entries) that make the job fail, e.g. `CVE-2021-4160,CVE-2022-0778'
required: false
default: ''
cve-names-to-exempt:
description: 'Comma-separated list of CVE names(without spaces between the entries) that exempt the job fail, e.g. `CVE-2021-4160,CVE-2022-0778'
required: false
default: ''
nv-scanner-image:
Expand Down Expand Up @@ -59,6 +63,7 @@ runs:
HIGH_VUL_TO_FAIL: ${{ inputs.min-high-cves-to-fail }}
MEDIUM_VUL_TO_FAIL: ${{ inputs.min-medium-cves-to-fail }}
VUL_NAMES_TO_FAIL: ${{ inputs.cve-names-to-fail }}
VUL_NAMES_TO_EXEMPT: ${{ inputs.cve-names-to-exempt }}
SCANNER_REPOSITORY: ${{ inputs.image-repository }}
SCANNER_TAG: ${{ inputs.image-tag }}
SCANNER_REGISTRY: ${{ inputs.image-registry }}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions run-scan.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
source /usr/bin/utils.sh

set -e

Expand Down Expand Up @@ -35,16 +36,16 @@ fi
docker cp neuvector.scanner:/var/neuvector/scan_result.json scan_result.json
docker rm neuvector.scanner

VUL_EXEMPT_LIST=$(printf '["%s"]' "${VUL_NAMES_TO_EXEMPT//,/\",\"}")
filterOutExemptCVEsFromJson "scan_result.json" "$VUL_EXEMPT_LIST"

VUL_NUM=$(cat scan_result.json | jq '.report.vulnerabilities | length')
FOUND_HIGH=$(cat scan_result.json | jq '.report.vulnerabilities[] | select(.severity == "High") | .severity' | wc -l)
FOUND_MEDIUM=$(cat scan_result.json | jq '.report.vulnerabilities[] | select(.severity == "Medium") | .severity' | wc -l)
VUL_LIST=$(printf '["%s"]' "${VUL_NAMES_TO_FAIL//,/\",\"}")
VUL_LIST_FOUND=$(cat scan_result.json | jq --arg arr "$VUL_LIST" '.report.vulnerabilities[] | select(.name as $n | $arr | index($n)) |.name')

echo "::set-output name=vulnerability_count::${VUL_NUM}"
echo "::set-output name=high_vulnerability_count::${FOUND_HIGH}"
echo "::set-output name=medium_vulnerability_count::${FOUND_MEDIUM}"

# we must count the high and med before we put.
if [[ -n $VUL_LIST_FOUND ]]; then
fail_reason="Found specific named vulnerabilities."
scan_fail="true"
Expand All @@ -59,6 +60,7 @@ else
scan_fail="false"
fi


if [[ $scan_fail == "true" ]]; then
summary="Image scanning failed. ${fail_reason}"
else
Expand All @@ -83,8 +85,6 @@ if [[ "$OUTPUT" == "text" ]]; then
echo -e "Vulnerabilities grouped by packages:\n"

jq -r '[.report.vulnerabilities | group_by(.package_name) | .[] | {package_name: .[0].package_name, vuls: [ (.[] | {name: .name, description: .description, severity: .severity}) ]}] | .[] | (.package_name) + ":\n" + (.vuls | [.[] | .name + " (" + .severity + "): " + .description] | join("\n")) + "\n\n"' scan_result.json

echo -e "\n${summary}"
fi

if [[ "$OUTPUT" == "json" ]]; then
Expand All @@ -99,6 +99,8 @@ if [[ "$OUTPUT" == "csv" ]]; then
cat scan_result.json | jq -r '['$labels'],(.'$query' | ['$vars'])|@csv'
fi

echo -e "\n${summary}"

if [[ "$scan_fail" == "true" ]]; then
exit 1;
fi
31 changes: 31 additions & 0 deletions utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

function filterOutExemptCVEsFromJson() {
local scanResult="$1"
local exemptCVEsJson="$2"

local filterJson="$(cat "$scanResult")"

# Filter out the exempted CVEs from the top-level vulnerabilities array
filterJson=$(jq --argjson exemptions "$exemptCVEsJson" '
.report.vulnerabilities |= map(select(.name as $name | $exemptions | index($name) | not))
' <<<"$filterJson")

# Filter out the exempted CVEs from the cves array in each module
filterJson=$(jq --argjson exemptions "$exemptCVEsJson" '
.report.modules |= map(
if .cves then
.cves |= map(select(.name as $name | $exemptions | index($name) | not))
else
.
end
)
' <<<"$filterJson")

if [ -n "$filterJson" ]; then
echo "$filterJson" > "$scanResult"
else
echo "Error: Filtered Scan result JSON is empty. The original file will not be modified."
exit 1
fi
}

0 comments on commit 3e1c586

Please sign in to comment.