agentic-threat-hunting-framework 0.2.2__py3-none-any.whl → 0.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/METADATA +1 -1
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/RECORD +8 -8
- athf/commands/context.py +29 -15
- athf/core/hunt_manager.py +7 -0
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/WHEEL +0 -0
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/entry_points.txt +0 -0
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {agentic_threat_hunting_framework-0.2.2.dist-info → agentic_threat_hunting_framework-0.2.3.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-threat-hunting-framework
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Agentic Threat Hunting Framework - Memory and AI for threat hunters
|
|
5
5
|
Author-email: Sydney Marrone <athf@nebulock.io>
|
|
6
6
|
Maintainer-email: Sydney Marrone <athf@nebulock.io>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
agentic_threat_hunting_framework-0.2.
|
|
1
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/licenses/LICENSE,sha256=_KObErRfiKoolznt-DF0nJnr3U9Rdh7Z4Ba7G5qqckk,1071
|
|
2
2
|
athf/__init__.py,sha256=OrjZe8P97_BTEkscapnwSsqKSjwXNP9d8-HtGr19Ni0,241
|
|
3
3
|
athf/__version__.py,sha256=p9cAuZ-dTEMpo-qoeYkFo2166r8LvKpa5qHBZihGq3w,59
|
|
4
4
|
athf/cli.py,sha256=XLNRXEs9kHPH6utJ7_SnzLFcldbGAnACPMTe0xMOkhQ,4492
|
|
5
5
|
athf/commands/__init__.py,sha256=uDyr0bz-agpGO8fraXQl24wuQCxqbeCevZsJ2bDK29s,25
|
|
6
|
-
athf/commands/context.py,sha256=
|
|
6
|
+
athf/commands/context.py,sha256=WvOf0OuttAsEk_h4QDtdfqYI4CulDg2UCtq_5r5iJAA,12686
|
|
7
7
|
athf/commands/env.py,sha256=AisRllJXbyCjK_2ii21qBBmCz9raxhBUemwM7BxqIYg,11859
|
|
8
8
|
athf/commands/hunt.py,sha256=2KORNWAqEvLY-Wc1q-a894g8kOpcqw_iJfnenKJeTDI,23019
|
|
9
9
|
athf/commands/init.py,sha256=L_29fvZF8SZ1BKh2D6NyDuacCC5JXOTezIxdBnnK88E,10941
|
|
@@ -11,13 +11,13 @@ athf/commands/investigate.py,sha256=mK_id5vjfN_ukqB_-fyia0FNa0pBmtn0Xv6CKHQI1Qo,
|
|
|
11
11
|
athf/commands/similar.py,sha256=ROoMs4NP1otCaXwM1XzpLWxmANknoeASlBT7zuMDqas,11793
|
|
12
12
|
athf/core/__init__.py,sha256=yG7C8ljx3UW4QZoYvDjUxsWHlbS8M-GLGB7Je7rRfqo,31
|
|
13
13
|
athf/core/attack_matrix.py,sha256=QZKKmxckQ6-U7lqVdGUJoj2jEAhP3Juvr3sqaNx2oTw,3238
|
|
14
|
-
athf/core/hunt_manager.py,sha256=
|
|
14
|
+
athf/core/hunt_manager.py,sha256=PFsg8Ecg94NCpuFZpApo82lyORkgK5IfOIih-7-XsmM,11580
|
|
15
15
|
athf/core/hunt_parser.py,sha256=FUj0yyBIcZnaS9aItMImeBDhegQwpkewIwUMNXW_ZWU,5122
|
|
16
16
|
athf/core/investigation_parser.py,sha256=wbfjnq4gFgIc0a4bHIAnidVNPhbHDpIXWY1SGLk0Xls,6804
|
|
17
17
|
athf/core/template_engine.py,sha256=vNTVhlxIXZpxU7VmQyrqCSt6ORS0IVjAV54TOmUDMTE,5636
|
|
18
18
|
athf/utils/__init__.py,sha256=aEAPI1xnAsowOtc036cCb9ZOek5nrrfevu8PElhbNgk,30
|
|
19
|
-
agentic_threat_hunting_framework-0.2.
|
|
20
|
-
agentic_threat_hunting_framework-0.2.
|
|
21
|
-
agentic_threat_hunting_framework-0.2.
|
|
22
|
-
agentic_threat_hunting_framework-0.2.
|
|
23
|
-
agentic_threat_hunting_framework-0.2.
|
|
19
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/METADATA,sha256=I3x8s2Rff1A7BjYz-lfy_M6I_qw0-nDBC2Ypc0DcxTA,15472
|
|
20
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/entry_points.txt,sha256=GopR2iTiBs-yNMWiUZ2DaFIFglXxWJx1XPjTa3ePtfE,39
|
|
22
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/top_level.txt,sha256=Cxxg6SMLfawDJWBITsciRzq27XV8fiaAor23o9Byoes,5
|
|
23
|
+
agentic_threat_hunting_framework-0.2.3.dist-info/RECORD,,
|
athf/commands/context.py
CHANGED
|
@@ -22,6 +22,9 @@ Examples:
|
|
|
22
22
|
# Export context for macOS platform hunts
|
|
23
23
|
athf context --platform macos
|
|
24
24
|
|
|
25
|
+
# Combine filters: persistence hunts on Linux
|
|
26
|
+
athf context --tactic persistence --platform linux
|
|
27
|
+
|
|
25
28
|
# Export full repository context (large output)
|
|
26
29
|
athf context --full
|
|
27
30
|
|
|
@@ -86,18 +89,20 @@ def context(
|
|
|
86
89
|
• With context: 1 command, ~1,000 tokens
|
|
87
90
|
• Savings: ~2,000 tokens per hunt (~$0.03 per hunt)
|
|
88
91
|
"""
|
|
89
|
-
# Validate
|
|
90
|
-
|
|
91
|
-
if
|
|
92
|
-
console.print("[red]Error: Must specify one of: --hunt, --tactic, --platform, or --full[/red]")
|
|
92
|
+
# Validate that at least one filter is provided
|
|
93
|
+
has_filter = any([hunt, tactic, platform, full])
|
|
94
|
+
if not has_filter:
|
|
95
|
+
console.print("[red]Error: Must specify at least one of: --hunt, --tactic, --platform, or --full[/red]")
|
|
93
96
|
console.print("\n[dim]Examples:[/dim]")
|
|
94
97
|
console.print(" athf context --hunt H-0013")
|
|
95
98
|
console.print(" athf context --tactic credential-access")
|
|
96
99
|
console.print(" athf context --platform macos")
|
|
100
|
+
console.print(" athf context --tactic persistence --platform linux")
|
|
97
101
|
raise click.Abort()
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
# --full flag is mutually exclusive with other filters
|
|
104
|
+
if full and (hunt or tactic or platform):
|
|
105
|
+
console.print("[red]Error: --full cannot be combined with other filters[/red]")
|
|
101
106
|
raise click.Abort()
|
|
102
107
|
|
|
103
108
|
# Build context bundle
|
|
@@ -158,17 +163,26 @@ def _build_context(
|
|
|
158
163
|
if index_path.exists():
|
|
159
164
|
context["hunt_index"] = _read_and_optimize(index_path)
|
|
160
165
|
|
|
161
|
-
# Load hunts based on
|
|
162
|
-
if
|
|
163
|
-
|
|
164
|
-
elif tactic:
|
|
165
|
-
hunt_files = _find_hunts_by_tactic(tactic)
|
|
166
|
-
elif platform:
|
|
167
|
-
hunt_files = _find_hunts_by_platform(platform)
|
|
168
|
-
elif full:
|
|
166
|
+
# Load hunts based on filters (can be combined)
|
|
167
|
+
if full:
|
|
168
|
+
# Full export: include all hunts
|
|
169
169
|
hunt_files = list(Path("hunts").glob("H-*.md"))
|
|
170
|
+
elif hunt:
|
|
171
|
+
# Specific hunt: only load that one
|
|
172
|
+
hunt_files = [Path(f"hunts/{hunt}.md")]
|
|
170
173
|
else:
|
|
171
|
-
|
|
174
|
+
# Combine tactic and platform filters
|
|
175
|
+
if tactic and platform:
|
|
176
|
+
# Both filters: find hunts matching both criteria
|
|
177
|
+
tactic_hunts = set(_find_hunts_by_tactic(tactic))
|
|
178
|
+
platform_hunts = set(_find_hunts_by_platform(platform))
|
|
179
|
+
hunt_files = list(tactic_hunts & platform_hunts) # Intersection
|
|
180
|
+
elif tactic:
|
|
181
|
+
hunt_files = _find_hunts_by_tactic(tactic)
|
|
182
|
+
elif platform:
|
|
183
|
+
hunt_files = _find_hunts_by_platform(platform)
|
|
184
|
+
else:
|
|
185
|
+
hunt_files = []
|
|
172
186
|
|
|
173
187
|
# Load hunt content
|
|
174
188
|
for hunt_file in hunt_files:
|
athf/core/hunt_manager.py
CHANGED
|
@@ -154,7 +154,14 @@ class HuntManager:
|
|
|
154
154
|
results = []
|
|
155
155
|
query_lower = query.lower()
|
|
156
156
|
|
|
157
|
+
# Exclude documentation files
|
|
158
|
+
exclude_files = {"README.md", "FORMAT_GUIDELINES.md"}
|
|
159
|
+
|
|
157
160
|
for hunt_file in self.hunts_dir.glob("*.md"):
|
|
161
|
+
# Skip documentation files
|
|
162
|
+
if hunt_file.name in exclude_files:
|
|
163
|
+
continue
|
|
164
|
+
|
|
158
165
|
try:
|
|
159
166
|
with open(hunt_file, "r", encoding="utf-8") as f:
|
|
160
167
|
content = f.read()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|