From c21d1a0dd71cfe4a2de9ab24c89e89f5203becd7 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 11:09:17 +0100 Subject: [PATCH 01/22] CCM-17525: Updating grype checks --- scripts/reports/parse-vulnerabilities.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index db93096..f4012e1 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -64,8 +64,8 @@ print_severity_section() { echo "### $severity ($count)" echo "" - echo "| Package | Language | Version | Fix | Description |" - echo "|---------|---------|---------|-----|-------------|" + echo "| ID | Package | Language | Version | Fix | Description |" + echo "|----|---------|---------|---------|-----|-------------|" jq -r --arg sev "$severity" ' [.matches[] | select(.vulnerability.severity == $sev) | { @@ -78,9 +78,9 @@ print_severity_section() { description: .vulnerability.description }] | unique_by([.id, .package, .version]) - | sort_by(.package) + | sort_by(.id, .package) | .[] - | "| \(.package) | \(.language) | \(.version) | \(.fix) | \(.description[0:70])... |" + | "| \(.id) | \(.package) | \(.language) | \(.version) | \(.fix) | \(.description[0:70])... |" ' "$REPORT_FILE" echo "" From b7db2246da734c0adc8a32b3b47fe6f2a93e9d2b Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 11:44:48 +0100 Subject: [PATCH 02/22] CCM-17525: Updating grype checks --- .github/actions/scan-dependencies/action.yaml | 33 ++++----- .pre-commit-hooks.yaml | 7 ++ docs/github-actions/scan-dependencies.md | 35 +++++++++- docs/pre-commit-hooks.md | 23 +++++++ scripts/config/pre-commit.yaml | 8 +++ scripts/githooks/scan-dependencies.sh | 15 ++++ scripts/reports/scan-vulnerabilities.sh | 69 ++++++++++++++++++- 7 files changed, 165 insertions(+), 25 deletions(-) create mode 100755 scripts/githooks/scan-dependencies.sh diff --git a/.github/actions/scan-dependencies/action.yaml b/.github/actions/scan-dependencies/action.yaml index 53ec460..30feeb1 100644 --- a/.github/actions/scan-dependencies/action.yaml +++ b/.github/actions/scan-dependencies/action.yaml @@ -20,7 +20,7 @@ inputs: description: "IDP AWS report upload endpoint to upload the report to" required: false skip_if_pr_has_label: - description: "Skip dependency scanning when the triggering PR has this label" + description: "Skip failing the dependency scan when the triggering PR has this label" required: false default: "skip-dependencies-check" runs: @@ -68,13 +68,7 @@ runs: fi echo "should_skip=${SHOULD_SKIP}" >> "$GITHUB_OUTPUT" - - name: "Skip dependency scan" - if: steps.skip-check.outputs.should_skip == 'true' - shell: bash - run: | - echo "Dependency scan skipped because PR has label '${{ inputs.skip_if_pr_has_label }}'." - name: "Generate SBOM" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: | ACTION_ROOT="$(cd "${GITHUB_ACTION_PATH}/../../.." && pwd)" @@ -82,26 +76,24 @@ runs: export BUILD_DATETIME=${{ inputs.build_datetime }} "${ACTION_ROOT}/scripts/reports/create-sbom-report.sh" - name: "Compress SBOM report" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: zip sbom-repository-report.json.zip sbom-repository-report.json - name: "Upload SBOM report as an artefact" - if: ${{ !env.ACT && steps.skip-check.outputs.should_skip != 'true' }} + if: ${{ !env.ACT }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: sbom-repository-report.json.zip path: ./sbom-repository-report.json.zip retention-days: 21 - name: "Scan vulnerabilities" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: | ACTION_ROOT="$(cd "${GITHUB_ACTION_PATH}/../../.." && pwd)" export TOOLING_ROOT="${ACTION_ROOT}" export BUILD_DATETIME=${{ inputs.build_datetime }} + export GRYPE_FAIL_ON_SEVERITY=none "${ACTION_ROOT}/scripts/reports/scan-vulnerabilities.sh" - name: "Generate vulnerabilities summary" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: | ACTION_ROOT="$(cd "${GITHUB_ACTION_PATH}/../../.." && pwd)" @@ -110,48 +102,49 @@ runs: cat vulnerabilities-summary.md >> "$GITHUB_STEP_SUMMARY" fi - name: "Compress vulnerabilities report" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: zip vulnerabilities-repository-report.json.zip vulnerabilities-repository-report.json - name: "Upload vulnerabilities report as an artefact" - if: ${{ !env.ACT && steps.skip-check.outputs.should_skip != 'true' }} + if: ${{ !env.ACT }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: vulnerabilities-repository-report.json.zip path: ./vulnerabilities-repository-report.json.zip retention-days: 21 - name: "Upload vulnerabilities summary as an artefact" - if: ${{ !env.ACT && steps.skip-check.outputs.should_skip != 'true' }} + if: ${{ !env.ACT }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: vulnerabilities-summary.md path: ./vulnerabilities-summary.md retention-days: 21 - name: "Fail if Critical or High vulnerabilities found" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash run: | CRITICAL_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "Critical") | {id: .vulnerability.id, package: .artifact.name, version: .artifact.version}] | unique_by([.id, .package, .version]) | length' vulnerabilities-repository-report.json) HIGH_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "High") | {id: .vulnerability.id, package: .artifact.name, version: .artifact.version}] | unique_by([.id, .package, .version]) | length' vulnerabilities-repository-report.json) echo "Critical: $CRITICAL_COUNT, High: $HIGH_COUNT" if [[ "$CRITICAL_COUNT" -gt 0 || "$HIGH_COUNT" -gt 0 ]]; then - echo "::error::Found $CRITICAL_COUNT Critical and $HIGH_COUNT High severity vulnerabilities" - exit 1 + if [[ "${{ steps.skip-check.outputs.should_skip }}" == "true" ]]; then + echo "Bypassing blocking dependency scan failure because PR has label '${{ inputs.skip_if_pr_has_label }}'." + else + echo "::error::Found $CRITICAL_COUNT Critical and $HIGH_COUNT High severity vulnerabilities" + exit 1 + fi fi - name: "Check prerequisites for sending the reports" - if: steps.skip-check.outputs.should_skip != 'true' shell: bash id: check run: echo "secrets_exist=${{ inputs.idp_aws_report_upload_role_name != '' && inputs.idp_aws_report_upload_bucket_endpoint != '' }}" >> $GITHUB_OUTPUT - name: "Authenticate to send the reports" - if: steps.skip-check.outputs.should_skip != 'true' && steps.check.outputs.secrets_exist == 'true' + if: steps.check.outputs.secrets_exist == 'true' uses: aws-actions/configure-aws-credentials@acca2b1b2070338fb9fd1ca27ecee81d687e58e5 # v6.1.2 with: role-to-assume: arn:aws:iam::${{ inputs.idp_aws_report_upload_account_id }}:role/${{ inputs.idp_aws_report_upload_role_name }} aws-region: ${{ inputs.idp_aws_report_upload_region }} - name: "Send the SBOM and vulnerabilities reports to the central location" shell: bash - if: steps.skip-check.outputs.should_skip != 'true' && steps.check.outputs.secrets_exist == 'true' + if: steps.check.outputs.secrets_exist == 'true' run: | aws s3 cp \ ./sbom-repository-report.json.zip \ diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index c0b496d..0866356 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -51,3 +51,10 @@ entry: .github/actions/check-todo-usage/check-todos.sh language: script pass_filenames: false + +- id: scan-dependencies + name: Scan dependencies + entry: scripts/githooks/scan-dependencies.sh + language: script + pass_filenames: false + stages: [manual] diff --git a/docs/github-actions/scan-dependencies.md b/docs/github-actions/scan-dependencies.md index 71c9253..befc70b 100644 --- a/docs/github-actions/scan-dependencies.md +++ b/docs/github-actions/scan-dependencies.md @@ -13,6 +13,7 @@ Scans project dependencies for known vulnerabilities. ### Description This composite action scans project dependencies to identify known security vulnerabilities. +It always produces the SBOM, raw Grype JSON report, and markdown summary, and it fails the workflow when High or Critical vulnerabilities are present unless the triggering PR carries a configured skip label. ### Usage @@ -20,16 +21,44 @@ This composite action scans project dependencies to identify known security vuln jobs: scan-deps: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read steps: - uses: actions/checkout@v4 - name: Scan dependencies uses: NHSDigital/nhs-notify-shared-modules/.github/actions/scan-dependencies@v1.0.0 + with: + build_datetime: "${{ needs.metadata.outputs.build_datetime }}" + build_timestamp: "${{ needs.metadata.outputs.build_timestamp }}" + skip_if_pr_has_label: grype-ignore-high-and-critical ``` ### Details - Scans: npm packages, Ruby gems, Python packages -- Checks: Known vulnerabilities (CVEs) -- Reports: Security advisories -- Alerts: High-risk dependencies +- Checks: Known vulnerabilities or CVE +- Reports: SBOM JSON, Grype JSON, and markdown summary +- Alerts: High and Critical vulnerabilities fail by default + +### Ignore File + +If a repository contains a root-level `.grypeignore`, each non-comment line is treated as a Grype vulnerability ID to suppress. For example: + +```text +CVE-2026-25128 # Ticket to review: CCM-14317 +GHSA-xxxx-yyyy-zzzz +``` + +The workflow summary now includes the vulnerability ID in each row so exemptions can be copied directly into `.grypeignore`. + +### Skip Label + +Set `skip_if_pr_has_label` to a PR label name if you need to skip the blocking failure for known High or Critical findings that are already being handled elsewhere. + +- The scan still runs. +- Reports and summaries are still uploaded. +- Only the final blocking failure is skipped when the label is present. + +The default label is `skip-dependencies-check`. diff --git a/docs/pre-commit-hooks.md b/docs/pre-commit-hooks.md index a60c2b7..18913d0 100644 --- a/docs/pre-commit-hooks.md +++ b/docs/pre-commit-hooks.md @@ -115,6 +115,27 @@ Validates TODO comments follow the required format with Jira ticket IDs. - id: check-todo-usage ``` +#### scan-dependencies + +Runs the same SBOM and Grype dependency scan used in CI and prints the markdown vulnerability summary locally. + +**Usage:** + +```yaml +- repo: https://github.com/NHSDigital/nhs-notify-shared-modules + rev: vX.Y.Z + hooks: + - id: scan-dependencies +``` + +Run it manually when needed: + +```bash +pre-commit run --config scripts/config/pre-commit.yaml --hook-stage manual scan-dependencies +``` + +If the repository contains a root `.grypeignore`, the hook will honor it automatically. + ## Setup in Your Repository Add to your `.pre-commit-config.yaml`: @@ -128,6 +149,7 @@ repos: - id: check-file-format - id: check-markdown-format - id: lint-terraform + - id: scan-dependencies # Add other hooks as needed ``` @@ -142,3 +164,4 @@ pre-commit install - All hooks run with `pass_filenames: false` - they operate on the entire repository - The `scan-secrets` hook checks the entire Git history for security - Hooks reference scripts in either `scripts/githooks/` or `.github/actions/` +- `scan-dependencies` uses the same Grype-based workflow as CI, respects a root `.grypeignore` when present, and is configured as a manual-only hook diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index 09807a1..690dd9f 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -70,3 +70,11 @@ repos: entry: /usr/bin/env check=branch ./.github/actions/check-todo-usage/check-todos.sh language: script pass_filenames: false + - repo: local + hooks: + - id: scan-dependencies + name: Scan dependencies + entry: ./scripts/githooks/scan-dependencies.sh + language: script + pass_filenames: false + stages: [manual] diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh new file mode 100755 index 0000000..86b73a1 --- /dev/null +++ b/scripts/githooks/scan-dependencies.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TOOLING_ROOT="${TOOLING_ROOT:-$(cd "${SCRIPT_DIR}/../.." && pwd)}" + +cd "$(git rev-parse --show-toplevel)" + +export BUILD_DATETIME="${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}" +export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" + +"${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" +"${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" +"${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json diff --git a/scripts/reports/scan-vulnerabilities.sh b/scripts/reports/scan-vulnerabilities.sh index 544a3f6..d67556e 100755 --- a/scripts/reports/scan-vulnerabilities.sh +++ b/scripts/reports/scan-vulnerabilities.sh @@ -28,6 +28,7 @@ TOOLING_ROOT="${TOOLING_ROOT:-${DEFAULT_TOOLING_ROOT}}" function main() { cd "$(git rev-parse --show-toplevel)" + trap cleanup-generated-grype-config EXIT create-report enrich-report @@ -35,6 +36,8 @@ function main() { function create-report() { + prepare-grype-config + if command -v grype > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then run-grype-natively else @@ -44,10 +47,18 @@ function create-report() { function run-grype-natively() { + local fail_on_severity=${GRYPE_FAIL_ON_SEVERITY:-} + local fail_on_opt="" + if [[ -n "$fail_on_severity" && "$fail_on_severity" != "none" ]]; then + fail_on_opt="--fail-on $fail_on_severity" + fi + + # shellcheck disable=SC2086 grype \ sbom:"$PWD/sbom-repository-report.json" \ - --config "$TOOLING_ROOT/scripts/config/grype.yaml" \ + --config "$GRYPE_CONFIG_FILE" \ --output json \ + $fail_on_opt \ --file "$PWD/vulnerabilities-repository-report.tmp.json" } @@ -58,19 +69,33 @@ function run-grype-in-docker() { # shellcheck disable=SC2155 local image=$(name=ghcr.io/anchore/grype docker-get-image-version-and-pull) + + local fail_on_severity=${GRYPE_FAIL_ON_SEVERITY:-} + local fail_on_opt="" + if [[ -n "$fail_on_severity" && "$fail_on_severity" != "none" ]]; then + fail_on_opt="--fail-on $fail_on_severity" + fi + + # shellcheck disable=SC2086 docker run --rm --platform linux/amd64 \ --volume "$PWD":/workdir \ --volume "$TOOLING_ROOT":/tooling \ --volume /tmp/grype/db:/.cache/grype/db \ "$image" \ sbom:/workdir/sbom-repository-report.json \ - --config /tooling/scripts/config/grype.yaml \ + --config "/tooling${GRYPE_CONFIG_FILE#${TOOLING_ROOT}}" \ --output json \ + $fail_on_opt \ --file /workdir/vulnerabilities-repository-report.tmp.json } function enrich-report() { + if [[ ! -f vulnerabilities-repository-report.tmp.json ]]; then + echo "Grype did not produce vulnerabilities-repository-report.tmp.json" >&2 + return 1 + fi + build_datetime=${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')} git_url=$(git config --get remote.origin.url) git_branch=$(git rev-parse --abbrev-ref HEAD) @@ -88,6 +113,46 @@ function enrich-report() { rm -f vulnerabilities-repository-report.tmp.json } +function prepare-grype-config() { + + GRYPE_CONFIG_FILE="$TOOLING_ROOT/scripts/config/grype.yaml" + GENERATED_GRYPE_CONFIG_FILE="" + + local ignore_file="$PWD/.grypeignore" + if [[ ! -f "$ignore_file" ]]; then + return 0 + fi + + local has_ignores=false + while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do + local vulnerability_id + vulnerability_id=$(echo "$raw_line" | sed 's/#.*//' | xargs) + [[ -z "$vulnerability_id" ]] && continue + + if [[ "$has_ignores" == false ]]; then + GENERATED_GRYPE_CONFIG_FILE=$(mktemp) + cat "$GRYPE_CONFIG_FILE" > "$GENERATED_GRYPE_CONFIG_FILE" + printf '\nignore:\n' >> "$GENERATED_GRYPE_CONFIG_FILE" + has_ignores=true + fi + + printf ' - vulnerability: %s\n' "$vulnerability_id" >> "$GENERATED_GRYPE_CONFIG_FILE" + done < "$ignore_file" + + if [[ "$has_ignores" == false ]]; then + return 0 + fi + + GRYPE_CONFIG_FILE="$GENERATED_GRYPE_CONFIG_FILE" +} + +function cleanup-generated-grype-config() { + + if [[ -n "${GENERATED_GRYPE_CONFIG_FILE:-}" && -f "$GENERATED_GRYPE_CONFIG_FILE" ]]; then + rm -f "$GENERATED_GRYPE_CONFIG_FILE" + fi +} + # ============================================================================== function is-arg-true() { From 098defea574f0b6d046a09acbcb2e262b1c37906 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 12:00:10 +0100 Subject: [PATCH 03/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 86b73a1..5fa7417 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -10,6 +10,5 @@ cd "$(git rev-parse --show-toplevel)" export BUILD_DATETIME="${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}" export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" -"${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json From 7dedf8b24e809deb25d4d3be60dd12f619eb9d04 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 12:01:47 +0100 Subject: [PATCH 04/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 5fa7417..86b73a1 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -10,5 +10,6 @@ cd "$(git rev-parse --show-toplevel)" export BUILD_DATETIME="${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}" export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" +"${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json From e1158b0b3c720c4f55a1be8ea5d56ef2483d55d9 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:04:26 +0100 Subject: [PATCH 05/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 2 +- scripts/reports/scan-vulnerabilities.sh | 53 ++----------------------- 2 files changed, 5 insertions(+), 50 deletions(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 86b73a1..e35d0c9 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -10,6 +10,6 @@ cd "$(git rev-parse --show-toplevel)" export BUILD_DATETIME="${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}" export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" -"${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" +"${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" > /dev/null 2>&1 "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json diff --git a/scripts/reports/scan-vulnerabilities.sh b/scripts/reports/scan-vulnerabilities.sh index d67556e..6d007e3 100755 --- a/scripts/reports/scan-vulnerabilities.sh +++ b/scripts/reports/scan-vulnerabilities.sh @@ -28,7 +28,6 @@ TOOLING_ROOT="${TOOLING_ROOT:-${DEFAULT_TOOLING_ROOT}}" function main() { cd "$(git rev-parse --show-toplevel)" - trap cleanup-generated-grype-config EXIT create-report enrich-report @@ -36,8 +35,6 @@ function main() { function create-report() { - prepare-grype-config - if command -v grype > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then run-grype-natively else @@ -56,10 +53,10 @@ function run-grype-natively() { # shellcheck disable=SC2086 grype \ sbom:"$PWD/sbom-repository-report.json" \ - --config "$GRYPE_CONFIG_FILE" \ --output json \ $fail_on_opt \ - --file "$PWD/vulnerabilities-repository-report.tmp.json" + --file "$PWD/vulnerabilities-repository-report.tmp.json" \ + > /dev/null 2>&1 } function run-grype-in-docker() { @@ -83,10 +80,10 @@ function run-grype-in-docker() { --volume /tmp/grype/db:/.cache/grype/db \ "$image" \ sbom:/workdir/sbom-repository-report.json \ - --config "/tooling${GRYPE_CONFIG_FILE#${TOOLING_ROOT}}" \ --output json \ $fail_on_opt \ - --file /workdir/vulnerabilities-repository-report.tmp.json + --file /workdir/vulnerabilities-repository-report.tmp.json \ + > /dev/null 2>&1 } function enrich-report() { @@ -113,48 +110,6 @@ function enrich-report() { rm -f vulnerabilities-repository-report.tmp.json } -function prepare-grype-config() { - - GRYPE_CONFIG_FILE="$TOOLING_ROOT/scripts/config/grype.yaml" - GENERATED_GRYPE_CONFIG_FILE="" - - local ignore_file="$PWD/.grypeignore" - if [[ ! -f "$ignore_file" ]]; then - return 0 - fi - - local has_ignores=false - while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do - local vulnerability_id - vulnerability_id=$(echo "$raw_line" | sed 's/#.*//' | xargs) - [[ -z "$vulnerability_id" ]] && continue - - if [[ "$has_ignores" == false ]]; then - GENERATED_GRYPE_CONFIG_FILE=$(mktemp) - cat "$GRYPE_CONFIG_FILE" > "$GENERATED_GRYPE_CONFIG_FILE" - printf '\nignore:\n' >> "$GENERATED_GRYPE_CONFIG_FILE" - has_ignores=true - fi - - printf ' - vulnerability: %s\n' "$vulnerability_id" >> "$GENERATED_GRYPE_CONFIG_FILE" - done < "$ignore_file" - - if [[ "$has_ignores" == false ]]; then - return 0 - fi - - GRYPE_CONFIG_FILE="$GENERATED_GRYPE_CONFIG_FILE" -} - -function cleanup-generated-grype-config() { - - if [[ -n "${GENERATED_GRYPE_CONFIG_FILE:-}" && -f "$GENERATED_GRYPE_CONFIG_FILE" ]]; then - rm -f "$GENERATED_GRYPE_CONFIG_FILE" - fi -} - -# ============================================================================== - function is-arg-true() { if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then From bbfd8de4e0b82efac10b2a09df673eef0e211a17 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:07:24 +0100 Subject: [PATCH 06/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index e35d0c9..587155a 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -13,3 +13,8 @@ export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" "${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" > /dev/null 2>&1 "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json + +# Display the vulnerability report +if [[ -f vulnerabilities-repository-report.json ]]; then + cat vulnerabilities-repository-report.json +fi From 9ea5e5a28caf01f6ac274213168349a0f92b0eec Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:14:49 +0100 Subject: [PATCH 07/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 587155a..e35d0c9 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -13,8 +13,3 @@ export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" "${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" > /dev/null 2>&1 "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json - -# Display the vulnerability report -if [[ -f vulnerabilities-repository-report.json ]]; then - cat vulnerabilities-repository-report.json -fi From 50be41834b958bd4cbc17129c381e78fea69608b Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:17:00 +0100 Subject: [PATCH 08/22] CCM-17525: Updating grype checks --- scripts/reports/scan-vulnerabilities.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/reports/scan-vulnerabilities.sh b/scripts/reports/scan-vulnerabilities.sh index 6d007e3..0ebb39d 100755 --- a/scripts/reports/scan-vulnerabilities.sh +++ b/scripts/reports/scan-vulnerabilities.sh @@ -55,8 +55,7 @@ function run-grype-natively() { sbom:"$PWD/sbom-repository-report.json" \ --output json \ $fail_on_opt \ - --file "$PWD/vulnerabilities-repository-report.tmp.json" \ - > /dev/null 2>&1 + --file "$PWD/vulnerabilities-repository-report.tmp.json" } function run-grype-in-docker() { @@ -82,8 +81,7 @@ function run-grype-in-docker() { sbom:/workdir/sbom-repository-report.json \ --output json \ $fail_on_opt \ - --file /workdir/vulnerabilities-repository-report.tmp.json \ - > /dev/null 2>&1 + --file /workdir/vulnerabilities-repository-report.tmp.json } function enrich-report() { From 48faf5c165b6f0f94aba640646fa06ea1ec3e5a0 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:22:26 +0100 Subject: [PATCH 09/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index e35d0c9..915081e 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -13,3 +13,9 @@ export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" "${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" > /dev/null 2>&1 "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json + +# Display Critical and High vulnerabilities +echo "" +echo "Critical and High Vulnerabilities:" +echo "==================================" +jq -r '.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | "\(.vulnerability.severity | ascii_upcase): \(.vulnerability.id) - \(.artifact.name)@\(.artifact.version)"' vulnerabilities-repository-report.tmp.json | sort From 12c5edf4c1c5e7625e06aaae37f7be6dfdbcad3e Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:28:09 +0100 Subject: [PATCH 10/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 915081e..6d564a2 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -10,12 +10,33 @@ cd "$(git rev-parse --show-toplevel)" export BUILD_DATETIME="${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}" export GRYPE_FAIL_ON_SEVERITY="${GRYPE_FAIL_ON_SEVERITY:-high}" +echo "Step 1: Creating SBOM..." "${TOOLING_ROOT}/scripts/reports/create-sbom-report.sh" > /dev/null 2>&1 +[[ -f sbom-repository-report.json ]] && echo " ✓ SBOM created" || echo " ✗ SBOM not found" + +echo "Step 2: Scanning vulnerabilities..." "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" +[[ -f vulnerabilities-repository-report.tmp.json ]] && echo " ✓ Vulnerability scan complete" || echo " ✗ Vulnerability report not found" + +echo "Step 3: Parsing vulnerabilities..." "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json +[[ -f vulnerabilities-repository-report.json ]] && echo " ✓ Vulnerabilities parsed" || echo " ✗ Parsed report not found" # Display Critical and High vulnerabilities echo "" echo "Critical and High Vulnerabilities:" echo "==================================" -jq -r '.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | "\(.vulnerability.severity | ascii_upcase): \(.vulnerability.id) - \(.artifact.name)@\(.artifact.version)"' vulnerabilities-repository-report.tmp.json | sort + +# Find which report file exists +REPORT_FILE="" +if [[ -f vulnerabilities-repository-report.json ]]; then + REPORT_FILE="vulnerabilities-repository-report.json" +elif [[ -f vulnerabilities-repository-report.tmp.json ]]; then + REPORT_FILE="vulnerabilities-repository-report.tmp.json" +fi + +if [[ -n "$REPORT_FILE" ]]; then + jq -r '.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | "\(.vulnerability.severity | ascii_upcase): \(.vulnerability.id) - \(.artifact.name)@\(.artifact.version)"' "$REPORT_FILE" | sort +else + echo "No vulnerability report found" +fi From 71c2e0221a0b5f65740505e4d455ab5c9180527b Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:29:39 +0100 Subject: [PATCH 11/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 6d564a2..f446e82 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -15,7 +15,7 @@ echo "Step 1: Creating SBOM..." [[ -f sbom-repository-report.json ]] && echo " ✓ SBOM created" || echo " ✗ SBOM not found" echo "Step 2: Scanning vulnerabilities..." -"${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" +"${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" || true [[ -f vulnerabilities-repository-report.tmp.json ]] && echo " ✓ Vulnerability scan complete" || echo " ✗ Vulnerability report not found" echo "Step 3: Parsing vulnerabilities..." From 448528fa8d01a38e90067a51807b0c03b5ca3603 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:32:11 +0100 Subject: [PATCH 12/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index f446e82..a93dc7b 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -19,8 +19,20 @@ echo "Step 2: Scanning vulnerabilities..." [[ -f vulnerabilities-repository-report.tmp.json ]] && echo " ✓ Vulnerability scan complete" || echo " ✗ Vulnerability report not found" echo "Step 3: Parsing vulnerabilities..." -"${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" vulnerabilities-repository-report.json -[[ -f vulnerabilities-repository-report.json ]] && echo " ✓ Vulnerabilities parsed" || echo " ✗ Parsed report not found" +REPORT_FILE="" +if [[ -f vulnerabilities-repository-report.json ]]; then + REPORT_FILE="vulnerabilities-repository-report.json" +elif [[ -f vulnerabilities-repository-report.tmp.json ]]; then + REPORT_FILE="vulnerabilities-repository-report.tmp.json" +fi + +if [[ -n "$REPORT_FILE" ]]; then + "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" "$REPORT_FILE" + echo " ✓ Vulnerabilities parsed" +else + echo " ✗ No vulnerability report found" + exit 1 +fi # Display Critical and High vulnerabilities echo "" From cb79fe433921534d4ec38a0f52d7dcb3cea09ebd Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:38:35 +0100 Subject: [PATCH 13/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index a93dc7b..ca0abb8 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -48,7 +48,19 @@ elif [[ -f vulnerabilities-repository-report.tmp.json ]]; then fi if [[ -n "$REPORT_FILE" ]]; then - jq -r '.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | "\(.vulnerability.severity | ascii_upcase): \(.vulnerability.id) - \(.artifact.name)@\(.artifact.version)"' "$REPORT_FILE" | sort + # Create markdown table of Critical and High vulns + jq -r ' + ["ID", "Package", "Language", "Version", "Fix", "Description"], + (.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | [ + .vulnerability.id, + .artifact.name, + (.artifact.language // "unknown"), + .artifact.version, + (if .vulnerability.fix.state then .vulnerability.fix.state else "no fix available" end), + .vulnerability.description + ]) | + @csv + ' "$REPORT_FILE" | column -t -s',' | sed 's/"//g' else echo "No vulnerability report found" fi From 2eea47c89a4ca56c516e9421cd897da1cb06eee1 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:43:34 +0100 Subject: [PATCH 14/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 31 --------------------------- 1 file changed, 31 deletions(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index ca0abb8..abdadac 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -33,34 +33,3 @@ else echo " ✗ No vulnerability report found" exit 1 fi - -# Display Critical and High vulnerabilities -echo "" -echo "Critical and High Vulnerabilities:" -echo "==================================" - -# Find which report file exists -REPORT_FILE="" -if [[ -f vulnerabilities-repository-report.json ]]; then - REPORT_FILE="vulnerabilities-repository-report.json" -elif [[ -f vulnerabilities-repository-report.tmp.json ]]; then - REPORT_FILE="vulnerabilities-repository-report.tmp.json" -fi - -if [[ -n "$REPORT_FILE" ]]; then - # Create markdown table of Critical and High vulns - jq -r ' - ["ID", "Package", "Language", "Version", "Fix", "Description"], - (.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | [ - .vulnerability.id, - .artifact.name, - (.artifact.language // "unknown"), - .artifact.version, - (if .vulnerability.fix.state then .vulnerability.fix.state else "no fix available" end), - .vulnerability.description - ]) | - @csv - ' "$REPORT_FILE" | column -t -s',' | sed 's/"//g' -else - echo "No vulnerability report found" -fi From a04e6bf7776cca32020d82327b65ed49a887ef8b Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 13:56:44 +0100 Subject: [PATCH 15/22] CCM-17525: Updating grype checks --- scripts/githooks/scan-dependencies.sh | 16 +++++++++----- scripts/reports/parse-vulnerabilities.sh | 28 ++++++++---------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index abdadac..4514471 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -16,7 +16,6 @@ echo "Step 1: Creating SBOM..." echo "Step 2: Scanning vulnerabilities..." "${TOOLING_ROOT}/scripts/reports/scan-vulnerabilities.sh" || true -[[ -f vulnerabilities-repository-report.tmp.json ]] && echo " ✓ Vulnerability scan complete" || echo " ✗ Vulnerability report not found" echo "Step 3: Parsing vulnerabilities..." REPORT_FILE="" @@ -27,9 +26,16 @@ elif [[ -f vulnerabilities-repository-report.tmp.json ]]; then fi if [[ -n "$REPORT_FILE" ]]; then - "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" "$REPORT_FILE" + "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" "$REPORT_FILE" "true" echo " ✓ Vulnerabilities parsed" -else - echo " ✗ No vulnerability report found" - exit 1 + + # Check if Critical or High vulnerabilities exist and fail + CRITICAL_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "Critical") | {id: .vulnerability.id, package: .artifact.name, version: .artifact.version}] | unique_by([.id, .package, .version]) | length' "$REPORT_FILE") + HIGH_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "High") | {id: .vulnerability.id, package: .artifact.name, version: .artifact.version}] | unique_by([.id, .package, .version]) | length' "$REPORT_FILE") + + if [[ "$CRITICAL_COUNT" -gt 0 || "$HIGH_COUNT" -gt 0 ]]; then + echo "" + echo "❌ Found $CRITICAL_COUNT Critical and $HIGH_COUNT High severity vulnerabilities" + exit 1 + fi fi diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index f4012e1..313b1f9 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -4,17 +4,19 @@ # Local changes may diverge from the template source of truth. # # Parse vulnerability report JSON and output a human-readable summary -# Usage: ./parse-vulnerabilities.sh -# +# Usage: ./parse-vulnerabilities.sh [critical-high-only] +# Options: +# critical-high-only Only print Critical and High severity sections set -euo pipefail if [[ $# -lt 1 ]]; then - echo "Usage: $0 " + echo "Usage: $0 [critical-high-only]" exit 1 fi REPORT_FILE="$1" +FILTER_CRITICAL_HIGH_ONLY="${2:-false}" if [[ ! -f "$REPORT_FILE" ]]; then echo "Error: File not found: $REPORT_FILE" @@ -88,20 +90,8 @@ print_severity_section() { print_severity_section "Critical" "$CRITICAL_COUNT" print_severity_section "High" "$HIGH_COUNT" -print_severity_section "Medium" "$MEDIUM_COUNT" -print_severity_section "Low" "$LOW_COUNT" - -# Priority packages summary -echo "---" -echo "" -echo "### Priority Packages to Update" -echo "" -jq -r ' - [.matches[] | select(.vulnerability.severity == "Critical" or .vulnerability.severity == "High") | .artifact.name] - | unique - | sort - | join(", ") -' "$REPORT_FILE" | fold -s -w 80 - -echo "" +if [[ "$FILTER_CRITICAL_HIGH_ONLY" != "true" ]]; then + print_severity_section "Medium" "$MEDIUM_COUNT" + print_severity_section "Low" "$LOW_COUNT" +fi From 56393499736fa6b6bc34c83e3456bf9950ceb60c Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 14:14:33 +0100 Subject: [PATCH 16/22] CCM-17525: Updating grype checks --- scripts/reports/parse-vulnerabilities.sh | 28 ++++++++++-------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index 313b1f9..c0ebf66 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -66,24 +66,20 @@ print_severity_section() { echo "### $severity ($count)" echo "" - echo "| ID | Package | Language | Version | Fix | Description |" - echo "|----|---------|---------|---------|-----|-------------|" jq -r --arg sev "$severity" ' - [.matches[] | select(.vulnerability.severity == $sev) | { - id: .vulnerability.id, - severity: .vulnerability.severity, - package: .artifact.name, - language: .artifact.language, - version: .artifact.version, - fix: (.vulnerability.fix.versions[0] // "N/A"), - description: .vulnerability.description - }] - | unique_by([.id, .package, .version]) - | sort_by(.id, .package) - | .[] - | "| \(.id) | \(.package) | \(.language) | \(.version) | \(.fix) | \(.description[0:70])... |" - ' "$REPORT_FILE" + (["ID", "Package", "Language", "Version", "File", "Fix", "Description"] | @tsv), + (["ID", "Package", "Language", "Version", "File", "Fix", "Description"] | map(length*"-") | @tsv), + (.matches[] | select(.vulnerability.severity == $sev) | [ + .vulnerability.id, + .artifact.name, + .artifact.language, + .artifact.version, + (.artifact.locations[0].path // "N/A"), + (.vulnerability.fix.versions[0] // "N/A"), + ((.vulnerability.description // "N/A") | .[0:70] + "...") + ] | @tsv) + ' "$REPORT_FILE" | sort -u | column -t -s $'\t' -o ' | ' echo "" } From c91155207c2fe90a59083c8cecb5cf6c199f53fe Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 14:17:32 +0100 Subject: [PATCH 17/22] CCM-17525: Updating grype checks --- scripts/reports/parse-vulnerabilities.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index c0ebf66..89a7be3 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -79,7 +79,7 @@ print_severity_section() { (.vulnerability.fix.versions[0] // "N/A"), ((.vulnerability.description // "N/A") | .[0:70] + "...") ] | @tsv) - ' "$REPORT_FILE" | sort -u | column -t -s $'\t' -o ' | ' + ' "$REPORT_FILE" | sort -u | sed 's/ / | /g' echo "" } From 8db144970df4c666aca1b8dd12c5e2c09a0a4329 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 14:19:54 +0100 Subject: [PATCH 18/22] CCM-17525: Updating grype checks --- scripts/reports/parse-vulnerabilities.sh | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index 89a7be3..5d83987 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -66,20 +66,24 @@ print_severity_section() { echo "### $severity ($count)" echo "" + echo "| ID | Package | Language | Version | File | Fix | Description |" + echo "|---|---|---|---|---|---|---|" jq -r --arg sev "$severity" ' - (["ID", "Package", "Language", "Version", "File", "Fix", "Description"] | @tsv), - (["ID", "Package", "Language", "Version", "File", "Fix", "Description"] | map(length*"-") | @tsv), - (.matches[] | select(.vulnerability.severity == $sev) | [ - .vulnerability.id, - .artifact.name, - .artifact.language, - .artifact.version, - (.artifact.locations[0].path // "N/A"), - (.vulnerability.fix.versions[0] // "N/A"), - ((.vulnerability.description // "N/A") | .[0:70] + "...") - ] | @tsv) - ' "$REPORT_FILE" | sort -u | sed 's/ / | /g' + [.matches[] | select(.vulnerability.severity == $sev) | { + id: .vulnerability.id, + package: .artifact.name, + language: .artifact.language, + version: .artifact.version, + file: (.artifact.locations[0].path // "N/A"), + fix: (.vulnerability.fix.versions[0] // "N/A"), + description: ((.vulnerability.description // "N/A") | .[0:70] + "...") + }] + | unique_by([.id, .package, .version]) + | sort_by(.id) + | .[] + | "| \(.id) | \(.package) | \(.language) | \(.version) | \(.file) | \(.fix) | \(.description) |" + ' "$REPORT_FILE" echo "" } From f38eee4766309e44aeaf89896983f3eca0b60ee7 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 15:02:21 +0100 Subject: [PATCH 19/22] CCM-17525: Updating grype checks --- scripts/config/syft.yaml | 2 ++ scripts/githooks/scan-dependencies.sh | 1 - scripts/reports/parse-vulnerabilities.sh | 7 +++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/config/syft.yaml b/scripts/config/syft.yaml index e9f5f58..f47f61e 100644 --- a/scripts/config/syft.yaml +++ b/scripts/config/syft.yaml @@ -4,6 +4,8 @@ # - "./out/**/*.json" exclude: - ./.git/** + - ./**/terraform/**/.terraform/** + - ./**/terraform/plugin-cache/** # maximum number of workers used to process the list of package catalogers in parallel parallelism: 3 diff --git a/scripts/githooks/scan-dependencies.sh b/scripts/githooks/scan-dependencies.sh index 4514471..6c4fcef 100755 --- a/scripts/githooks/scan-dependencies.sh +++ b/scripts/githooks/scan-dependencies.sh @@ -27,7 +27,6 @@ fi if [[ -n "$REPORT_FILE" ]]; then "${TOOLING_ROOT}/scripts/reports/parse-vulnerabilities.sh" "$REPORT_FILE" "true" - echo " ✓ Vulnerabilities parsed" # Check if Critical or High vulnerabilities exist and fail CRITICAL_COUNT=$(jq '[.matches[] | select(.vulnerability.severity == "Critical") | {id: .vulnerability.id, package: .artifact.name, version: .artifact.version}] | unique_by([.id, .package, .version]) | length' "$REPORT_FILE") diff --git a/scripts/reports/parse-vulnerabilities.sh b/scripts/reports/parse-vulnerabilities.sh index 5d83987..181d086 100755 --- a/scripts/reports/parse-vulnerabilities.sh +++ b/scripts/reports/parse-vulnerabilities.sh @@ -66,8 +66,8 @@ print_severity_section() { echo "### $severity ($count)" echo "" - echo "| ID | Package | Language | Version | File | Fix | Description |" - echo "|---|---|---|---|---|---|---|" + echo "| ID | Package | Language | Version | Fix | Description |" + echo "|---|---|---|---|---|---|" jq -r --arg sev "$severity" ' [.matches[] | select(.vulnerability.severity == $sev) | { @@ -75,14 +75,13 @@ print_severity_section() { package: .artifact.name, language: .artifact.language, version: .artifact.version, - file: (.artifact.locations[0].path // "N/A"), fix: (.vulnerability.fix.versions[0] // "N/A"), description: ((.vulnerability.description // "N/A") | .[0:70] + "...") }] | unique_by([.id, .package, .version]) | sort_by(.id) | .[] - | "| \(.id) | \(.package) | \(.language) | \(.version) | \(.file) | \(.fix) | \(.description) |" + | "| \(.id) | \(.package) | \(.language) | \(.version) | \(.fix) | \(.description) |" ' "$REPORT_FILE" echo "" From 190f741df16e0566753fe1fcb3e834d09d7b23ad Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Tue, 7 Jul 2026 15:19:18 +0100 Subject: [PATCH 20/22] CCM-17525: Updating grype checks --- scripts/config/syft.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/config/syft.yaml b/scripts/config/syft.yaml index f47f61e..c5ec846 100644 --- a/scripts/config/syft.yaml +++ b/scripts/config/syft.yaml @@ -6,6 +6,8 @@ exclude: - ./.git/** - ./**/terraform/**/.terraform/** - ./**/terraform/plugin-cache/** + - ./**/node_modules/** + - ./node_modules/** # maximum number of workers used to process the list of package catalogers in parallel parallelism: 3 From 5af930404011b66890cdb44ac86b01fea7148fee Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Wed, 8 Jul 2026 11:40:02 +0100 Subject: [PATCH 21/22] CCM-17525: Updating grype checks --- scripts/reports/scan-vulnerabilities.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/reports/scan-vulnerabilities.sh b/scripts/reports/scan-vulnerabilities.sh index 0ebb39d..488b08f 100755 --- a/scripts/reports/scan-vulnerabilities.sh +++ b/scripts/reports/scan-vulnerabilities.sh @@ -53,6 +53,7 @@ function run-grype-natively() { # shellcheck disable=SC2086 grype \ sbom:"$PWD/sbom-repository-report.json" \ + --config "$PWD/scripts/config/grype.yaml" \ --output json \ $fail_on_opt \ --file "$PWD/vulnerabilities-repository-report.tmp.json" @@ -79,6 +80,7 @@ function run-grype-in-docker() { --volume /tmp/grype/db:/.cache/grype/db \ "$image" \ sbom:/workdir/sbom-repository-report.json \ + --config /workdir/scripts/config/grype.yaml \ --output json \ $fail_on_opt \ --file /workdir/vulnerabilities-repository-report.tmp.json From 85a09049c88d38724d7c36ebf207a2fbd9e90e77 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Wed, 8 Jul 2026 11:47:58 +0100 Subject: [PATCH 22/22] CCM-17525: Updating grype checks --- scripts/config/syft.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/config/syft.yaml b/scripts/config/syft.yaml index c5ec846..f47f61e 100644 --- a/scripts/config/syft.yaml +++ b/scripts/config/syft.yaml @@ -6,8 +6,6 @@ exclude: - ./.git/** - ./**/terraform/**/.terraform/** - ./**/terraform/plugin-cache/** - - ./**/node_modules/** - - ./node_modules/** # maximum number of workers used to process the list of package catalogers in parallel parallelism: 3