Scan Comparison (nat scan --diff)
nat scan --diff compares the results of your current scan against a previous baseline scan, making it easy to catch regressions, confirm fixes, and track security posture over time.
Quick use: nat scan --url https://api.example.com --diff latest — scan and instantly see what's new, what's fixed, and what's changed compared to your last scan.
What it shows
A diff scan produces a structured comparison across four categories:
| Category | Description |
|---|---|
| 🆕 New findings | Findings present in the current scan but absent from the baseline |
| ✅ Fixed findings | Findings that existed in the baseline but are gone in the current scan |
| 🔄 Changed severity | Findings present in both scans, but with a different severity level |
| ➡️ Unchanged findings | Findings identical in both scans |
Usage
nat scan --url <target> --diff <scan-id|latest> [other nat scan flags]Flags
| Flag | Description |
|---|---|
--diff <scan-id> | Compare against a specific previous scan by ID |
--diff latest | Compare against the most recent scan for the same target URL |
All standard nat scan flags work alongside --diff:
nat scan \
--url https://api.example.com \
--spec ./openapi.yaml \
--diff latest \
--fail-on high \
--format sarifExample output
Running nat scan --url https://api.example.com --diff latest:
NAT Scan Comparison
Current scan: scan_abc123 (2025-01-15 14:32)
Baseline scan: scan_xyz789 (2025-01-08 10:15)
Target: https://api.example.com
🆕 New findings (2)
────────────────────────────────────────────────────
[HIGH] SQL Injection GET /users/search?q=
[MEDIUM] Missing rate limit POST /auth/login
✅ Fixed findings (3)
────────────────────────────────────────────────────
[HIGH] BOLA vulnerability GET /orders/{id}
[MEDIUM] Exposed stack trace POST /products
[LOW] Missing CORS header GET /health
🔄 Changed severity (1)
────────────────────────────────────────────────────
[MEDIUM→HIGH] Weak JWT algorithm POST /auth/token
➡️ Unchanged findings (7)
────────────────────────────────────────────────────
[HIGH] Broken Object Level Auth DELETE /users/{id}
... and 6 more
────────────────────────────────────────────────────
Summary: +2 new ✅3 fixed 🔄1 changed ➡️7 unchanged
Result: FAIL — new high-severity finding introducedJSON diff output
nat scan --url https://api.example.com --diff latest --format json{
"current_scan_id": "scan_abc123",
"baseline_scan_id": "scan_xyz789",
"target": "https://api.example.com",
"diff": {
"new": [
{
"id": "finding_new1",
"title": "SQL Injection",
"severity": "high",
"endpoint": "GET /users/search",
"parameter": "q"
}
],
"fixed": [
{
"id": "finding_old1",
"title": "BOLA vulnerability",
"severity": "high",
"endpoint": "GET /orders/{id}"
}
],
"changed_severity": [
{
"id": "finding_chg1",
"title": "Weak JWT algorithm",
"previous_severity": "medium",
"current_severity": "high",
"endpoint": "POST /auth/token"
}
],
"unchanged": 7
},
"summary": {
"new": 2,
"fixed": 3,
"changed_severity": 1,
"unchanged": 7
},
"result": "fail"
}CI/CD usage
PR regression gate
Fail a pull request if it introduces new security findings:
# .github/workflows/nat-scan.yml
name: Security Regression Gate
on:
pull_request:
branches: [main]
jobs:
nat-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run NAT scan with regression check
run: nat scan --url ${{ vars.STAGING_URL }} --diff latest --fail-on high --format sarif
- name: Upload SARIF to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: nat-results.sarifWhen using --diff latest, NAT compares against the most recent scan for the same target URL. For PR gates, make sure your main branch scan runs regularly (e.g., on every merge or nightly) so the baseline is fresh.
Compare against a specific scan
Pin a specific scan as a baseline using its ID from the NAT dashboard:
nat scan --url https://api.example.com --diff scan_xyz789This is useful for post-deployment validation: compare the production scan against the pre-deployment baseline.
Multi-environment comparison
jobs:
nat-scan-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Scan the PR environment and diff against main branch baseline
- name: Scan PR environment
run: |
nat scan \
--url ${{ vars.PR_STAGING_URL }} \
--spec ./openapi.yaml \
--diff latest \
--fail-on high \
--format sarif \
--no-color
- name: Upload results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: nat-results.sarifUse cases
PR regression gates
Block a pull request merge if new security findings are introduced. Use --diff latest with --fail-on high so the build fails only when regressions are high severity or above.
Weekly trend tracking
Run a scheduled scan with --diff to track security posture over time:
# .github/workflows/nat-weekly.yml
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am
jobs:
weekly-scan:
runs-on: ubuntu-latest
steps:
- name: Weekly security scan
run: |
nat scan \
--url ${{ vars.PRODUCTION_URL }} \
--diff latest \
--format markdown \
--output weekly-report.mdPost-deployment validation
After deploying a new version, compare the post-deploy scan against the pre-deploy baseline:
Scan before deploying
# Capture the pre-deploy scan ID
PRE_DEPLOY_SCAN=$(nat scan --url https://api.example.com --format json | jq -r '.scan_id')
echo "Pre-deploy scan: $PRE_DEPLOY_SCAN"Deploy your application
# Your deployment step hereScan after deploying and compare
nat scan --url https://api.example.com --diff $PRE_DEPLOY_SCAN --fail-on criticalIf the deployment introduced critical findings, the scan exits with a non-zero status so you can roll back immediately.
Troubleshooting
| Problem | Fix |
|---|---|
--diff latest says "no previous scan found" | No prior scan exists for this target URL. Run one full scan first, then use --diff latest on subsequent runs. |
| Baseline scan ID not found | Verify the scan ID in the NAT dashboard. IDs look like scan_abc123. |
| Diff shows unexpected "new" findings for unchanged code | The baseline scan may have used a different spec or auth config. Ensure both scans use the same --spec and auth settings. |
--diff and --fail-on together not failing | Check that --fail-on threshold matches the severity of the new findings. Use --fail-on medium to catch medium-and-above regressions. |