"""Print audit counts without exposing secret matches or source snippets.""" import json import os from pathlib import Path def summarize(reports): incomplete = False def read(name): nonlocal incomplete try: report = json.loads((reports / name).read_text()) if not isinstance(report, dict) or report.get('error'): raise ValueError('Invalid audit report') return report except (OSError, ValueError): print(f'{name}: report missing, invalid or scanner error; inspect the audit step.') incomplete = True return {} for project in ('root', 'backend', 'frontend', 'log-exporter'): report = read(f'npm-audit-{project}.json') counts = report.get('metadata', {}).get('vulnerabilities', {}) if 'high' not in counts or 'critical' not in counts: print(f'{project}: dependency audit unavailable.') incomplete = True continue print(f'{project}: {counts["high"]} high, {counts["critical"]} critical vulnerabilities.') report = read('source-security.json') if 'Results' not in report: print('Source audit unavailable.') incomplete = True else: results = report['Results'] or [] secrets = sum(len(result.get('Secrets') or []) for result in results) misconfigs = sum(len(result.get('Misconfigurations') or []) for result in results) print(f'Source: {secrets} secret findings, {misconfigs} infrastructure findings.') print('Download the security-reports artifact for details. The audit step determines pass/fail.') return int(incomplete) if __name__ == '__main__': raise SystemExit(summarize(Path(os.environ['RUNNER_TEMP']) / 'security-reports'))