Skip to content

Commit 63589e5

Browse files
PranavShukla7drosettipranavshukla
authored
Fix: Handle CNAME in Quad9 resolver and prevent DNS visualizer errors (#2959) (#3005)
* Fix Quad9 DNS resolver: handle A/AAAA/CNAME records properly to avoid visualizer errors (#2959) * Fix: Quad9 DNS resolver retry logic and DNS visualizer key error * Fix: DNS visualizer handle missing/empty 'resolutions' (#2959) Ensure visualizer handles analyzer reports without 'resolutions' and works with normalized records from Quad9 resolver. * Implement Quad9DNSResolver with JSON response parsing Switched the Quad9DNSResolver to use the Quad9 DoH JSON API instead of raw DNS wire parsing. This makes the analyzer simpler and aligned with maintainer’s request. The response is now parsed from the "Answer" section of the JSON to extract A record resolutions, while preserving retry and error handling logic. Also restored the missing comment for clarity. --------- Co-authored-by: Daniele Rosetti <[email protected]> Co-authored-by: pranavshukla <[email protected]>
1 parent a7fd60f commit 63589e5

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

api_app/analyzers_manager/observable_analyzers/dns/dns_resolvers/quad9_dns_resolver.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"""Quad9 DNS resolutions"""
55
import logging
66

7-
import dns.message
87
import httpx
98

109
from api_app.analyzers_manager import classes
@@ -35,21 +34,21 @@ def run(self):
3534
# with 2 or 3 attemps the analyzer should get the data
3635
attempt_number = 3
3736
quad9_response = None
38-
for attempt in range(0, attempt_number):
37+
for attempt in range(attempt_number):
3938
try:
4039
quad9_response = httpx.Client(http2=True).get(
4140
complete_url, headers=self.headers, timeout=10
4241
)
4342
except httpx.ConnectError as exception:
44-
# if the last attempt fails, raise an error
4543
if attempt == attempt_number - 1:
4644
raise exception
4745
else:
4846
quad9_response.raise_for_status()
4947

50-
dns_response = dns.message.from_wire(quad9_response.content)
48+
json_response = quad9_response.json()
5149
resolutions: list[str] = []
52-
for answer in dns_response.answer:
53-
resolutions.extend([resolution.address for resolution in answer])
50+
for answer in json_response.get("Answer", []):
51+
if "data" in answer:
52+
resolutions.append(answer["data"])
5453

5554
return dns_resolver_response(observable, resolutions)

api_app/visualizers_manager/visualizers/dns.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from api_app.analyzers_manager.observable_analyzers.dns.dns_resolvers.quad9_dns_resolver import ( # noqa: E501
2828
Quad9DNSResolver,
2929
)
30-
from api_app.choices import Classification
3130
from api_app.models import Job
3231
from api_app.visualizers_manager.classes import VisualizableObject, Visualizer
3332
from api_app.visualizers_manager.decorators import (
@@ -68,8 +67,8 @@ def _dns_resolution(self, analyzer_report: AnalyzerReport) -> VisualizableObject
6867
value=[
6968
self.Base(
7069
value=(
71-
dns_resolution["data"]
72-
if self._job.analyzable.classification == Classification.DOMAIN
70+
dns_resolution.get("data")
71+
if isinstance(dns_resolution, dict) and "data" in dns_resolution
7372
else dns_resolution
7473
),
7574
disable=False,

0 commit comments

Comments
 (0)