diff --git a/.github/workflows/cve.yml b/.github/workflows/cve.yml new file mode 100644 index 000000000..04899875a --- /dev/null +++ b/.github/workflows/cve.yml @@ -0,0 +1,53 @@ +name: CVE Scanning + +permissions: + contents: read + +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] + schedule: + - cron: '0 6 * * 1' # Weekly Monday 6am UTC + +jobs: + grype: + name: Grype dependency scan + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Install Grype + id: grype + uses: anchore/scan-action/download-grype@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7 + with: + cache-db: true + + - name: Scan (table) + run: | + ${{ steps.grype.outputs.cmd }} dir:. \ + --config .grype.yaml \ + --output template + + - name: Scan (SARIF) + if: ${{ always() }} + run: | + ${{ steps.grype.outputs.cmd }} dir:. \ + --config .grype.yaml \ + --output sarif --file grype-results.sarif || true + + - name: Upload SARIF report + if: ${{ always() }} + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 + with: + sarif_file: grype-results.sarif diff --git a/.grype-report.tmpl b/.grype-report.tmpl new file mode 100644 index 000000000..51be56eb5 --- /dev/null +++ b/.grype-report.tmpl @@ -0,0 +1,6 @@ +{{printf "%-8s | %-19s | %-50s | %-15s | %s" "SEVERITY" "ADVISORY" "PACKAGE" "FIXED IN" "SOURCE"}} +{{printf "%-8s | %-19s | %-50s | %-15s | %s" "--------" "-------------------" "--------------------------------------------------" "---------------" "------"}} +{{- range .Matches -}} +{{- $loc := "" -}}{{- range .Artifact.Locations -}}{{- $loc = .RealPath -}}{{- end}} +{{printf "%-8s | %-19s | %-50s | %-15s | %s" .Vulnerability.Severity .Vulnerability.ID (printf "%s@%s" .Artifact.Name .Artifact.Version) (join ", " .Vulnerability.Fix.Versions) $loc}} +{{- end}} diff --git a/.grype.yaml b/.grype.yaml new file mode 100644 index 000000000..1bf3cd4b3 --- /dev/null +++ b/.grype.yaml @@ -0,0 +1,11 @@ +fail-on-severity: high +sort-by: severity +output-template-file: .grype-report.tmpl + +ignore: + - fix-state: 'wont-fix' + - fix-state: 'not-fixed' + +# Comment out to include scanning experimental license inventory +exclude: + - './experimental/**' diff --git a/package-lock.json b/package-lock.json index 3903023c2..0845db1aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4398,6 +4398,17 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "dev": true,