← Back to Docs

Output Formats

vigil supports 4 output formats to fit different workflows: interactive terminal, automation, CI dashboards, and security platforms.

Format selection

# Formato human (default)
vigil scan src/

# Formato JSON
vigil scan src/ -f json

# Formato JUnit XML
vigil scan src/ -f junit

# Formato SARIF 2.1.0
vigil scan src/ -f sarif

Human

Default format, optimized for terminal reading. Includes ANSI colors, severity icons, and a final summary.

Severity icons

IconSeverityColor
XCRITICALRed
XHIGHRed
!MEDIUMYellow
~LOWBlue
iINFOCyan

Example output

  vigil v0.4.0 — scanned 42 files

  X CRITICAL  DEP-001  requirements.txt:14
    Package 'python-jwt-utils' does not exist in pypi.
    This is likely a hallucinated dependency from an AI agent.
    -> Suggestion: Remove 'python-jwt-utils' and find the correct package name.

  X HIGH      AUTH-005  src/main.py:8
    CORS configured with '*' allowing requests from any origin.
    -> Suggestion: Restrict CORS to specific trusted origins.

  -------------------------------------------------
  42 files scanned in 1.2s
  2 findings: 1 critical, 1 high
  analyzers: dependency, auth

Clean output (no findings)

  vigil v0.4.0 — scanned 42 files

  No findings.

  -------------------------------------------------
  42 files scanned in 0.5s
  0 findings

Colors

  • Colors are automatically enabled when stdout is a TTY (interactive terminal).
  • If stdout is a pipe or a file, colors are automatically disabled.
  • You can control this with the output.colors config option.

Behavior with --output

When using --output with the human format, the report is written to both the file and the terminal. This allows saving the report without losing immediate feedback.


JSON

Structured format for programmatic processing, integration with other tools, or storage.

Structure

{
  "version": "0.4.0",
  "files_scanned": 42,
  "duration_seconds": 1.2,
  "findings": [
    {
      "rule_id": "DEP-001",
      "category": "dependency",
      "severity": "critical",
      "message": "Package 'python-jwt-utils' does not exist in pypi.",
      "location": {
        "file": "requirements.txt",
        "line": 14,
        "column": null,
        "end_line": null,
        "snippet": "python-jwt-utils==1.0.0"
      },
      "suggestion": "Remove 'python-jwt-utils' and find the correct package name.",
      "metadata": {}
    }
  ],
  "summary": {
    "total": 2,
    "by_severity": {
      "critical": 1,
      "high": 1,
      "medium": 0,
      "low": 0,
      "info": 0
    },
    "by_category": {
      "dependency": 1,
      "auth": 1
    },
    "by_rule": {
      "DEP-001": 1,
      "AUTH-005": 1
    }
  }
}

Fields

FieldTypeDescription
versionstringvigil version
files_scannedintNumber of files analyzed
duration_secondsfloatScan duration in seconds
findingsarrayList of findings (empty if no issues)
summaryobjectSummary with counts by severity, category, and rule

Each finding

FieldTypeDescription
rule_idstringUnique rule ID (e.g. DEP-001)
categorystringCategory: dependency, auth, secrets, test-quality
severitystringcritical, high, medium, low, info
messagestringProblem description
locationobjectLocation in the code
suggestionstring|nullFix suggestion
metadataobjectAdditional rule-specific data

Typical usage

# Generar y procesar con jq
vigil scan src/ -f json | jq '.findings[] | select(.severity == "critical")'

# Guardar a archivo
vigil scan src/ -f json -o report.json

# Integrar con scripts
vigil scan src/ -f json | python process_results.py

JUnit XML

Format compatible with CI/CD dashboards (Jenkins, GitLab CI, Azure DevOps, etc.). Each finding is represented as a failed test case.

Structure

<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="vigil" tests="2" failures="2" errors="0" time="1.2">
    <testcase name="DEP-001" classname="dependency.requirements.txt">
      <failure type="error" message="Package 'python-jwt-utils' does not exist in pypi.">
Severity: critical
File: requirements.txt:14
Suggestion: Remove 'python-jwt-utils' and find the correct package name.
      </failure>
    </testcase>
    <testcase name="AUTH-005" classname="auth.src/main.py">
      <failure type="warning" message="CORS configured with '*' allowing requests from any origin.">
Severity: high
File: src/main.py:8
Suggestion: Restrict CORS to specific trusted origins.
      </failure>
    </testcase>
  </testsuite>
</testsuites>

Severity mapping

vigil severityJUnit failure type
CRITICALerror
HIGHerror
MEDIUMwarning
LOWwarning
INFOwarning

Typical usage

# Generar reporte JUnit
vigil scan src/ -f junit -o report.xml

In GitLab CI, the report can be published as a test artifact:

vigil:
  script:
    - vigil scan src/ -f junit -o report.xml
  artifacts:
    reports:
      junit: report.xml

In Jenkins, it can be used with the JUnit plugin:

stage('Security Scan') {
    steps {
        sh 'vigil scan src/ -f junit -o report.xml'
    }
    post {
        always {
            junit 'report.xml'
        }
    }
}

SARIF 2.1.0

Static Analysis Results Interchange Format. Industry-standard format for static analysis results. Compatible with GitHub Code Scanning, VS Code SARIF Viewer, and other platforms.

Structure

{
  "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "vigil",
          "version": "0.4.0",
          "informationUri": "https://github.com/org/vigil",
          "rules": [
            {
              "id": "DEP-001",
              "name": "HallucinatedDependency",
              "shortDescription": {
                "text": "Package declared as dependency does not exist in the public registry."
              },
              "properties": {
                "cwe": "CWE-829"
              }
            }
          ]
        }
      },
      "results": [
        {
          "ruleId": "DEP-001",
          "level": "error",
          "message": {
            "text": "Package 'python-jwt-utils' does not exist in pypi."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "requirements.txt"
                },
                "region": {
                  "startLine": 14
                }
              }
            }
          ],
          "fixes": [
            {
              "description": {
                "text": "Remove 'python-jwt-utils' and find the correct package name."
              }
            }
          ]
        }
      ]
    }
  ]
}

Severity mapping

vigil severitySARIF level
CRITICALerror
HIGHerror
MEDIUMwarning
LOWnote
INFOnote

SARIF elements

  • tool.driver.rules: Only includes rules that generated findings (not all 26 rules).
  • results: Each finding as an individual result with physical location.
  • fixes: If the finding has a suggestion, it is included as fixes[].description.
  • properties.cwe: If the rule has a CWE reference, it is included in the properties.

Usage with GitHub Code Scanning

# Generar SARIF
vigil scan src/ -f sarif -o vigil.sarif

In GitHub Actions:

- name: Run vigil
  run: vigil scan src/ -f sarif -o vigil.sarif
  continue-on-error: true

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: vigil.sarif

The findings appear directly in the repository’s “Security” tab and as annotations on pull requests.


Format comparison

FeatureHumanJSONJUnitSARIF
Terminal readingYesNoNoNo
Programmatic processingNoYesPartialYes
ColorsYes (TTY)NoNoNo
GitHub Code ScanningNoNoNoYes
CI dashboardsNoNoYesYes
Fix suggestionsYesYesYesYes
CWE referencesNoNoNoYes
Rule definitionsNoNoNoYes

Combining formats

It is possible to generate multiple reports in a single run using scripts:

# Generar JSON y SARIF en una pasada
vigil scan src/ -f json -o report.json
vigil scan src/ -f sarif -o vigil.sarif
vigil scan src/ -f junit -o report.xml

Since vigil uses a cache for registry responses, successive runs are fast because they don’t repeat HTTP requests.