-
-
Notifications
You must be signed in to change notification settings - Fork 652
[GSoC 2026] core(datamodel): populate the reconciled verdict for key-free domain/URL analyzers #3893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
[GSoC 2026] core(datamodel): populate the reconciled verdict for key-free domain/URL analyzers #3893
Changes from 6 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
67e6f6b
[GSoC 2026] core(datamodel): extract shared classify() from the DataM…
berardifra 204fa9f
[GSoC 2026] core(datamodel): populate evaluation for key-free DNS mal…
berardifra b05c67f
[GSoC 2026] core(datamodel): Phishtank verdict (verified vs unverifie…
berardifra a4572b6
[GSoC 2026] core(datamodel): PhishingArmy + Phishstats verdict on a l…
berardifra 75f0c7d
[GSoC 2026] core(datamodel): Tranco popularity verdict (trusted, rank…
berardifra 7e70eb7
[GSoC 2026] test(datamodel): anti-rot guard for key-free verdict targ…
berardifra fbaf00b
[GSoC 2026] core(datamodel): score Tranco top-1000 domains as allowli…
berardifra 48dc6f2
[GSoC 2026] core(datamodel): replace the bucket constants with a shar…
berardifra File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
api_app/analyzers_manager/migrations/0195_data_model_key_free_detectors.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl | ||
| # See the file 'LICENSE' for copying permission. | ||
|
|
||
| from django.db import migrations | ||
|
|
||
| # Single reviewable reliability table. $-prefixed keys are written as literal | ||
| # constants (analyzers_manager/models.py:92-95). Conditionality lives in each | ||
| # analyzer's _do_create_data_model gate, so a non-hit produces no data model. | ||
| # Reliability tiers reflect source authority: Google Safe Browsing/WebRisk (8) | ||
| # and Spamhaus (7) rank above the DNS-resolver blocklists (6). | ||
| MAPPINGS = { | ||
| "GoogleSafebrowsing": {"$malicious": "evaluation", "$8": "reliability"}, | ||
| "GoogleWebRisk": {"$malicious": "evaluation", "$8": "reliability"}, | ||
| "Spamhaus_WQS": {"$malicious": "evaluation", "$7": "reliability"}, | ||
| "AdGuard": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "Quad9_Malicious_Detector": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "CloudFlare_Malicious_Detector": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "CleanBrowsing_Malicious_Detector": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "UltraDNS_Malicious_Detector": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "DNS4EU_Malicious_Detector": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "Mullvad_DNS": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| } | ||
|
|
||
|
|
||
| def apply_mappings(apps, schema_editor): | ||
| AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") | ||
| for name, mapping in MAPPINGS.items(): | ||
| ac = AnalyzerConfig.objects.filter(name=name).first() | ||
| if not ac: | ||
| continue | ||
| ac.mapping_data_model = mapping | ||
| ac.save() | ||
|
|
||
|
|
||
| def revert_mappings(apps, schema_editor): | ||
| AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") | ||
| for name in MAPPINGS: | ||
| ac = AnalyzerConfig.objects.filter(name=name).first() | ||
| if not ac: | ||
| continue | ||
| ac.mapping_data_model = {} | ||
| ac.save() | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("analyzers_manager", "0194_analyzer_config_rdap"), | ||
| ] | ||
| operations = [ | ||
| migrations.RunPython(apply_mappings, revert_mappings), | ||
| ] |
41 changes: 41 additions & 0 deletions
41
api_app/analyzers_manager/migrations/0196_data_model_phishing_lists.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl | ||
| # See the file 'LICENSE' for copying permission. | ||
|
|
||
| from django.db import migrations | ||
|
|
||
| # Same declarative pattern as 0195: $-prefixed keys are written as literal | ||
| # constants (analyzers_manager/models.py:92-95). A listing hit is gated in each | ||
| # analyzer's _do_create_data_model, so a miss produces no data model. | ||
| MAPPINGS = { | ||
| "PhishingArmy": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| "Phishstats": {"$malicious": "evaluation", "$6": "reliability"}, | ||
| } | ||
|
|
||
|
|
||
| def apply_mappings(apps, schema_editor): | ||
| AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") | ||
| for name, mapping in MAPPINGS.items(): | ||
| ac = AnalyzerConfig.objects.filter(name=name).first() | ||
| if not ac: | ||
| continue | ||
| ac.mapping_data_model = mapping | ||
| ac.save() | ||
|
|
||
|
|
||
| def revert_mappings(apps, schema_editor): | ||
| AnalyzerConfig = apps.get_model("analyzers_manager", "AnalyzerConfig") | ||
| for name in MAPPINGS: | ||
| ac = AnalyzerConfig.objects.filter(name=name).first() | ||
| if not ac: | ||
| continue | ||
| ac.mapping_data_model = {} | ||
| ac.save() | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("analyzers_manager", "0195_data_model_key_free_detectors"), | ||
| ] | ||
| operations = [ | ||
| migrations.RunPython(apply_mappings, revert_mappings), | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
api_app/analyzers_manager/observable_analyzers/dns/dns_malicious_detectors/data_model.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl | ||
| # See the file 'LICENSE' for copying permission. | ||
|
|
||
|
|
||
| class MaliciousDetectorResponseDataModelMixin: | ||
| """Emit a DataModel only on a real malicious hit. | ||
|
|
||
| These analyzers map the constant ``$malicious -> evaluation`` in their | ||
| ``mapping_data_model``, which writes ``evaluation = "malicious"`` unconditionally | ||
| whenever a data model is created. So a clean lookup (``malicious: false``), a | ||
| timeout, or a failure note would otherwise be stamped MALICIOUS. Gating creation | ||
| on ``report["malicious"] is True`` makes a non-hit produce no data model (silent); | ||
| it must never map a non-hit to trusted. | ||
| """ | ||
|
|
||
| def _do_create_data_model(self) -> bool: | ||
| return super()._do_create_data_model() and self.report.report.get("malicious") is True |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl | ||
| # See the file 'LICENSE' for copying permission. | ||
|
|
||
| from api_app.data_model_manager.enums import DataModelEvaluations | ||
|
|
||
| # Presentation buckets — the single source of truth consumed by both the | ||
| # DataModel visualizer and (later) the chatbot, so every surface says the same | ||
| # word for the same (evaluation, reliability) pair. | ||
| BUCKET_TRUSTED = "trusted" | ||
| BUCKET_CLEAN = "clean" | ||
| BUCKET_MALICIOUS = "malicious" | ||
| BUCKET_SUSPICIOUS = "suspicious" | ||
| BUCKET_NO_EVALUATION = "no evaluation" | ||
|
mlodic marked this conversation as resolved.
Outdated
|
||
|
|
||
| # Bucket boundaries (verbatim from the pre-existing visualizer logic this | ||
| # function replaced). | ||
| TRUSTED_RELIABILITY_FLOOR = 8 | ||
| MALICIOUS_RELIABILITY_FLOOR = 6 | ||
|
|
||
|
|
||
| def classify(evaluation: str | None, reliability: int) -> str: | ||
| """Map a (evaluation, reliability) pair to one of the five presentation buckets. | ||
|
|
||
| Single source of truth for the bucketing: the DataModel visualizer calls this | ||
| (and the chatbot will), so the badge and the chat always agree. | ||
| """ | ||
| if evaluation == DataModelEvaluations.TRUSTED.value: | ||
| return BUCKET_TRUSTED if reliability >= TRUSTED_RELIABILITY_FLOOR else BUCKET_CLEAN | ||
| if evaluation == DataModelEvaluations.MALICIOUS.value: | ||
| return BUCKET_MALICIOUS if reliability >= MALICIOUS_RELIABILITY_FLOOR else BUCKET_SUSPICIOUS | ||
| return BUCKET_NO_EVALUATION | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.