GitHub Action
GitHub Action
CVERiskPilot Compliance Scan@cveriskpilot/scan against your codebase, maps findings to compliance controls, and can post results as a PR comment.Quick Start
Add this step to any workflow file. The action runs the latest scanner (0.2.0 or later) via npx --yes @cveriskpilot/scan with your chosen inputs. Inputs you leave empty fall back to a committed .cveriskpilot.json profile, then to the scanner defaults.
# Minimal workflow
name: Compliance Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: devbrewster/cveriskpilot-scan/action@main
Full Workflow Example
A complete workflow with a PR comment, SARIF upload to GitHub Code Scanning (done by the action when upload-sarif is true, the default) and upload to the CVERiskPilot dashboard. The API key is passed on pushes to main only: an upload updates the dashboard's findings for the repository, and a pull request scans code that is not merged, so it would close findings it happens to fix and open cases for code that may never merge. Pull requests still get the check and the comment.
name: Compliance Scan
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
pull-requests: write
security-events: write
jobs:
compliance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run CVERiskPilot Compliance Scan
id: scan
uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: enterprise
fail-on: high
comment: 'true'
upload-sarif: 'true'
# upload from pushes to main only, never pull requests
api-key: ${{ github.event_name == 'push' && secrets.CRP_API_KEY || '' }}
# only when your organization has several clients
client: 'Acme Production'
fail-on-upload-error: 'true'
Inputs
All inputs are optional. Configure them under the with: key in your workflow step.
| Input | Description | Options | Default |
|---|---|---|---|
preset | Framework preset to use for compliance mapping. Leave it empty to use the committed .cveriskpilot.json profile. | federal, defense, enterprise, startup, devsecops, all | (profile, else all) |
fail-on | Severity threshold that causes the action to fail. Any finding at or above this level triggers a non-zero exit code. Leave it empty to use the committed .cveriskpilot.json profile. | critical, high, medium, low, info | (profile, else critical) |
scanners | Limit which scanners run. Comma-separated list. | deps, secrets, iac, api | (all scanners) |
exclude | Glob patterns to exclude from scanning. Comma-separated. | Any valid glob pattern | (none) |
api-key | CVERiskPilot API key. When set, every run is uploaded to your workspace, including runs with no findings, so findings fixed since the last scan move to verification. Use a GitHub secret, and pass it on default-branch runs only: a pull request scans unmerged code. | API key string | (none) |
client | Client to upload into, by id or exact name. Needed when your organization has more than one client and the API key is not limited to one. | Client id or name | (none) |
asset | Asset name for the upload. The default names the repository as host/owner/repo, the same on every run. | Any name | (repository) |
api-url | CVERiskPilot address. Change it only if CVERiskPilot support gives you a different endpoint. | URL | https://cveriskpilot.com |
fail-on-upload-error | Fail the step with exit code 3 when nothing reaches the dashboard (the upload failed, or no scanner produced complete results to send). By default the error is printed in the job log and the result reflects the scan only. | true, false | false |
upload-sarif | Run a local SARIF pass and upload it to GitHub Code Scanning. Needs the security-events: write permission. | true, false | true |
comment | Whether to post scan results as a PR comment. | true, false | true |
github-token | GitHub token used for posting PR comments. The default token works for most cases. | GitHub token string | github.token |
Outputs
Access outputs from subsequent steps using steps.<step-id>.outputs.<name>.
| Output | Description |
|---|---|
exit-code | 0 = pass, 1 = fail (findings met threshold), 2 = error (scan could not complete), 3 = nothing reached the dashboard and fail-on-upload-error is true. |
total-findings | Total number of findings discovered across all scanners. |
critical-count | Number of findings with CRITICAL severity. |
high-count | Number of findings with HIGH severity. |
controls-affected | Number of unique compliance controls affected by the findings. |
comment-id | GitHub comment ID if a PR comment was posted. Empty if comment was not posted. |
PR Comments
When comment: 'true' (the default), the action posts a detailed summary comment on the pull request. The comment includes:
- Severity summary with color-coded counts (critical, high, medium, low)
- Findings table with file paths, CWE identifiers, and matched compliance controls
- Compliance impact breakdown showing which framework controls are affected
- Rule-based triage verdicts: actionable, needs review, or auto-dismissed
The action uses a hidden HTML marker <!-- crp-scan-comment --> to identify its comments. On subsequent runs, it updates the existing comment instead of posting a new one, keeping your PR clean and free of duplicate reports.
Internally, the action uses actions/github-script@v7 to interact with the GitHub API for comment management.
Common Workflow Examples
- uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: startup
fail-on: critical
- name: CMMC Compliance Scan
uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: defense
fail-on: high
- uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: enterprise
comment: 'false'
api-key: ${{ secrets.CRP_API_KEY }}
client: 'Acme Production'
- uses: devbrewster/cveriskpilot-scan/action@main
with:
scanners: deps
fail-on: high
- uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: enterprise
exclude: '**/test/**,**/fixtures/**,docs/**'
Using Outputs
Reference outputs from the scan step in subsequent steps to build conditional workflows, send notifications, or gate deployments.
steps:
- uses: actions/checkout@v4
- name: Run Compliance Scan
id: scan
uses: devbrewster/cveriskpilot-scan/action@main
with:
preset: enterprise
fail-on: high
- name: Check Results
if: always()
run: |
echo "Exit code: ${{ steps.scan.outputs.exit-code }}"
echo "Total findings: ${{ steps.scan.outputs.total-findings }}"
echo "Critical: ${{ steps.scan.outputs.critical-count }}"
echo "High: ${{ steps.scan.outputs.high-count }}"
echo "Controls affected: ${{ steps.scan.outputs.controls-affected }}"
- name: Block Deploy on Critical
if: steps.scan.outputs.critical-count != '0'
run: |
echo "Blocking deployment: ${{ steps.scan.outputs.critical-count }} critical findings"
exit 1
How It Works
The GitHub Action is a composite action that orchestrates three steps internally:
Setup Node.js
Uses actions/setup-node@v4 to ensure Node.js 20 is available in the runner environment.
Run Scanner
Executes npx --yes @cveriskpilot/scan (the latest release, 0.2.0 or later) with the configured preset, scanners, and output options.
Post Comment
Uses actions/github-script@v7 to post or update the PR comment with scan results.
With an api-key, the scan step also uploads the run to CVERiskPilot. The upload names the repository as its asset and carries the commit, branch and pull request number, and the job log shows the link to the upload on the dashboard, or the reason an upload failed. The pass/fail verdict also appears on the Pipelines page.
When upload-sarif is true (the default), the action runs a second, local-only pass that writes SARIF 2.1.0 and uploads it to GitHub Code Scanning. Branding uses a shield icon with blue color in the GitHub Marketplace listing.
Next Steps
CLI Reference
Full flag reference for the underlying crp-scan CLI.
Open pagePipeline Setup Guide
Step-by-step guide for CI/CD integration beyond GitHub Actions.
Open pageStart Audit Readiness trial
Create a workspace, begin a 14-day Audit Readiness trial, and move into the hosted API flow.
Start Audit Readiness trial