mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 07:11:28 +02:00
Severity alone is close to useless for ordering work: roughly 60% of CVEs
score 7.0 or above. Until now EPSS and KEV came from nuclei's template
metadata, frozen at authoring time, so a finding could never learn that the
world had changed around it.
Two keyless feeds now land nightly and re-score every finding already stored:
EPSS (368k CVEs) and the CISA KEV catalog (1,695). A feed that fails to
download leaves its table untouched, so an install with no egress keeps
ranking. CISA is authoritative for is_kev on anything carrying a CVE.
exploitation.py judges each finding the way interest/ judges hosts, and the
signals that matter cross dimensions no other tool joins:
ransom_path a KEV ransomware CVE on a host whose ports also expose
a service ransomware crews reach for
fresh_exploit a public exploit published after the scan that found it
untestable no scanner template covers this CVE, so no scan can
clear it -- BlueKeep, EternalBlue and HTTP/2 Rapid Reset
all report false here
reachable answering directly, with no CDN or WAF in front
vulnx is an optional ceiling, never the floor: per-CVE exploits and their
links, template coverage, internet-wide population and bounty activity,
cached forever. Measured at 10 requests a minute keyless with no Retry-After,
so the client paces off the remaining header and can only ever be a
background cache-fill.
Alerting is delta-only, on the same rule as new findings: intel_signals is
upserted so created_at is when a finding first earned a signal, and repeated
refreshes alert nothing.
The nightly download is opt-out (instance_settings.threat_intel_auto_sync).
It gates the beat task and the worker warm-up only -- Refresh now always
works, so nobody is stuck with a scheduled outbound request they did not ask
for. Bounty activity renders only under CAP_HACKERONE; the gate is
presentational, so switching mode never loses data.
Every count is a promise: coverage, the query it compiles to, and the rows
its sheet opens were verified equal across all five signals.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwxTAkPFUXPHPvdYT8Rhtm
269 lines
6.7 KiB
Python
269 lines
6.7 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from shared.models.vulnerability import SeverityCount
|
|
|
|
|
|
class TakeoverCandidate(BaseModel):
|
|
name: str
|
|
target_id: uuid.UUID
|
|
cname: str
|
|
provider: str
|
|
last_seen: datetime
|
|
|
|
|
|
class TakeoverSignal(BaseModel):
|
|
count: int
|
|
items: list[TakeoverCandidate] = Field(default_factory=list)
|
|
|
|
|
|
class SpoofableDomain(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
reason: str
|
|
|
|
|
|
class SpoofableSignal(BaseModel):
|
|
count: int
|
|
items: list[SpoofableDomain] = Field(default_factory=list)
|
|
|
|
|
|
class StaleTarget(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
target_type: str
|
|
last_scanned_at: datetime | None = None
|
|
|
|
|
|
class StaleSignal(BaseModel):
|
|
never_scanned: int
|
|
stale: int
|
|
items: list[StaleTarget] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardSignals(BaseModel):
|
|
takeover: TakeoverSignal
|
|
spoofable: SpoofableSignal
|
|
stale: StaleSignal
|
|
|
|
|
|
class DashboardTargetCount(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
scan_id: uuid.UUID
|
|
count: int
|
|
|
|
|
|
class ExpiringTarget(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
expires_at: datetime
|
|
|
|
|
|
class FailedRun(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
scan_id: uuid.UUID
|
|
engine_name: str
|
|
error: str | None = None
|
|
at: datetime
|
|
|
|
|
|
class DashboardSurfaceMetric(BaseModel):
|
|
key: str
|
|
label: str
|
|
value: int = 0
|
|
targets_covered: int = 0
|
|
new_in_window: int = 0
|
|
|
|
|
|
class DashboardFinding(BaseModel):
|
|
id: uuid.UUID
|
|
scan_id: uuid.UUID
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
template_id: str
|
|
name: str
|
|
severity: str
|
|
host: str | None = None
|
|
matched_at: str
|
|
host_count: int = 1
|
|
is_kev: bool = False
|
|
is_new: bool = False
|
|
cve_ids: list[str] = Field(default_factory=list)
|
|
epss_score: float | None = None
|
|
cvss_score: float | None = None
|
|
discovered_at: datetime
|
|
|
|
|
|
class DashboardRisk(BaseModel):
|
|
total: int = 0
|
|
actionable: int = 0
|
|
kev: int = 0
|
|
ransomware: int = 0
|
|
overdue: int = 0
|
|
newly_exploited: int = 0
|
|
new_in_window: int = 0
|
|
suppressed: int = 0
|
|
targets_affected: int = 0
|
|
targets_scanned: int = 0
|
|
by_severity: list[SeverityCount] = Field(default_factory=list)
|
|
queue: list[DashboardFinding] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardGeo(BaseModel):
|
|
code: str
|
|
count: int
|
|
targets: list[DashboardTargetCount] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardExposureBand(BaseModel):
|
|
key: str
|
|
label: str
|
|
count: int = 0
|
|
targets: int = 0
|
|
query: str
|
|
|
|
|
|
class DashboardExposedService(BaseModel):
|
|
key: str
|
|
label: str
|
|
service_class: str
|
|
sensitive: bool = False
|
|
count: int = 0
|
|
query: str
|
|
targets: list[DashboardTargetCount] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardExposure(BaseModel):
|
|
services: int = 0
|
|
addresses: int = 0
|
|
targets: int = 0
|
|
sensitive: int = 0
|
|
sensitive_targets: int = 0
|
|
non_web: int = 0
|
|
bands: list[DashboardExposureBand] = Field(default_factory=list)
|
|
top: list[DashboardExposedService] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardCertSignal(BaseModel):
|
|
count: int = 0
|
|
query: str
|
|
targets: list[DashboardTargetCount] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardCerts(BaseModel):
|
|
expired: DashboardCertSignal
|
|
expiring: DashboardCertSignal
|
|
|
|
|
|
class DashboardChangeRow(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
target_type: str
|
|
runs: int = 0
|
|
last_scan_id: uuid.UUID
|
|
last_status: str
|
|
last_at: datetime
|
|
new: dict[str, int] = Field(default_factory=dict)
|
|
new_scan: dict[str, uuid.UUID | None] = Field(default_factory=dict)
|
|
first: list[str] = Field(default_factory=list)
|
|
gone_web_assets: int = 0
|
|
|
|
|
|
class DashboardDay(BaseModel):
|
|
date: str
|
|
runs: int = 0
|
|
failed: int = 0
|
|
new: dict[str, int] = Field(default_factory=dict)
|
|
|
|
|
|
class DashboardTargetSurface(BaseModel):
|
|
key: str
|
|
covered: bool = False
|
|
value: int | None = None
|
|
previous: int | None = None
|
|
delta: int | None = None
|
|
scan_id: uuid.UUID | None = None
|
|
scan_status: str | None = None
|
|
observed_at: datetime | None = None
|
|
|
|
|
|
class DashboardTargetRow(BaseModel):
|
|
id: uuid.UUID
|
|
value: str
|
|
type: str
|
|
scans_total: int = 0
|
|
last_scan_id: uuid.UUID | None = None
|
|
last_scan_status: str | None = None
|
|
last_scan_at: datetime | None = None
|
|
surface: list[DashboardTargetSurface] = Field(default_factory=list)
|
|
findings: int = 0
|
|
actionable: int = 0
|
|
kev: int = 0
|
|
worst_severity: str | None = None
|
|
risk_scan_id: uuid.UUID | None = None
|
|
sensitive_services: int = 0
|
|
services_scan_id: uuid.UUID | None = None
|
|
monitored: bool = False
|
|
|
|
|
|
class DashboardReadiness(BaseModel):
|
|
worker_online: bool = False
|
|
worker_concurrency: int | None = None
|
|
checks_ready: bool = False
|
|
checks_total: int = 0
|
|
|
|
|
|
class DashboardOverview(BaseModel):
|
|
generated_at: datetime
|
|
window: str
|
|
first_run: bool = False
|
|
targets_total: int = 0
|
|
targets_scanned: int = 0
|
|
targets_never_scanned: int = 0
|
|
targets_stale: int = 0
|
|
targets_monitored: int = 0
|
|
targets_by_type: dict[str, int] = Field(default_factory=dict)
|
|
runs_total: int = 0
|
|
runs_in_window: int = 0
|
|
failed_in_window: int = 0
|
|
last_completed_at: datetime | None = None
|
|
surface: list[DashboardSurfaceMetric] = Field(default_factory=list)
|
|
risk: DashboardRisk = Field(default_factory=DashboardRisk)
|
|
signals: DashboardSignals
|
|
never_scanned: list[StaleTarget] = Field(default_factory=list)
|
|
stale: list[StaleTarget] = Field(default_factory=list)
|
|
sensitive: list[DashboardTargetCount] = Field(default_factory=list)
|
|
expiring: list[ExpiringTarget] = Field(default_factory=list)
|
|
failed_runs: list[FailedRun] = Field(default_factory=list)
|
|
exposure: DashboardExposure = Field(default_factory=DashboardExposure)
|
|
certs: DashboardCerts
|
|
geography: list[DashboardGeo] = Field(default_factory=list)
|
|
geo_total: int = 0
|
|
changes: list[DashboardChangeRow] = Field(default_factory=list)
|
|
daily: list[DashboardDay] = Field(default_factory=list)
|
|
targets: list[DashboardTargetRow] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardDiscoverySource(BaseModel):
|
|
target_id: uuid.UUID
|
|
target_value: str
|
|
scan_id: uuid.UUID
|
|
seen_on: str
|
|
hostname_count: int = 0
|
|
|
|
|
|
class DashboardDiscoveredDomain(BaseModel):
|
|
domain: str
|
|
hostname_count: int = 0
|
|
hostnames: list[str] = Field(default_factory=list)
|
|
sources: list[DashboardDiscoverySource] = Field(default_factory=list)
|
|
|
|
|
|
class DashboardDiscovery(BaseModel):
|
|
targets_examined: int = 0
|
|
domains: list[DashboardDiscoveredDomain] = Field(default_factory=list)
|