feat: tool normalizers, Exploit-DB grounding, orchestrator, report, triage, CLI
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""nuclei — template-based exposure/misconfig/CVE checks. Output: ``-jsonl``.
|
||||
|
||||
Gated behind ``--enable-nuclei`` (off by default in V0): it needs network for
|
||||
template fetch and meaningful runtime. Templates cache to a runtime volume.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ..schema import NucleiFinding, Severity
|
||||
from .base import parse_jsonl, run_tool
|
||||
|
||||
BINARY = "nuclei"
|
||||
|
||||
_SEVERITIES = {s.value for s in Severity}
|
||||
|
||||
|
||||
def _severity(value) -> Severity:
|
||||
v = str(value or "").lower().strip()
|
||||
return Severity(v) if v in _SEVERITIES else Severity.UNKNOWN
|
||||
|
||||
|
||||
def normalize(raw: str) -> list[NucleiFinding]:
|
||||
"""Map nuclei -jsonl lines into NucleiFinding records."""
|
||||
out: list[NucleiFinding] = []
|
||||
for rec in parse_jsonl(raw):
|
||||
info = rec.get("info") or {}
|
||||
ref = info.get("reference") or []
|
||||
if isinstance(ref, str):
|
||||
ref = [ref]
|
||||
template_id = rec.get("template-id") or rec.get("templateID") or rec.get("template_id")
|
||||
if not template_id:
|
||||
continue
|
||||
out.append(
|
||||
NucleiFinding(
|
||||
template_id=str(template_id),
|
||||
name=info.get("name"),
|
||||
severity=_severity(info.get("severity")),
|
||||
matched_at=rec.get("matched-at") or rec.get("matched_at"),
|
||||
host=rec.get("host"),
|
||||
reference=[str(r) for r in ref if r],
|
||||
)
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def run(
|
||||
targets: list[str],
|
||||
*,
|
||||
timeout: float = 600.0,
|
||||
rate_limit: int | None = None,
|
||||
templates_dir: str | None = None,
|
||||
) -> tuple[list[NucleiFinding], object]:
|
||||
cmd = [BINARY, "-jsonl", "-silent", "-disable-update-check"]
|
||||
if templates_dir:
|
||||
cmd += ["-update-template-dir", templates_dir, "-templates", templates_dir]
|
||||
if rate_limit:
|
||||
cmd += ["-rate-limit", str(rate_limit)]
|
||||
res = run_tool(cmd, timeout=timeout, input_text="\n".join(targets) + "\n")
|
||||
return normalize(res.stdout), res
|
||||
Reference in New Issue
Block a user