Documentation
Guides
Scan Comparison

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:

CategoryDescription
🆕 New findingsFindings present in the current scan but absent from the baseline
Fixed findingsFindings that existed in the baseline but are gone in the current scan
🔄 Changed severityFindings present in both scans, but with a different severity level
➡️ Unchanged findingsFindings identical in both scans

Usage

nat scan --url <target> --diff <scan-id|latest> [other nat scan flags]

Flags

FlagDescription
--diff <scan-id>Compare against a specific previous scan by ID
--diff latestCompare 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 sarif

Example 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 introduced

JSON 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.sarif

When 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_xyz789

This 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.sarif

Use 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.md

Post-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 here

Scan after deploying and compare

nat scan --url https://api.example.com --diff $PRE_DEPLOY_SCAN --fail-on critical

If the deployment introduced critical findings, the scan exits with a non-zero status so you can roll back immediately.


Troubleshooting

ProblemFix
--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 foundVerify the scan ID in the NAT dashboard. IDs look like scan_abc123.
Diff shows unexpected "new" findings for unchanged codeThe 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 failingCheck that --fail-on threshold matches the severity of the new findings. Use --fail-on medium to catch medium-and-above regressions.

Related

Was this helpful?