@cryptotaxi247 / CoPilot / commits / bdf69920

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