Add PowerShell and CVE filtering options to detection rules (#754)
taylor_socfortress committed
Mar 9, 2026 at 08:57 UTC
bdf69920c6f622413091a08a4aa76b8a5c08df09
6 files changed
+115
-6
backend/app/integrations/copilot_searches/routes/copilot_searches.py
+63
-2
@@ -94,7 +94,7 @@ async def check_if_event_definition_exists(event_definition_title: str) -> bool:
94
async def list_rules(
95
platform: PlatformFilter = Query(
96
PlatformFilter.ALL,
97
- description="Filter by platform (linux, windows, all)",
97
+ description="Filter by platform (linux, windows, powershell, all)",
98
),
99
status: Optional[RuleStatus] = Query(
100
None,
@@ -123,7 +123,7 @@ async def list_rules(
123
List all detection rules with optional filtering.
124
125
Supports filtering by:
126
- - **platform**: linux, windows, or all
126
+ - **platform**: linux, windows, powershell, cve or all
127
- **status**: production, experimental, deprecated
128
- **severity**: low, medium, high, critical
129
- **mitre_id**: MITRE ATT&CK technique ID
@@ -202,6 +202,67 @@ async def list_windows_rules(
202
return RuleListResponse(**result)
203
204
205
+@copilot_searches_router.get(
206
+ "/powershell",
207
+ response_model=RuleListResponse,
208
+ description="List all PowerShell detection rules",
209
+)
210
+async def list_powershell_rules(
211
+ status: Optional[RuleStatus] = Query(None),
212
+ severity: Optional[RuleSeverity] = Query(None),
213
+ mitre_id: Optional[str] = Query(None),
214
+ search: Optional[str] = Query(None),
215
+ has_graylog: Optional[bool] = Query(None),
216
+ skip: int = Query(0, ge=0),
217
+ limit: int = Query(100, ge=1, le=500),
218
+):
219
+ """List all PowerShell detection rules."""
220
+ result = await get_rules_list(
221
+ platform=PlatformFilter.POWERSHELL,
222
+ status=status,
223
+ severity=severity,
224
+ mitre_id=mitre_id,
225
+ search=search,
226
+ has_graylog=has_graylog,
227
+ skip=skip,
228
+ limit=limit,
229
+ )
230
+
231
+ return RuleListResponse(**result)
232
+
233
+
234
+@copilot_searches_router.get(
235
+ "/cve",
236
+ response_model=RuleListResponse,
237
+ description="List all detection rules that have CVE tags",
238
+)
239
+async def list_cve_rules(
240
+ status: Optional[RuleStatus] = Query(None),
241
+ severity: Optional[RuleSeverity] = Query(None),
242
+ mitre_id: Optional[str] = Query(None),
243
+ search: Optional[str] = Query(None),
244
+ has_graylog: Optional[bool] = Query(None),
245
+ skip: int = Query(0, ge=0),
246
+ limit: int = Query(100, ge=1, le=500),
247
+):
248
+ """List all detection rules that have CVE tags."""
249
+ result = await get_rules_list(
250
+ status=status,
251
+ severity=severity,
252
+ mitre_id=mitre_id,
253
+ search=search,
254
+ has_graylog=has_graylog,
255
+ skip=skip,
256
+ limit=limit,
257
+ )
258
+
259
+ # Filter to only rules with CVE tags
260
+ result["rules"] = [r for r in result["rules"] if r.cve]
261
+ result["filtered"] = len(result["rules"])
262
+
263
+ return RuleListResponse(**result)
264
+
265
+
266
@copilot_searches_router.get(
267
"/stats",
268
response_model=RuleStatsResponse,
backend/app/integrations/copilot_searches/schema/copilot_searches.py
+2
@@ -13,6 +13,8 @@ class PlatformFilter(str, Enum):
13
ALL = "all"
14
LINUX = "linux"
15
WINDOWS = "windows"
16
+ POWERSHELL = "powershell"
17
+ CVE = "cve"
18
19
20
class RuleStatus(str, Enum):
backend/app/integrations/copilot_searches/services/copilot_searches.py
+10
-2
@@ -229,6 +229,10 @@ class RulesCache:
229
return "linux"
230
if "/windows/" in path_lower:
231
return "windows"
232
+ if "/powershell/" in path_lower:
233
+ return "powershell"
234
+ if "/cve/" in path_lower:
235
+ return "cve"
236
237
# Check tags
238
asset_type = rule_data.get("tags", {}).get("asset_type", "").lower()
@@ -239,9 +243,13 @@ class RulesCache:
243
244
# Check rule name
245
name_lower = rule_data.get("name", "").lower()
246
+ if "powershell" in name_lower:
247
+ return "powershell"
248
+ if "cve" in name_lower:
249
+ return "cve"
250
if "linux" in name_lower:
251
return "linux"
244
- if "windows" in name_lower or "powershell" in name_lower:
252
+ if "windows" in name_lower:
253
return "windows"
254
255
return "unknown"
@@ -520,7 +528,7 @@ async def get_rules_list(
528
Get filtered list of detection rules.
529
530
Args:
523
- platform: Filter by platform (linux, windows, all)
531
+ platform: Filter by platform (linux, windows, powershell, all)
532
status: Filter by rule status
533
severity: Filter by severity level
534
mitre_id: Filter by MITRE ATT&CK technique ID
frontend/src/api/endpoints/copilotSearches.ts
+36
@@ -71,6 +71,42 @@ export default {
71
})
72
},
73
74
+ /**
75
+ * List all PowerShell detection rules
76
+ */
77
+ getPowershellRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
78
+ return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/powershell`, {
79
+ params: {
80
+ status: query?.status,
81
+ severity: query?.severity,
82
+ mitre_id: query?.mitre_id,
83
+ search: query?.search,
84
+ has_graylog: query?.has_graylog,
85
+ skip: query?.skip || 0,
86
+ limit: query?.limit || 100
87
+ },
88
+ signal
89
+ })
90
+ },
91
+
92
+ /**
93
+ * List all detection rules that have CVE tags
94
+ */
95
+ getCveRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
96
+ return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/cve`, {
97
+ params: {
98
+ status: query?.status,
99
+ severity: query?.severity,
100
+ mitre_id: query?.mitre_id,
101
+ search: query?.search,
102
+ has_graylog: query?.has_graylog,
103
+ skip: query?.skip || 0,
104
+ limit: query?.limit || 100
105
+ },
106
+ signal
107
+ })
108
+ },
109
+
110
/**
111
* Get statistics about loaded detection rules
112
*/
frontend/src/components/copilotSearches/List.vue
+3
-1
@@ -199,7 +199,9 @@ const RefreshIcon = "carbon:renew"
199
200
const platformOptions = [
201
{ label: "Linux", value: "linux" },
202
- { label: "Windows", value: "windows" }
202
+ { label: "Windows", value: "windows" },
203
+ { label: "PowerShell", value: "powershell" },
204
+ { label: "CVE", value: "cve" }
205
]
206
207
const severityOptions = [
frontend/src/types/copilotSearches.d.ts
+1
-1
@@ -1,4 +1,4 @@
1
-export type PlatformFilter = "all" | "linux" | "windows"
1
+export type PlatformFilter = "all" | "linux" | "windows" | "powershell" | "cve"
2
export type RuleStatus = "production" | "experimental" | "deprecated"
3
export type RuleSeverity = "low" | "medium" | "high" | "critical"
4