Files
SlipItIn/.github/skills/security-specialist/scripts/finalize.py
Tim Krampitz 01046b01e4 Neue Skills, Referenzen & OpenWiki-Doku integriert
Umfangreiche Erweiterung der Skill-Bibliothek: Neue Skills für Humanisierung (Englisch/PT-BR), Design-Validierung, AI-SEO und Coolify-Deployment inkl. Regelwerke, Presets, Pattern-Referenzen, Testfälle und Automatisierungsskripte. Zusätzliche Skills für Revenue-Centric Design, Pier Cloud, OKF, Lebenslauf- und LinkedIn-Optimierung sowie zahlreiche Referenzdateien, Checklisten und YAML/JSON/Markdown-Templates. Einführung einer vollständigen OpenWiki-Dokumentation mit Architektur-, Domain- und Workflow-Beschreibungen, zentralem Index und automatisierten Updates. Modularer Aufbau, restriktive Lizenzen und umfassende Qualitäts- und Evaluationsmechanismen für alle neuen Inhalte.
2026-07-26 14:00:58 +02:00

135 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""Seal a security scan and generate final reports."""
import argparse
import hashlib
import json
import sqlite3
from datetime import datetime, timezone
from pathlib import Path
def _connect(scan_dir: Path) -> sqlite3.Connection:
db_path = scan_dir / "scan.db"
if not db_path.exists():
raise SystemExit(f"Database not found: {db_path}")
conn = sqlite3.connect(str(db_path))
conn.row_factory = sqlite3.Row
return conn
def _get_active_scan(conn: sqlite3.Connection) -> dict:
row = conn.execute("SELECT * FROM scans WHERE status = 'active' ORDER BY started_at DESC LIMIT 1").fetchone()
if not row:
raise SystemExit("No active scan found to seal.")
return dict(row)
def _seal(conn: sqlite3.Connection, scan_id: str) -> None:
now = datetime.now(timezone.utc).isoformat()
conn.execute("UPDATE scans SET sealed_at = ?, status = 'sealed' WHERE id = ?", (now, scan_id))
conn.commit()
def _export_findings(conn: sqlite3.Connection, scan_id: str, scan_dir: Path) -> list[dict]:
rows = conn.execute("SELECT * FROM findings WHERE scan_id = ? ORDER BY severity, file_path", (scan_id,)).fetchall()
findings = [dict(r) for r in rows]
(scan_dir / "findings.json").write_text(json.dumps(findings, indent=2))
return findings
def _severity_order(sev: str) -> int:
return {"critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4}.get(sev, 5)
def _generate_report(findings: list[dict], scan: dict, scan_dir: Path) -> None:
counts: dict[str, int] = {}
for f in findings:
counts[f["severity"]] = counts.get(f["severity"], 0) + 1
total = len(findings)
lines = ["# Security Scan Report\n"]
lines.append(f"**Repository:** `{scan['repo_path']}` ")
lines.append(f"**Scan ID:** `{scan['id']}` ")
lines.append(f"**Started:** {scan['started_at']} ")
lines.append(f"**Sealed:** {scan['sealed_at']}\n")
# Executive summary
lines.append("## Executive Summary\n")
if total == 0:
lines.append("No findings were recorded during this scan.\n")
else:
lines.append(f"This scan identified **{total} finding(s)** across the repository:\n")
for sev in sorted(counts, key=_severity_order):
emoji = {"critical": "🔴", "high": "🟠", "medium": "🟡", "low": "🔵", "info": ""}.get(sev, "·")
lines.append(f"- {emoji} **{sev.capitalize()}:** {counts[sev]}")
lines.append("")
if counts.get("critical", 0) > 0:
lines.append("⚠️ Critical findings require immediate attention before deployment.\n")
# Findings table
if findings:
lines.append("## Findings Overview\n")
lines.append("| # | Severity | Category | File | Status | Title |")
lines.append("|---|----------|----------|------|--------|-------|")
for i, f in enumerate(sorted(findings, key=lambda x: _severity_order(x["severity"])), 1):
loc = f"`{f['file_path']}:{f['line_number']}`" if f["file_path"] else ""
lines.append(f"| {i} | {f['severity']} | {f['category']} | {loc} | {f['status']} | {f['title']} |")
lines.append("")
# Detailed findings
if findings:
lines.append("## Detailed Findings\n")
for i, f in enumerate(sorted(findings, key=lambda x: _severity_order(x["severity"])), 1):
lines.append(f"### {i}. {f['title']}\n")
lines.append(f"- **Severity:** {f['severity']}")
lines.append(f"- **Category:** {f['category']}")
lines.append(f"- **Status:** {f['status']}")
if f["file_path"]:
lines.append(f"- **Location:** `{f['file_path']}:{f['line_number']}`")
if f["tracking_url"]:
lines.append(f"- **Tracking:** {f['tracking_url']}")
lines.append(f"\n{f['description']}\n")
if f["evidence"]:
lines.append("**Evidence:**\n")
lines.append(f"```\n{f['evidence']}\n```\n")
(scan_dir / "report.md").write_text("\n".join(lines))
def _write_integrity(scan_dir: Path) -> str:
content = (scan_dir / "findings.json").read_bytes()
digest = hashlib.sha256(content).hexdigest()
(scan_dir / "integrity.sha256").write_text(f"{digest} findings.json\n")
return digest
def main() -> None:
parser = argparse.ArgumentParser(description="Seal scan and generate reports")
parser.add_argument("--scan-dir", required=True, help="Path to .security/ directory")
args = parser.parse_args()
scan_dir = Path(args.scan_dir).resolve()
conn = _connect(scan_dir)
scan = _get_active_scan(conn)
_seal(conn, scan["id"])
scan["sealed_at"] = datetime.now(timezone.utc).isoformat()
findings = _export_findings(conn, scan["id"], scan_dir)
_generate_report(findings, scan, scan_dir)
digest = _write_integrity(scan_dir)
conn.close()
total = len(findings)
counts = {}
for f in findings:
counts[f["severity"]] = counts.get(f["severity"], 0) + 1
print(f"Scan sealed: {scan['id']}")
print(f"Findings: {total} total — " + ", ".join(f"{k}: {v}" for k, v in sorted(counts.items(), key=lambda x: _severity_order(x[0]))))
print(f"Reports: {scan_dir / 'report.md'}, {scan_dir / 'findings.json'}")
print(f"Integrity: {digest}")
if __name__ == "__main__":
main()