Security Report Automator
Submit a domain, receive a professional penetration testing report in your inbox — fully automated, no manual analysis required. Under 90 seconds, end to end.
A basic security recon report takes a skilled analyst 3–6 hours — querying cert logs, running port scans, checking CVE databases, grading SSL configs, and writing it up. Most small businesses never get one because it's too expensive.
A fully automated passive recon pipeline. Domain in → branded PDF in under 3 minutes. Six APIs run in parallel, findings are structured and scored, Groq AI writes the report in a pentester's voice, WeasyPrint renders it, Resend delivers it.
The pipeline, end-to-end.
Eight stages. One submission. A pentest-grade PDF on the other side.
Submission
User submits domain + email via the branded frontend. FastAPI validates input, creates a Supabase job (status: queued), returns job_id + poll URL in <100ms. A BackgroundTask kicks off the async pipeline.
Parallel Recon
Six API modules fire concurrently — crt.sh, HackerTarget, Shodan, SSL Labs, NVD, HIBP. Each is fault-tolerant: one failure never blocks the others.
Aggregation + Score
Findings merged, deduplicated, structured into a typed AggregatedFindings object. Deterministic risk score (0–100) calculated from subdomain count, exposed services, CVE severity (CVSS-weighted), SSL grade, cert expiry, and breach exposure.
AI Report Writing
Structured findings JSON passed to Groq llama-3.3-70b-versatile (max 8,192 tokens) with a senior pentester system prompt. Forces a 6-section output: Exec Summary, Methodology, Risk Table, Detailed Findings, Recommendations, Technical Appendix.
PDF Rendering
Markdown → HTML via python-markdown → Jinja2 template → WeasyPrint PDF. Dark cyber design: Space Grotesk, JetBrains Mono, severity badges, CONFIDENTIAL headers, branded cover with risk score.
Email Delivery
Resend sends the PDF as a base64 attachment from noreply@kedrichai.xyz. Subject includes risk level + score. HTML body with color-coded risk badge. Non-blocking — job completes even if email fails.
Job Completion
Supabase record updated to completed with pdf_path, pdf_url, report_markdown, findings_json, email_sent. Status page polls every 8s and shows the live pipeline with per-stage indicators.
Slack Notification
n8n receives a webhook on submission, polls /jobs/{id} every 10s via Wait → HTTP → IF loop, then posts to #make-testing on completion — domain, risk score, subdomain count, CVE count, PDF link.
Domain in, report out.
The full pipeline in real time — from submission to the finished PDF landing in the inbox.
What lands in your inbox.
The PDF isn't a template fill-in. It's 11 structured sections written by the AI in a senior pentester's voice — backed by real evidence.
- 01Cover Page — domain, reference, date, classification, risk score, scan stats
- 02Executive Summary — 3–4 paragraphs for non-technical readers
- 03Assessment Scope and Methodology — what was scanned, how, limitations
- 04Risk Summary Table — all findings ranked by severity
- 05Detailed Findings — Description / Evidence / Business Impact / Remediation
- 06Priority Recommendations — every fix, prioritized
- 07Technical Appendix A — complete subdomain list
- 08Technical Appendix B — exposed services table (IP / Port / Product / Version)
- 09Technical Appendix C — CVE reference table (CVSS / Severity / Description)
- 10Technical Appendix D — SSL/TLS technical details
- 11Disclaimer — passive recon only, confidential, authorized recipient
Exposed SSH Service on Port 22
SSL Certificate Expiring in 12 Days
Scan a domain you own.
Submit a domain + email. In 45–90 seconds you'll get a real PDF report delivered to your inbox. Only scan domains you own or have authorization to test — every scan is logged.
The trade-offs, owned.
Five calls that shaped the system more than the spec did.
Built with an OpenAI-compatible SDK pattern from day one — Groq, Anthropic Claude, and OpenAI GPT-4o all swap via a single AI_PROVIDER env var, no code changes. Groq Llama 3.3 70B runs in production (free tier, 100k tokens/day, no credit card). Claude or GPT-4o can take over for higher-stakes runs in seconds — clients prefer the flexibility over vendor lock-in.
ReportLab makes you build the PDF in Python — paragraph here, table there. WeasyPrint takes HTML/CSS (which I already know) and renders to PDF. Matched the portfolio design system in hours, not days. Trade-off: requires Pango/Cairo/GLib system libs → custom Dockerfile on Railway. Worth it.
Tasks are created concurrently but awaited sequentially. Each module handles its own exception without one failure cancelling others. gather(return_exceptions=True) would work but needs unwrapping — sequential await is cleaner for 5–6 tasks.
A formula-based score (subdomain count + service exposure + CVE severity + SSL grade) is reproducible, auditable, and explainable. "Your score went from 30 to 55 because Shodan found an exposed FTP service running vsftpd 2.3.4" is a sentence you can actually say. A black-box model score isn't.
All findings are validated through Pydantic models before being serialized to JSON for the AI. The AI never receives malformed data — meaning it can't invent a CVE ID that wasn't in the NVD response, because the CVE list is finite and pre-validated. Garbage in, garbage out. Pydantic stops the garbage.
Things worth pointing out.
Every recon source is passive: certificate logs, public DNS, Shodan's already-crawled index, SSL Labs' public API. Zero packets are sent to the target domain. This legal boundary is stated in the PDF disclaimer, the email footer, and the frontend — and the system is architected around it, not retrofitted to claim it.
The AI system prompt doesn't just set tone — it enforces structure. Exact section headings, exact column names, exact severity labels (CRITICAL/HIGH/MEDIUM/LOW/INFORMATIONAL), no placeholders allowed. The output is consistently parseable because the prompt treats the AI like a template engine with judgment, not a creative writer.
n8n isn't in the user-facing flow — it's the operator's nervous system. Monitors every job, catches failures, pings Slack on completion. Cleanly separates concerns: FastAPI handles the work, n8n handles observability.
What broke. How I fixed it.
Needs Pango, Cairo, GLib — Linux system libraries that don't exist on Windows or Railway's default image. Debugged 'gobject-2.0-0 not found' locally before accepting that PDF testing had to happen on the deployed container. Dockerfile installs every required lib explicitly. libgdk-pixbuf2.0-0 was renamed to libgdk-pixbuf-xlib-2.0-0 in Debian trixie — caught that on first Railway build.
WeasyPrint 62.3 shipped with pydyf 0.10.0. A newer pydyf (0.11+) removed transform() from its parent class, breaking WeasyPrint's PDF stream generation with AttributeError: 'super' object has no attribute 'transform'. Fix: pin pydyf==0.10.0 in requirements.txt.
Shodan's free key doesn't support hostname search — returns 403 "Requires membership". The original handler only caught 401, so the pipeline retried 3 times, waited 30 seconds, then failed. Fix: treat both 401 and 403 as graceful skip conditions.
Railway's variable editor made it easy to paste "BASE_URL = https://..." (including the key name) as the value. This propagated into every generated PDF URL as a literal string. Added to the "screenshot before debugging" checklist.
Free tier is 100k tokens/day. A full-scan report uses ~2,700 tokens (1,264 input + 1,544 output). About 37 reports/day before hitting the cap. Fine for portfolio demo; needs paid tier or scan deduplication for production.
Frontend, PDF, ops layer.
Every screen from the production system. Click any to expand.









Each layer, its job.
The numbers.
What I'd do differently.
The current build runs free-tier everything. Here's where I'd invest first.
Save to Supabase Storage or S3. Railway's ephemeral filesystem resets on redeploy and loses all generated reports.
Cache recon findings per domain with a 24-hour TTL. Running crt.sh + Shodan + SSL Labs on google.com 50 times is wasteful and burns rate limits.
FastAPI BackgroundTasks works at low volume but doesn't survive restarts. Celery + Redis would handle retries, priority, and multi-worker scaling.
Current API key is one shared secret. Production needs per-client keys, usage quotas, and a tenant model so one user can't exhaust the Groq quota for everyone.
Automated passive recon can surface false positives. A CRITICAL-rated report probably warrants a human analyst review before delivery to a paying client.
Want a recon pipeline
for your security ops?
Book a free 30-minute call — or copy my email and reach out when you're ready. We'll scope what to automate first.