ScanResult JSON Schema
Overview
The ScanResult object is the primary output structure from VulnParse-Pin. It contains all vulnerability data parsed and enriched from your scanner reports. This document describes the complete schema structure so you can understand and validate the JSON output.
Schema Location
The official JSON Schema for ScanResult is included with VulnParse-Pin:
vulnparse_pin/core/schemas/scanResult.schema.json
This schema conforms to JSON Schema Draft 2020-12 and is used for runtime validation of all ScanResult objects.
Top-Level Structure
Every ScanResult contains three required properties:
{
"scan_metadata": { ... },
"assets": [ ... ],
"derived": { ... }
}
ScanMetaData
Contains information about the source scan.
| Field | Type | Required | Description |
|---|---|---|---|
source |
string | ✓ | Vulnerability scanner source (e.g., "Nessus", "OpenVAS") |
scan_date |
string/number | ✓ | ISO 8601 timestamp or Unix timestamp of scan execution |
asset_count |
integer | ✓ | Total number of scanned assets (≥ 0) |
vulnerability_count |
integer | ✓ | Total vulnerabilities detected (≥ 0) |
parsed_at |
string/null | - | ISO 8601 timestamp when VulnParse-Pin parsed this report |
source_file |
string/null | - | Original scanner report file path |
scan_name |
string/null | - | Human-readable scan name/identifier |
Example
{
"source": "Nessus",
"scan_date": "2026-03-28T14:32:00Z",
"asset_count": 42,
"vulnerability_count": 1205,
"parsed_at": "2026-03-28T14:35:12.123456Z",
"source_file": "/scans/network_perimeter_v1.nessus",
"scan_name": "Q1 2026 Network Perimeter"
}
Assets
An array of scanned systems or network devices.
Asset Object
| Field | Type | Required | Description |
|---|---|---|---|
hostname |
string | ✓ | FQDN or hostname (non-empty) |
ip_address |
string | ✓ | IPv4 or IPv6 address |
asset_id |
string/null | - | Auto-generated unique identifier (hash of hostname + IP) |
criticality |
string/null | - | Asset criticality level: "Extreme" (3+ Critical findings), "High" (1+ Critical or 2+ High), "Medium" (1 High), "Low" (none). Used in TopN exposure inference rules (as lowercase: extreme, high, medium, low) |
avg_risk_score |
number/null | - | Average risk score across all findings (0-10 scale) |
os |
string/null | - | Detected operating system |
shodan_data |
object/null | - | Additional intelligence from Shodan (if enrichment enabled) |
findings |
array | ✓ | Array of vulnerabilities on this asset |
Example
{
"asset_id": "A-db8f3e5d",
"hostname": "web-prod-01.example.com",
"ip_address": "203.0.113.42",
"criticality": "Extreme",
"avg_risk_score": 7.8,
"os": "Linux 5.15.0-1234",
"findings": [...]
}
Findings
Individual vulnerability records. Each asset contains an array of findings.
Finding Object
| Field | Type | Required | Description |
|---|---|---|---|
finding_id |
string | ✓ | Unique ID (hash of asset, scanner_sig, protocol, port, title) |
vuln_id |
string | ✓ | Scanner plugin/OID identifier |
title |
string | ✓ | Vulnerability name (non-empty) |
description |
string | ✓ | Detailed vulnerability description |
severity |
string | ✓ | Scanner severity (e.g., "Critical", "High", "Medium", "Low", "Info") |
cves |
array | ✓ | Associated CVE IDs (array of strings) |
asset_id |
string/null | - | Reference to parent asset |
Scoring Fields
| Field | Type | Description |
|---|---|---|
cvss_score |
number/null | CVSS score (0-10) |
cvss_vector |
string/null | CVSS vector string (e.g., "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") |
raw_risk_score |
number/null | Initial score from scoring pass (before adjustments) |
risk_score |
number/null | Final adjusted risk score after TopN prioritization |
risk_band |
string/null | Risk classification ("Critical", "High", "Medium", "Low", "Minimal") |
Intelligence Fields
| Field | Type | Description |
|---|---|---|
epss_score |
number/null | EPSS score from CISA/NVD (0-1) |
cisa_kev |
boolean/null | Whether on CISA Known Exploited Vulnerabilities list |
exploit_available |
boolean/null | Public exploit exists |
exploit_references |
array/null | References to public exploits |
enriched |
boolean/null | Whether enrichment was applied |
enrichment_source_cve |
string/null | CVE from which enrichment data was sourced |
Scanner Details
| Field | Type | Description |
|---|---|---|
detection_plugin |
string/null | Scanner detection method |
plugin_output |
string/null | Raw scanner plugin output |
plugin_evidence |
array/null | Evidence items from scanner |
affected_port |
integer/null | Network port (0-65535) |
protocol |
string/null | Protocol (tcp, udp, icmp, etc.) |
Remediation Fields
| Field | Type | Description |
|---|---|---|
solution |
string/null | Patching/remediation guidance |
references |
array/null | External references (URLs, documentation) |
triage_priority |
string/null | Priority from TopN triage pass |
Example
{
"finding_id": "F-a7c2b9e1",
"vuln_id": "95054",
"asset_id": "A-db8f3e5d",
"title": "Remote Code Execution in OpenSSH",
"description": "A remote attacker can execute arbitrary code...",
"severity": "Critical",
"cves": ["CVE-2024-6387"],
"cvss_score": 9.8,
"cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"epss_score": 0.76,
"cisa_kev": true,
"exploit_available": true,
"affected_port": 22,
"protocol": "tcp",
"raw_risk_score": 8.5,
"risk_score": 9.2,
"risk_band": "Critical",
"triage_priority": "Critical",
"enriched": true,
"enrichment_source_cve": "CVE-2024-6387",
"solution": "Upgrade OpenSSH to version 9.8 or later",
"references": [
"https://nvd.nist.gov/vuln/detail/CVE-2024-6387"
]
}
Derived Context
Container for results from post-parsing passes (Scoring, TopN, etc.).
| Field | Type | Description |
|---|---|---|
passes |
object | Dictionary mapping pass names to their results |
Schema Validation
Using jsonschema Library
from vulnparse_pin.utils.schema_validate import validate_scan_result_schema
# After parsing/enriching your scan
validate_scan_result_schema(my_scan_result)
# Raises ValueError if validation fails
Validating JSON Files
To validate a VulnParse-Pin JSON output file against the schema:
# Using Python
python -m jsonschema \
-i output.json \
-s vulnparse_pin/core/schemas/scanResult.schema.json
Custom Validation
You can also use the schema directly with your preferred JSON Schema validator:
from jsonschema import Draft202012Validator
import json
with open('output.json') as f:
data = json.load(f)
with open('vulnparse_pin/core/schemas/scanResult.schema.json') as f:
schema = json.load(f)
validator = Draft202012Validator(schema)
for error in validator.iter_errors(data):
print(f"Validation error: {error.message}")
Common Patterns
Filter by Risk Band
critical_findings = [
f for asset in scan.assets
for f in asset.findings
if f.risk_band == "Critical"
]
Find CISA KEV Vulnerabilities
kev_findings = [
f for asset in scan.assets
for f in asset.findings
if f.cisa_kev
]
Group by Severity
from collections import defaultdict
by_severity = defaultdict(list)
for asset in scan.assets:
for finding in asset.findings:
by_severity[finding.severity].append(finding)
Export to CSV
See the --output-csv flag in the CLI documentation for direct CSV export with schema-aware field handling.
Notes
- asset_id: Auto-generated as a hash of the hostname and IP address. Same asset across multiple scans will have the same ID.
- finding_id: Uniquely identifies a vulnerability on a specific asset. Deduplication by finding_id prevents double-counting the same vulnerability instance.
- Times: Can be ISO 8601 strings or Unix timestamps; both are handled transparently.
- Nullability: Fields marked as nullable (type
"string/null") will benullif data is unavailable. - Risk Scores: After enrichment and the Scoring pass, findings will have raw/risk scores. Before these passes, these fields may be
null.