Security Audit

beacon

Scans business websites for security weaknesses and matches every finding to a documented breach where the same vulnerability was exploited.

TypeScriptNode.jsTLSDNSOWASPSPF/DKIM/DMARCCT LogsHTML Analysis
beacon
$
01 / Engineering

What it checks

7 scanners, 100 breach precedents, plain-English risk translation.

02 / The Code

From the source

Precedent matching, TLS inspection, and the grading algorithm. Copied from the repo.

Breach Precedent Matching
Maps scanner finding IDs to breach categories, returns the most impactful real-world example.
/** Map from scanner findings to breach database categories. */
const FINDING_TO_BREACH: Record<string, string[]> = {
  "headers-no-csp": ["xss", "supply-chain"],
  "dns-no-dmarc":   ["email-spoofing"],
  "dns-no-spf":     ["email-spoofing"],
  "paths-env":      ["exposed-files"],
  "paths-git-head": ["exposed-files"],
  "third-party-hotjar": ["session-recording"],
  "forms-whatsapp-communication": ["whatsapp-consumer-tools"],
  // ... 40+ mappings across 20 categories
};

/** Pick the most impactful precedent from matching breaches. */
function pickPrecedent(categories: string[]): BreachPrecedent | undefined {
  const matches = BREACHES
    .filter(b => categories.includes(b.category))
    .sort((a, b) => (b.impact?.length ?? 0) - (a.impact?.length ?? 0));
  return matches[0];
}
TLS Inspection
Direct socket connection to inspect protocol, cipher, and certificate without external dependencies.
function inspectTls(host: string): Promise<TlsInfo | null> {
  return new Promise((resolve) => {
    const sock = tls.connect(443, host, {
      servername: host, // SNI — required for shared hosting
      timeout: 8000
    }, () => {
      resolve({
        protocol: sock.getProtocol() ?? "unknown",
        cipher: sock.getCipher()?.standardName ?? "unknown",
        authorized: sock.authorized,
        authError: sock.authorizationError
          ? String(sock.authorizationError) : undefined,
        certExpiry: sock.getPeerCertificate()?.valid_to
          ? new Date(sock.getPeerCertificate().valid_to) : undefined,
      });
      sock.end();
    });
    sock.on("error", () => resolve(null));
  });
}
Grade Computation
Starts at 100, deducts by severity. Simple, transparent, reproducible.
const WEIGHTS: Record<Severity, number> = {
  critical: 40,
  high:     20,
  medium:    8,
  low:       2,
  info:      0,
};

export function computeGrade(findings: Finding[]): Grade {
  let score = 100;
  for (const f of findings) score -= WEIGHTS[f.severity];
  if (score >= 90) return "A";
  if (score >= 75) return "B";
  if (score >= 55) return "C";
  if (score >= 35) return "D";
  return "F";
}
0
breach precedents
0
tests passing
0
scanners
0
vulnerability categories