Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/actions/osv-severity-gate/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: OSV severity gate
description: >
Fails the build only when osv-scanner results contain a vulnerability at or
above the CVSS threshold (default 7.0, i.e. HIGH/CRITICAL). osv-scanner has
no severity filter of its own and exits non-zero on ANY finding, so the scan
step must run with `continue-on-error: true`, output JSON to a file, and let
this gate decide pass/fail.

inputs:
scan-outcome:
description: Outcome of the osv-scanner step (`steps.<id>.outcome`)
required: true
results-file:
description: Path to the osv-scanner JSON results file
required: false
default: osv-results.json
cvss-threshold:
description: Minimum CVSS score that fails the build
required: false
default: "7.0"

runs:
using: composite
steps:
- name: Evaluate scan results
shell: bash
env:
SCAN_OUTCOME: ${{ inputs.scan-outcome }}
RESULTS_FILE: ${{ inputs.results-file }}
CVSS_THRESHOLD: ${{ inputs.cvss-threshold }}
run: |
set -euo pipefail

# osv-scanner exit codes: 0 = no findings, 1 = findings, >1 = scan error.
if [[ "$SCAN_OUTCOME" == "success" ]]; then
echo "osv-scanner found no vulnerabilities."
rm -f "$RESULTS_FILE"
exit 0
fi

if ! jq -e . "$RESULTS_FILE" >/dev/null 2>&1; then
echo "::error::osv-scanner failed without producing valid JSON results ($RESULTS_FILE). This is a scan error (e.g. bad flags or network failure), not a vulnerability finding. Check the audit step logs."
exit 1
fi

echo "Vulnerability findings (max CVSS per advisory group):"
jq -r '
.results[]?.packages[]?
| .package as $p
| .groups[]?
| " \($p.name)@\($p.version) CVSS \(.max_severity // "" | if . == "" then "unscored" else . end) \(.ids | join(", "))"
' "$RESULTS_FILE"

TOTAL=$(jq '[.results[]?.packages[]?.groups[]?] | length' "$RESULTS_FILE")
UNSCORED=$(jq '[.results[]?.packages[]?.groups[]? | select((.max_severity // "") == "")] | length' "$RESULTS_FILE")
BLOCKING=$(jq --argjson t "$CVSS_THRESHOLD" '
[.results[]?.packages[]?.groups[]?
| .max_severity // ""
| select(. != "")
| tonumber
| select(. >= $t)]
| length
' "$RESULTS_FILE")

# Keep the working tree clean for later git/publish steps.
rm -f "$RESULTS_FILE"

if [[ "$UNSCORED" -gt 0 ]]; then
echo "::warning::$UNSCORED advisory group(s) have no CVSS score and were not counted against the threshold. Review them manually."
fi

if [[ "$BLOCKING" -gt 0 ]]; then
echo "::error::$BLOCKING of $TOTAL advisory group(s) at or above CVSS $CVSS_THRESHOLD (HIGH/CRITICAL). Failing the release. Fix the dependency or add a justified exclusion to osv-scanner.toml."
exit 1
fi

echo "$TOTAL advisory group(s) found, none at or above CVSS $CVSS_THRESHOLD. Not blocking the release."
echo "::warning::$TOTAL medium/low advisory group(s) present — see log above. Track remediation in WCN-1550."
14 changes: 12 additions & 2 deletions .github/workflows/npmjs-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,25 @@ jobs:
run: |
yarn install --frozen-lockfile

# osv-scanner has no severity filter and exits non-zero on ANY finding,
# so run it with continue-on-error and let the severity gate below
# decide pass/fail based on CVSS score (fails on HIGH/CRITICAL only).
- name: Audit Dependencies
id: osv-scan
continue-on-error: true
uses: google/osv-scanner-action/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
with:
scan-args: |-
--config=osv-scanner.toml
--severity=HIGH
--severity=CRITICAL
--format=json
--output-file=osv-results.json
./

- name: Enforce Vulnerability Severity Threshold
uses: ./.github/actions/osv-severity-gate
with:
scan-outcome: ${{ steps.osv-scan.outcome }}

- name: Run dependency check
run: |
yarn check-deps
Expand Down
14 changes: 12 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,25 @@ jobs:
- name: Install BitGoJS
run: sfw yarn install --with-frozen-lockfile

# osv-scanner has no severity filter and exits non-zero on ANY finding,
# so run it with continue-on-error and let the severity gate below
# decide pass/fail based on CVSS score (fails on HIGH/CRITICAL only).
- name: Audit Dependencies
id: osv-scan
continue-on-error: true
uses: google/osv-scanner-action/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
with:
scan-args: |-
--config=osv-scanner.toml
--severity=HIGH
--severity=CRITICAL
--format=json
--output-file=osv-results.json
./

- name: Enforce Vulnerability Severity Threshold
uses: ./.github/actions/osv-severity-gate
with:
scan-outcome: ${{ steps.osv-scan.outcome }}

- name: Set Environment Variable for Alpha
if: github.ref != 'refs/heads/master' # only publish changes if on feature branches
run: |
Expand Down