25 lines
1.1 KiB
Python
25 lines
1.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Fail closed on invalid CSAF JSON and incomplete synchronization."""
|
|
import json
|
|
from pathlib import Path
|
|
import re
|
|
import sys
|
|
|
|
CVE=re.compile(r'^CVE-\d{4}-\d{4,}\.json$',re.I)
|
|
def validate(root=Path('data/vex'), state=Path('state/sync.json')):
|
|
if not state.exists():raise ValueError('Missing completed sync state')
|
|
metadata=json.loads(state.read_text())
|
|
files=sorted(root.rglob('*.json'))
|
|
if not files or len(files)!=metadata['record_count']:
|
|
raise ValueError(f'Count mismatch: files={len(files)} expected={metadata["record_count"]}')
|
|
for path in files:
|
|
if not CVE.match(path.name):raise ValueError(f'Invalid filename: {path}')
|
|
doc=json.loads(path.read_bytes())
|
|
if not isinstance(doc,dict) or not isinstance(doc.get('document'),dict) or not isinstance(doc.get('vulnerabilities'),list):
|
|
raise ValueError(f'Invalid CSAF VEX: {path}')
|
|
print(f'Validated {len(files)} CSAF VEX documents')
|
|
if __name__=='__main__':
|
|
try:validate()
|
|
except (ValueError,OSError,KeyError,json.JSONDecodeError) as ex:
|
|
print(f'VALIDATION FAILED: {ex}',file=sys.stderr);sys.exit(1)
|