From f7f31eeaee9e8554f15757f2b7f3c2b0ba19d1f9 Mon Sep 17 00:00:00 2001 From: cicada0007 Date: Sun, 23 Mar 2025 11:34:23 +0530 Subject: [PATCH 1/4] added Threat Intelligence --- .../organization/organization_analytics.html | 52 +++++++++++++++++++ website/views/company.py | 52 ++++++++++++++++++- 2 files changed, 102 insertions(+), 2 deletions(-) diff --git a/website/templates/organization/organization_analytics.html b/website/templates/organization/organization_analytics.html index bf1f2f1575..940834b7ee 100644 --- a/website/templates/organization/organization_analytics.html +++ b/website/templates/organization/organization_analytics.html @@ -327,6 +327,58 @@

Top Affected Domains

+ +
+
+

Threat Intelligence

+
+ + +
+

Security Risk Score

+
+
+
+ + {{ threat_intelligence.risk_score }}/100 + +
+
+
+
+ + +
+

Top Issue Categories

+
+ {% for vector in threat_intelligence.attack_vectors %} +
+ {{ vector.vulnerability_type }} + {{ vector.count }} +
+ {% endfor %} +
+
+ + +
+

Recent Security Alerts

+
+ {% for alert in threat_intelligence.recent_alerts %} +
+ + {{ alert.description }} +
+ {% endfor %} +
+
+ +
+
+
{% endblock body %} {% block js %} diff --git a/website/views/company.py b/website/views/company.py index c3ba42b341..288344d3d0 100644 --- a/website/views/company.py +++ b/website/views/company.py @@ -225,6 +225,52 @@ def get_security_incidents_summary(self, organization): .order_by("-count")[:5], } + def get_threat_intelligence(self, organization): + """Gets threat intelligence data for the organization.""" + security_issues = Issue.objects.filter( + domain__organization__id=organization, + label=4, # Security label + ) + + # Get trending attack types based on issue labels/tags instead + attack_vectors = ( + security_issues.filter(created__gte=timezone.now() - timedelta(days=90)) + .values("label") # Use label instead of vulnerability_type + .annotate(count=Count("id")) + .order_by("-count")[:5] + ) + + # Calculate risk score (0-100) + total_issues = security_issues.count() + critical_issues = security_issues.filter(cve_score__gte=8).count() # Use cve_score instead of severity + risk_score = min(100, (critical_issues / total_issues * 100) if total_issues > 0 else 0) + + return { + "attack_vectors": [ + { + "vulnerability_type": self.get_label_name(vector["label"]), # Convert label to readable name + "count": vector["count"], + } + for vector in attack_vectors + ], + "risk_score": int(risk_score), + "recent_alerts": security_issues.filter( + created__gte=timezone.now() - timedelta(days=7), + cve_score__gte=7, # Use cve_score for severity + ).order_by("-created")[:5], + } + + def get_label_name(self, label_id): + """Convert label ID to human-readable name.""" + label_names = { + 1: "Design", + 2: "Functional", + 3: "Performance", + 4: "Security", + # Add more labels as needed + } + return label_names.get(label_id, "Other") + def get_general_info(self, organization): total_organization_bugs = Issue.objects.filter(domain__organization__id=organization).count() total_bug_hunts = Hunt.objects.filter(domain__organization__id=organization).count() @@ -413,6 +459,7 @@ def get(self, request, id, *args, **kwargs): "spent_on_bugtypes": self.get_spent_on_bugtypes(id), "security_incidents_summary": self.get_security_incidents_summary(id), } + context.update({"threat_intelligence": self.get_threat_intelligence(id)}) return render(request, "organization/organization_analytics.html", context=context) @@ -1233,8 +1280,9 @@ def get(self, request, id, *args, **kwargs): .distinct() ) else: - # For unauthenticated users, don't show organization list - organizations = [] + # For unauthenticated users, show empty lists + organization_users_list = [] + domains_data = [] # Get the organization object organization_obj = Organization.objects.filter(id=id).first() From 6024fb33c9130221caf4632659e1d7b100560432 Mon Sep 17 00:00:00 2001 From: cicada0007 Date: Sun, 23 Mar 2025 11:51:56 +0530 Subject: [PATCH 2/4] fix --- .../organization/organization_analytics.html | 9 +-------- website/views/company.py | 14 +++----------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/website/templates/organization/organization_analytics.html b/website/templates/organization/organization_analytics.html index 940834b7ee..0b58b85483 100644 --- a/website/templates/organization/organization_analytics.html +++ b/website/templates/organization/organization_analytics.html @@ -332,24 +332,19 @@

Top Affected Domains

Threat Intelligence

-

Security Risk Score

- + {{ threat_intelligence.risk_score }}/100
-

Top Issue Categories

@@ -362,7 +357,6 @@

Top Issue Categories

{% endfor %}
-

Recent Security Alerts

@@ -375,7 +369,6 @@

Recent Security Alerts

{% endfor %}
- diff --git a/website/views/company.py b/website/views/company.py index 288344d3d0..ee87e31fbf 100644 --- a/website/views/company.py +++ b/website/views/company.py @@ -262,14 +262,7 @@ def get_threat_intelligence(self, organization): def get_label_name(self, label_id): """Convert label ID to human-readable name.""" - label_names = { - 1: "Design", - 2: "Functional", - 3: "Performance", - 4: "Security", - # Add more labels as needed - } - return label_names.get(label_id, "Other") + return self.labels.get(label_id, "Other") def get_general_info(self, organization): total_organization_bugs = Issue.objects.filter(domain__organization__id=organization).count() @@ -1280,9 +1273,8 @@ def get(self, request, id, *args, **kwargs): .distinct() ) else: - # For unauthenticated users, show empty lists - organization_users_list = [] - domains_data = [] + # For unauthenticated users, don't show organization list + organizations = [] # Get the organization object organization_obj = Organization.objects.filter(id=id).first() From 15f454cc8d920cd38ee301d67a45672065a7cb75 Mon Sep 17 00:00:00 2001 From: cicada0007 Date: Mon, 24 Mar 2025 23:56:43 +0530 Subject: [PATCH 3/4] fix --- website/views/company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/views/company.py b/website/views/company.py index ee87e31fbf..77faaab4f8 100644 --- a/website/views/company.py +++ b/website/views/company.py @@ -262,7 +262,7 @@ def get_threat_intelligence(self, organization): def get_label_name(self, label_id): """Convert label ID to human-readable name.""" - return self.labels.get(label_id, "Other") + return self.labels.get(label_id, "Other" def get_general_info(self, organization): total_organization_bugs = Issue.objects.filter(domain__organization__id=organization).count() From 88b74d47073a1b7a4e25540b85c64c74a51f27f0 Mon Sep 17 00:00:00 2001 From: cicada0007 Date: Tue, 25 Mar 2025 02:54:09 +0530 Subject: [PATCH 4/4] fix --- website/views/company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/views/company.py b/website/views/company.py index 77faaab4f8..ee87e31fbf 100644 --- a/website/views/company.py +++ b/website/views/company.py @@ -262,7 +262,7 @@ def get_threat_intelligence(self, organization): def get_label_name(self, label_id): """Convert label ID to human-readable name.""" - return self.labels.get(label_id, "Other" + return self.labels.get(label_id, "Other") def get_general_info(self, organization): total_organization_bugs = Issue.objects.filter(domain__organization__id=organization).count()