-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolicy.py
More file actions
260 lines (215 loc) · 7.43 KB
/
policy.py
File metadata and controls
260 lines (215 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
"""
Policy Mapping Module
Maps risk scores to categories and Gmail labels
Defines threat classification and labeling strategy
"""
from typing import Dict
def map_score_to_label(risk_score: float) -> Dict:
"""
Map numerical risk score to category and Gmail label
Args:
risk_score: Risk score from 0 to 100
Returns:
Dictionary containing:
- category: str - "SAFE", "REVIEW", or "HIGH_RISK"
- label: str - Gmail label path
- color: str - Suggested color for UI
- action: str - Recommended user action
- description: str - Human-readable description
Score Ranges:
0-29 → SAFE
30-69 → REVIEW
70-100 → HIGH_RISK
"""
# Clamp score to valid range
score = max(0.0, min(100.0, float(risk_score)))
if score < 30:
return {
"category": "SAFE",
"label": "phishguard/safe",
"color": "#1a7f37", # Green
"action": "no_action",
"description": "Email appears legitimate with low risk indicators",
"severity_emoji": "✅",
"severity_level": 1
}
elif score < 70:
return {
"category": "REVIEW",
"label": "phishguard/review",
"color": "#9e6a03", # Yellow/Orange
"action": "user_review",
"description": "Email contains suspicious elements requiring review",
"severity_emoji": "⚠️",
"severity_level": 2
}
else:
return {
"category": "HIGH_RISK",
"label": "phishguard/high-risk",
"color": "#da3633", # Red
"action": "quarantine",
"description": "Email shows strong phishing indicators - high threat",
"severity_emoji": "🚫",
"severity_level": 3
}
def get_all_labels() -> list[Dict]:
"""
Get all available PhishGuard labels with metadata
Returns:
List of label dictionaries
"""
return [
{
"category": "SAFE",
"label": "phishguard/safe",
"color": "#1a7f37",
"description": "Verified safe emails"
},
{
"category": "REVIEW",
"label": "phishguard/review",
"color": "#9e6a03",
"description": "Emails requiring manual review"
},
{
"category": "HIGH_RISK",
"label": "phishguard/high-risk",
"color": "#da3633",
"description": "High-risk phishing threats"
}
]
def get_action_recommendations(category: str) -> list[str]:
"""
Get recommended actions for a given category
Args:
category: "SAFE", "REVIEW", or "HIGH_RISK"
Returns:
List of recommended action strings
"""
recommendations = {
"SAFE": [
"Email appears legitimate",
"Proceed with normal caution",
"Verify any unexpected requests independently"
],
"REVIEW": [
"Verify sender identity through alternative channel",
"Examine all links carefully before clicking",
"Be cautious with any sensitive information requests",
"Check for domain name anomalies",
"Contact sender directly if in doubt"
],
"HIGH_RISK": [
"DO NOT click any links in this email",
"DO NOT provide any personal or financial information",
"DO NOT download or open attachments",
"Mark as spam and delete immediately",
"Report to your IT security team",
"Block sender if possible"
]
}
return recommendations.get(category, recommendations["REVIEW"])
def should_auto_label(risk_score: float, confidence_threshold: float = 60.0) -> bool:
"""
Determine if email should be automatically labeled
Args:
risk_score: Risk score 0-100
confidence_threshold: Minimum confidence for auto-labeling
Returns:
True if should auto-label, False if needs manual review
"""
# Auto-label if score is very low (clearly safe) or very high (clearly dangerous)
# Avoid auto-labeling borderline cases
return risk_score < 20 or risk_score > 80
def calculate_confidence(risk_score: float, num_indicators: int, has_ai_analysis: bool) -> float:
"""
Calculate confidence level of the classification
Args:
risk_score: Risk score 0-100
num_indicators: Number of detected indicators
has_ai_analysis: Whether Gemini AI analysis was used
Returns:
Confidence score 0-100
"""
base_confidence = 50.0
# Increase confidence with more indicators
indicator_bonus = min(30.0, num_indicators * 5.0)
# Increase confidence if AI analysis was performed
ai_bonus = 20.0 if has_ai_analysis else 0.0
# Extreme scores are more confident
if risk_score < 15 or risk_score > 85:
extremity_bonus = 10.0
else:
extremity_bonus = 0.0
confidence = base_confidence + indicator_bonus + ai_bonus + extremity_bonus
return min(100.0, confidence)
def get_label_for_display(category: str) -> Dict:
"""
Get display properties for a category
Args:
category: "SAFE", "REVIEW", or "HIGH_RISK"
Returns:
Dictionary with display properties
"""
display_map = {
"SAFE": {
"text": "Safe",
"badge_class": "badge-safe",
"emoji": "✅",
"color": "#1a7f37"
},
"REVIEW": {
"text": "Review",
"badge_class": "badge-review",
"emoji": "⚠️",
"color": "#9e6a03"
},
"HIGH_RISK": {
"text": "High Risk",
"badge_class": "badge-high",
"emoji": "🚫",
"color": "#da3633"
}
}
return display_map.get(category, display_map["REVIEW"])
def merge_heuristic_and_ai_scores(heuristic_score: float, ai_score: float, ai_weight: float = 0.7) -> float:
"""
Merge heuristic and AI risk scores with weighted average
Args:
heuristic_score: Score from heuristic analysis (0-100)
ai_score: Score from AI analysis (0-100)
ai_weight: Weight for AI score (0-1), default 0.7
Returns:
Combined risk score 0-100
"""
heuristic_weight = 1.0 - ai_weight
combined = (ai_score * ai_weight) + (heuristic_score * heuristic_weight)
return max(0.0, min(100.0, combined))
def escalate_category(current_category: str) -> str:
"""
Escalate to next higher threat category
Args:
current_category: Current category
Returns:
Escalated category
"""
escalation_map = {
"SAFE": "REVIEW",
"REVIEW": "HIGH_RISK",
"HIGH_RISK": "HIGH_RISK" # Already at max
}
return escalation_map.get(current_category, "REVIEW")
# Risk score normalization utilities
def normalize_heuristic_score(heuristic_score: float, scale: str = "10") -> float:
"""
Normalize heuristic score to 0-100 scale
Args:
heuristic_score: Original heuristic score
scale: Original scale ("10" for 0-10 scale, "100" for 0-100)
Returns:
Normalized score 0-100
"""
if scale == "10":
return min(100.0, heuristic_score * 10.0)
return max(0.0, min(100.0, float(heuristic_score)))