[GSoC 2026] core(datamodel): populate the reconciled verdict for key-free domain/URL analyzers - #3893
Conversation
…-banded reliability)
mlodic
left a comment
There was a problem hiding this comment.
Could you share a screenshot of a working execution of a DNS playbook analysis to show how data models are populated in the raw results of at least one of the changed analyzers?
Here's a real run of the Dns playbook on
The analyzer's report says "malicious": true, and the data_model it produced carries "evaluation": "malicious" with "reliability": 6, the value mapped for this analyzer in migration 0195. The same screenshot also shows the gate working: Quad9_Malicious_Detector, UltraDNS_Malicious_Detector and DNS4EU_Malicious_Detector all answered "malicious": false on the same domain and produced no data model at all, so a clean lookup is never stamped malicious. The job's reconciled verdict is malicious / 6.
|
mlodic
left a comment
There was a problem hiding this comment.
thanks for the efforts and the explanations, wonderful result


Description
Populate
job.data_modelwith a reconciled verdict (evaluation+reliability) for the key-freedomain/URL analyzers that today produce a malicious/benign signal but throw it away because they carry no
DataModel hook. Once populated, the same verdict is read by the visualizer badge, the reconciliation
engine, pivots, and (in a follow-up chatbot PR) the assistant — one source of truth, no semantic fork.
This is the core-first part of the chatbot result-interpretation effort (PR B of the split; the
chatbot reader that consumes this lands separately).
Refs #3892What changes
classify()extracted from the DataModel visualizer intoapi_app/data_model_manager/classify.py(single source of the five presentation buckets + the
8/6thresholds), with the bucket names in aDataModelVerdictBuckets(Choices)enum indata_model_manager/enums.pywhoseTRUSTED/MALICIOUSmembers derive from
DataModelEvaluations; the visualizer now calls it — behaviour-preserving.AdGuard,Quad9,CloudFlare,CleanBrowsing,UltraDNS,DNS4EU,Mullvad,Spamhaus_WQS,GoogleSafebrowsing,GoogleWebRisk) contributeevaluation=maliciousonly on a real hit, via a shared_do_create_data_modelgate mixin + adeclarative
mapping_data_modelmigration (0195).0196).evaluation=malicious, reliability 8 verified / 5 unverified (_update_data_model).evaluation=trusted, reliability banded byrank, with the top 1000 treated as a reliable allowlist (
_update_data_model).The load-bearing safety point: a
$-prefixedmapping_data_modelkey writes its constantunconditionally whenever a data model is created (
analyzers_manager/models.py:92-95), so{"$malicious":"evaluation"}would stamp MALICIOUS on every clean lookup. Each analyzer's_do_create_data_modelgate is what suppresses non-hits (miss / timeout / failure → no data model,never
trusted). This is unit-tested per analyzer, incl. the critical clean-lookup case.Reliability table (single reviewable source;
reliability= trust in the source):Two regimes, following review feedback:
trusted) — treated as a reliable allowlist, and intended to outrank amalicious hit under the engine's average-reliability reconciliation. Rationale (@mlodic): in daily
incident response false positives are the expensive failure mode, because the analyst time they burn
costs more than the rare true positive they hide, so reliable allowlists must be enforced where
available. This puts Tranco's top band at the same reliability as the pre-existing
HuntingAbuseAPIallowlist (9).
clean) — popularity is weak positive evidence: every maliciousreliability (≥5) stays above it, so a popular-but-flagged domain still resolves to malicious.
The malicious tiers (8/7/6) reflect source authority and can be flattened on request.
Notes for reviewers (pre-empting two accurate observations from self-review):
HuntingAbuseAPIalreadymaps
$trusted/reliability 9 (allowlist,0158) and is untouched here; it sits above the maliciousrange by design and does not affect the two regimes above.
Noneevaluation default to reliability 5; a lone Tranco
trustedfrom the lower bands (2–4) can beout-averaged by such a group and reconcile to
no evaluationrather thanclean. This is orthogonalto the malicious guarantee (malicious ≥6 always wins) and is existing
EvaluationEngineModulebehaviour, surfaced here for transparency.
Type of change
classify()extraction).Checklist
developDataModelpopulation for the changed analyzers following thedocumentation (declarative
mapping_data_model+_do_create_data_model/_update_data_modelhooks,mirroring the URLhaus / HuntingAbuseAPI precedents). No new analyzer was added — existing key-free
analyzers gain DataModel hooks; the plugin sub-items about new-analyzer samples/
FREE_TO_USE/urlattributes do not apply.
tests).
Ruff) gave 0 errors (check+format --checkclean on all 25 files).against a rebuilt test image (
makemigrations --checkclean; affected suite green, incl.engines_manager+visualizers_managerregression checks).changes).
DeepSource/Django Doctorsalerts raised on the PR.generated code (design, per-analyzer implementation, and tests were reviewed; behaviour verified via the
local test suite).