Output Formats
vigil supports 4 output formats to fit different workflows: interactive terminal, automation, CI dashboards, and security platforms.
Format selection
# Human format (default)
vigil scan src/
# JSON format
vigil scan src/ -f json
# JUnit XML format
vigil scan src/ -f junit
# SARIF 2.1.0 format
vigil scan src/ -f sarif
Human
Default format, optimized for reading in the terminal. Includes ANSI colors, severity icons, and a final summary.
Severity icons
| Icon | Severity | Color |
|---|---|---|
X | CRITICAL | Red |
X | HIGH | Red |
! | MEDIUM | Yellow |
~ | LOW | Blue |
i | INFO | Cyan |
Output example
vigil v0.2.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.2.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.colorsconfig option.
Behavior with --output
When --output is used with the human format, the report is written to both the file and the terminal. This allows you to save the report without losing immediate feedback.
JSON
Structured format for programmatic processing, integration with other tools, or storage.
Structure
{
"version": "0.2.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
| Field | Type | Description |
|---|---|---|
version | string | vigil version |
files_scanned | int | Number of files analyzed |
duration_seconds | float | Scan duration in seconds |
findings | array | List of findings (empty if no issues) |
summary | object | Summary with counts by severity, category, and rule |
Each finding
| Field | Type | Description |
|---|---|---|
rule_id | string | Unique rule ID (e.g., DEP-001) |
category | string | Category: dependency, auth, secrets, test-quality |
severity | string | critical, high, medium, low, info |
message | string | Description of the issue |
location | object | Location in the code |
suggestion | string|null | Fix suggestion |
metadata | object | Additional data specific to the rule |
Typical usage
# Generate and process with jq
vigil scan src/ -f json | jq '.findings[] | select(.severity == "critical")'
# Save to file
vigil scan src/ -f json -o report.json
# Integrate with 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 severity | JUnit failure type |
|---|---|
| CRITICAL | error |
| HIGH | error |
| MEDIUM | warning |
| LOW | warning |
| INFO | warning |
Typical usage
# Generate JUnit report
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.2.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 severity | SARIF level |
|---|---|
| CRITICAL | error |
| HIGH | error |
| MEDIUM | warning |
| LOW | note |
| INFO | note |
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 asfixes[].description.properties.cwe: If the rule has a CWE reference, it is included in the properties.
Usage with GitHub Code Scanning
# Generate 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
Findings appear directly in the repository’s “Security” tab and as annotations on pull requests.
Format comparison
| Feature | Human | JSON | JUnit | SARIF |
|---|---|---|---|---|
| Terminal reading | Yes | No | No | No |
| Programmatic processing | No | Yes | Partial | Yes |
| Colors | Yes (TTY) | No | No | No |
| GitHub Code Scanning | No | No | No | Yes |
| CI dashboards | No | No | Yes | Yes |
| Fix suggestions | Yes | Yes | Yes | Yes |
| CWE references | No | No | No | Yes |
| Rule definitions | No | No | No | Yes |
Combining formats
It is possible to generate multiple reports in a single run using scripts:
# Generate JSON and SARIF in one pass
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 caches registry responses, successive runs are fast because HTTP requests are not repeated.