Exit Codes

Oculum uses exit codes to communicate scan results to CI/CD systems. Use these codes to control pipeline behavior.

Exit Code Reference

CodeMeaningCI Behavior
0Success — no findings at or above thresholdPipeline continues
1Findings found at or above --fail-on severityPipeline fails
2Configuration error or invalid argumentsPipeline fails
3Authentication required but not providedPipeline fails
130User cancelled (Ctrl+C)Pipeline fails

Controlling Exit Behavior

--fail-on

Set the severity threshold for failing:

# Fail only on critical issues
oculum scan --fail-on critical

# Fail on high or critical
oculum scan --fail-on high

# Fail on medium or above
oculum scan --fail-on medium

# Fail on any finding (except info)
oculum scan --fail-on low

# Never fail on findings (default)
oculum scan --fail-on none

Severity Hierarchy

From highest to lowest:

  1. critical — Immediate action required
  2. high — Significant security risk
  3. medium — Moderate risk
  4. low — Minor issues
  5. info — Informational

--fail-on high means fail if there are high OR critical findings.


CI/CD Examples

GitHub Actions

- name: Security Scan
  run: oculum scan --fail-on high
  # Exit 1 fails the step if high/critical findings

GitLab CI

security-scan:
  script:
    - oculum scan --fail-on high
  allow_failure: false  # Block pipeline on failure

Jenkins

sh 'oculum scan --fail-on high'
// Non-zero exit fails the stage

Category-Based Failing

Fail only on specific categories:

# Only fail on AI-related issues
oculum scan --fail-on-categories "ai-*"

# Only fail on secrets
oculum scan --fail-on-categories "secrets-*"

# Multiple categories
oculum scan --fail-on-categories "ai-*,secrets-*"

Available Categories

  • ai-* — All AI security detectors
  • secrets-* — Secret detection
  • owasp-* — Traditional web vulnerabilities
  • config-* — Configuration issues

Combining with --new

Only fail on new findings (not in baseline):

# Fail on new high/critical issues
oculum scan --new --fail-on high

This is useful for PRs where you want to:

  • Allow existing security debt
  • Block new issues from being introduced

Handling Exit Codes in Scripts

Bash

#!/bin/bash

oculum scan --fail-on high
exit_code=$?

if [ $exit_code -eq 0 ]; then
  echo "No blocking issues found"
elif [ $exit_code -eq 1 ]; then
  echo "Security issues found"
  exit 1
elif [ $exit_code -eq 2 ]; then
  echo "Configuration error"
  exit 2
elif [ $exit_code -eq 3 ]; then
  echo "Authentication required"
  exit 3
fi

Node.js

const { execSync } = require('child_process');

try {
  execSync('oculum scan --fail-on high', { stdio: 'inherit' });
  console.log('Scan passed');
} catch (error) {
  if (error.status === 1) {
    console.error('Security issues found');
  } else if (error.status === 2) {
    console.error('Configuration error');
  }
  process.exit(error.status);
}

Common Patterns

PR Checks (Strict)

# Fail on any high/critical issue
oculum scan --fail-on high

PR Checks (Permissive)

# Only fail on critical
oculum scan --fail-on critical

PR Checks (New Only)

# Only fail on new issues
oculum scan --new --fail-on high

Main Branch

# Thorough scan, fail on high
oculum scan --depth verified --fail-on high

Audit Mode

# Scan without failing, report only
oculum scan --fail-on none --format json --output audit.json

Suppressed Findings

Suppressed findings don't affect the exit code. If all findings at the threshold are suppressed, exit code is 0.

# Has one critical finding, but it's suppressed
oculum scan --fail-on critical
# Exit code: 0

JSON Output with Exit Codes

Get detailed information with JSON while still using exit codes:

oculum scan --format json --output results.json --fail-on high
# Exit code reflects findings
# Full details in results.json

Check hasBlockingIssues in JSON:

{
  "hasBlockingIssues": true,
  "summary": {
    "critical": 1,
    "high": 2
  }
}

Debugging Exit Codes

If unexpected exit codes:

# Verbose output shows what's happening
oculum scan --fail-on high --verbose

# Check what's being counted
oculum scan --format json | jq '.summary'

Related