Baselines & Tracking

Track security progress over time by comparing scans against a baseline. Show only new findings, celebrate fixes, and maintain visibility into existing issues.

What is a Baseline?

A baseline is a snapshot of your security findings at a point in time. It lets you:

  • See only new issues — Focus on what changed, not legacy debt
  • Track progress — See when issues are fixed
  • Maintain awareness — Know existing issues without noise

Creating a Baseline

Create a baseline from your current scan:

oculum baseline create

This:

  1. Runs a full scan of your codebase
  2. Stores finding hashes in .oculum/baseline.json
  3. Records git commit and branch info

With Options

# Create baseline with specific depth
oculum baseline create --depth verified

# Create baseline for specific path
oculum baseline create ./src

# Quiet mode (no output)
oculum baseline create -q

Scanning Against Baseline

Show only new findings (not in baseline):

oculum scan --new

This compares current findings against the baseline and shows:

  • New findings — Issues not in the baseline
  • Fixed count — How many issues were resolved
  • Existing count — How many baseline issues remain

Example Output

┌────────────────────────────────────────────────────────────────┐
│  Oculum Security Scan (Baseline Mode)                          │
│  Baseline: 2026-01-15 (abc1234)                                │
└────────────────────────────────────────────────────────────────┘

New findings: 2
Fixed since baseline: 3
Existing issues: 12

NEW FINDINGS:

  HIGH: Unvalidated User Input
   src/api/new-endpoint.ts:23
   User input passed directly to prompt

  MEDIUM: Missing Rate Limiting
   src/api/new-endpoint.ts:1
   No rate limiting on AI endpoint

Viewing Baseline Info

See what's in your current baseline:

oculum baseline show

Output:

Baseline Information:

  Created: 2026-01-15T10:30:00Z
  Git commit: abc1234
  Git branch: main
  Scan depth: verified

  Findings:
    Critical: 0
    High: 5
    Medium: 8
    Low: 3
    Info: 2
    Total: 18

Clearing a Baseline

Remove the baseline to see all findings again:

oculum baseline clear

This deletes .oculum/baseline.json.


Baseline File Format

The baseline is stored in .oculum/baseline.json:

{
  "version": 1,
  "createdAt": "2026-01-15T10:30:00Z",
  "gitCommit": "abc1234def567890",
  "gitBranch": "main",
  "scanDepth": "verified",
  "findings": [
    {
      "hash": "a1b2c3d4e5f67890",
      "path": "src/api/auth.ts",
      "line": 42,
      "category": "hardcoded_secret",
      "severity": "high"
    }
  ],
  "summary": {
    "critical": 0,
    "high": 5,
    "medium": 8,
    "low": 3,
    "info": 2,
    "total": 18
  }
}

Version Control

Recommended: Commit .oculum/baseline.json to version control.

This allows:

  • Team members to use the same baseline
  • CI to compare against the established baseline
  • Tracking baseline changes over time
git add .oculum/baseline.json
git commit -m "Update security baseline"

CI/CD Integration

PR Checks: Show Only New Issues

# GitHub Actions
- name: Security Scan (new findings only)
  run: |
    oculum scan --new --fail-on high

This fails only if the PR introduces new high/critical issues.

Main Branch: Update Baseline

# After merging to main
- name: Update Baseline
  if: github.ref == 'refs/heads/main'
  run: |
    oculum baseline create --depth verified
    git add .oculum/baseline.json
    git commit -m "Update security baseline" || true
    git push

Complete Workflow

name: Security

on:
  pull_request:
  push:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # On PRs: Show only new findings
      - name: Scan PR
        if: github.event_name == 'pull_request'
        run: oculum scan --new --fail-on high

      # On main: Full scan and update baseline
      - name: Scan Main
        if: github.ref == 'refs/heads/main'
        run: |
          oculum scan --depth verified --fail-on high
          oculum baseline create

Baseline Strategies

Strategy 1: Fresh Start

Best for new projects or major refactors:

# Fix all critical/high issues first
oculum scan --fail-on high

# Then create baseline
oculum baseline create

Strategy 2: Accept Legacy, Block New

Best for existing projects with security debt:

# Create baseline of current state
oculum baseline create

# From now on, only fail on new issues
oculum scan --new --fail-on high

Strategy 3: Gradual Improvement

Reduce baseline over time:

# Create initial baseline
oculum baseline create  # 50 findings

# Fix issues, update baseline
# ... fix 10 issues ...
oculum baseline create  # 40 findings

# Continue reducing
# Track progress in your issue tracker

Hash Stability

Baseline comparison uses finding hashes, which are stable across:

  • Whitespace changes
  • Minor formatting
  • Line number changes (within reason)

Hashes change when:

  • The actual vulnerable code changes
  • The file is renamed/moved
  • The detection category changes

Baseline Diff Details

The --new flag adds baseline information to the scan result:

{
  "baselineDiff": {
    "baselineCreatedAt": "2026-01-15T10:30:00Z",
    "baselineCommit": "abc1234",
    "newCount": 2,
    "fixedCount": 3,
    "existingCount": 12,
    "fixedFindings": [
      {
        "hash": "x1y2z3...",
        "category": "hardcoded_secret"
      }
    ]
  }
}

Best Practices

1. Create Baseline at Known-Good State

Don't baseline a "broken" state. Fix critical issues first:

oculum scan --fail-on critical  # Fix these
oculum baseline create           # Then baseline

2. Update Baseline Deliberately

Don't auto-update on every merge. Update when:

  • Security debt is intentionally accepted
  • Major fixes are completed
  • Team reviews and approves the new state

3. Document Baseline Decisions

Keep notes on why certain findings are in the baseline:

git commit -m "Update baseline: accepted 3 low-severity config warnings per SECURITY-123"

4. Review Fixed Findings

Celebrate progress! When --new shows fixed findings, acknowledge the improvement.


Related