agentic-threat-hunting-framework 0.2.0__tar.gz → 0.2.2__tar.gz

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.
Files changed (61) hide show
  1. {agentic_threat_hunting_framework-0.2.0/agentic_threat_hunting_framework.egg-info → agentic_threat_hunting_framework-0.2.2}/PKG-INFO +1 -1
  2. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2/agentic_threat_hunting_framework.egg-info}/PKG-INFO +1 -1
  3. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/__version__.py +1 -1
  4. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/context.py +3 -3
  5. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/env.py +2 -1
  6. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/investigate.py +8 -8
  7. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/similar.py +4 -4
  8. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/attack_matrix.py +19 -4
  9. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/hunt_manager.py +2 -2
  10. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/investigation_parser.py +3 -3
  11. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/CHANGELOG.md +28 -0
  12. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/CLI_REFERENCE.md +3 -3
  13. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/pyproject.toml +1 -1
  14. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/LICENSE +0 -0
  15. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/MANIFEST.in +0 -0
  16. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/README.md +0 -0
  17. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/USING_ATHF.md +0 -0
  18. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/agentic_threat_hunting_framework.egg-info/SOURCES.txt +0 -0
  19. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/agentic_threat_hunting_framework.egg-info/dependency_links.txt +0 -0
  20. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/agentic_threat_hunting_framework.egg-info/entry_points.txt +0 -0
  21. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/agentic_threat_hunting_framework.egg-info/requires.txt +0 -0
  22. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/agentic_threat_hunting_framework.egg-info/top_level.txt +0 -0
  23. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf-cli-workflow.gif +0 -0
  24. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf-level0.gif +0 -0
  25. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf-level1.gif +0 -0
  26. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf-level2.gif +0 -0
  27. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf-level3.gif +0 -0
  28. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf_fivelevels.png +0 -0
  29. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf_level_3.png +0 -0
  30. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf_lock.png +0 -0
  31. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf_logo.png +0 -0
  32. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/assets/athf_manual_v_ai.png +0 -0
  33. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/__init__.py +0 -0
  34. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/cli.py +0 -0
  35. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/__init__.py +0 -0
  36. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/hunt.py +0 -0
  37. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/commands/init.py +0 -0
  38. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/__init__.py +0 -0
  39. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/hunt_parser.py +0 -0
  40. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/core/template_engine.py +0 -0
  41. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/athf/utils/__init__.py +0 -0
  42. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/INSTALL.md +0 -0
  43. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/README.md +0 -0
  44. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/environment.md +0 -0
  45. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/getting-started.md +0 -0
  46. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/level4-agentic-workflows.md +0 -0
  47. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/lock-pattern.md +0 -0
  48. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/maturity-model.md +0 -0
  49. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/docs/why-athf.md +0 -0
  50. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/hunts/FORMAT_GUIDELINES.md +0 -0
  51. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/hunts/H-0001.md +0 -0
  52. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/hunts/H-0002.md +0 -0
  53. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/hunts/H-0003.md +0 -0
  54. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/hunts/README.md +0 -0
  55. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/integrations/MCP_CATALOG.md +0 -0
  56. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/integrations/README.md +0 -0
  57. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/integrations/quickstart/splunk.md +0 -0
  58. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/knowledge/hunting-knowledge.md +0 -0
  59. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/setup.cfg +0 -0
  60. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/setup.py +0 -0
  61. {agentic_threat_hunting_framework-0.2.0 → agentic_threat_hunting_framework-0.2.2}/templates/HUNT_LOCK.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-threat-hunting-framework
3
- Version: 0.2.0
3
+ Version: 0.2.2
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-threat-hunting-framework
3
- Version: 0.2.0
3
+ Version: 0.2.2
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,3 +1,3 @@
1
1
  """Version information for ATHF."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"
@@ -197,7 +197,7 @@ def _build_context(
197
197
 
198
198
  def _read_and_optimize(file_path: Path) -> str:
199
199
  """Read file and optimize for token efficiency."""
200
- content = file_path.read_text()
200
+ content = file_path.read_text(encoding='utf-8')
201
201
 
202
202
  # First pass: Remove all control characters except tabs and newlines
203
203
  # Control characters are U+0000 through U+001F (0-31), except tab (9), LF (10), CR (13)
@@ -234,7 +234,7 @@ def _find_hunts_by_tactic(tactic: str) -> List[Path]:
234
234
  normalized_tactic = tactic.replace("-", " ").lower()
235
235
 
236
236
  for hunt_file in hunts_dir.glob("H-*.md"):
237
- content = hunt_file.read_text()
237
+ content = hunt_file.read_text(encoding='utf-8')
238
238
 
239
239
  # Check YAML frontmatter for tactics field
240
240
  if content.startswith("---"):
@@ -263,7 +263,7 @@ def _find_hunts_by_platform(platform: str) -> List[Path]:
263
263
  normalized_platform = platform.lower()
264
264
 
265
265
  for hunt_file in hunts_dir.glob("H-*.md"):
266
- content = hunt_file.read_text()
266
+ content = hunt_file.read_text(encoding='utf-8')
267
267
 
268
268
  # Check YAML frontmatter for platform field
269
269
  if content.startswith("---"):
@@ -3,6 +3,7 @@
3
3
  import subprocess # nosec B404
4
4
  import sys
5
5
  from pathlib import Path
6
+ from typing import Union
6
7
 
7
8
  import click
8
9
  from rich.console import Console
@@ -280,7 +281,7 @@ def info() -> None:
280
281
 
281
282
  # Get installed packages count
282
283
  pip_path = python_path.parent / "pip"
283
- package_count: int | str
284
+ package_count: Union[int, str]
284
285
  try:
285
286
  result = subprocess.run(
286
287
  [str(pip_path), "list", "--format", "freeze"],
@@ -3,7 +3,7 @@
3
3
  import json
4
4
  from datetime import datetime
5
5
  from pathlib import Path
6
- from typing import Optional
6
+ from typing import List, Optional, Tuple
7
7
 
8
8
  import click
9
9
  import yaml
@@ -82,8 +82,8 @@ def new(
82
82
  title: Optional[str],
83
83
  investigation_type: Optional[str],
84
84
  tags: Optional[str],
85
- data_source: tuple[str, ...],
86
- related_hunt: tuple[str, ...],
85
+ data_source: Tuple[str, ...],
86
+ related_hunt: Tuple[str, ...],
87
87
  investigator: Optional[str],
88
88
  non_interactive: bool,
89
89
  ) -> None:
@@ -200,9 +200,9 @@ def _render_investigation_template(
200
200
  title: str,
201
201
  investigator: str,
202
202
  investigation_type: str,
203
- tags: list[str],
204
- data_sources: list[str],
205
- related_hunts: list[str],
203
+ tags: List[str],
204
+ data_sources: List[str],
205
+ related_hunts: List[str],
206
206
  ) -> str:
207
207
  """Render investigation template with provided values.
208
208
 
@@ -569,8 +569,8 @@ def validate(investigation_id: str) -> None:
569
569
  def promote(
570
570
  investigation_id: str,
571
571
  technique: Optional[str],
572
- tactic: tuple[str, ...],
573
- platform: tuple[str, ...],
572
+ tactic: Tuple[str, ...],
573
+ platform: Tuple[str, ...],
574
574
  status: str,
575
575
  non_interactive: bool,
576
576
  ) -> None:
@@ -121,7 +121,7 @@ def _get_hunt_text(hunt_id: str) -> Optional[str]:
121
121
  hunt_file = Path(f"hunts/{hunt_id}.md")
122
122
  if not hunt_file.exists():
123
123
  return None
124
- return hunt_file.read_text()
124
+ return hunt_file.read_text(encoding='utf-8')
125
125
 
126
126
 
127
127
  def _find_similar_hunts(
@@ -132,8 +132,8 @@ def _find_similar_hunts(
132
132
  ) -> List[Dict[str, Any]]:
133
133
  """Find similar hunts using TF-IDF similarity."""
134
134
  try:
135
- from sklearn.feature_extraction.text import TfidfVectorizer # type: ignore
136
- from sklearn.metrics.pairwise import cosine_similarity # type: ignore
135
+ from sklearn.feature_extraction.text import TfidfVectorizer
136
+ from sklearn.metrics.pairwise import cosine_similarity
137
137
  except ImportError:
138
138
  console.print("[red]Error: scikit-learn not installed[/red]")
139
139
  console.print("[dim]Install with: pip install scikit-learn[/dim]")
@@ -156,7 +156,7 @@ def _find_similar_hunts(
156
156
  if exclude_hunt and hunt_id == exclude_hunt:
157
157
  continue
158
158
 
159
- content = hunt_file.read_text()
159
+ content = hunt_file.read_text(encoding='utf-8')
160
160
  metadata = _extract_hunt_metadata(content)
161
161
 
162
162
  # Extract searchable text (weighted semantic sections)
@@ -4,9 +4,20 @@ This module contains reference data for the MITRE ATT&CK Enterprise matrix,
4
4
  including tactic ordering and technique counts.
5
5
  """
6
6
 
7
+ from typing import Dict, List, TypedDict
8
+
9
+
10
+ class TacticInfo(TypedDict):
11
+ """Type definition for tactic information."""
12
+
13
+ name: str
14
+ technique_count: int
15
+ order: int
16
+
17
+
7
18
  # MITRE ATT&CK Enterprise Matrix v14 (January 2024)
8
19
  # Approximate technique counts per tactic (includes sub-techniques)
9
- ATTACK_TACTICS = {
20
+ ATTACK_TACTICS: Dict[str, TacticInfo] = {
10
21
  "reconnaissance": {
11
22
  "name": "Reconnaissance",
12
23
  "technique_count": 10,
@@ -92,7 +103,9 @@ def get_tactic_display_name(tactic_key: str) -> str:
92
103
  Returns:
93
104
  Display name (e.g., "Credential Access")
94
105
  """
95
- return ATTACK_TACTICS.get(tactic_key, {}).get("name", tactic_key.replace("-", " ").title())
106
+ if tactic_key in ATTACK_TACTICS:
107
+ return ATTACK_TACTICS[tactic_key]["name"]
108
+ return tactic_key.replace("-", " ").title()
96
109
 
97
110
 
98
111
  def get_tactic_technique_count(tactic_key: str) -> int:
@@ -104,10 +117,12 @@ def get_tactic_technique_count(tactic_key: str) -> int:
104
117
  Returns:
105
118
  Total technique count for the tactic
106
119
  """
107
- return ATTACK_TACTICS.get(tactic_key, {}).get("technique_count", 0)
120
+ if tactic_key in ATTACK_TACTICS:
121
+ return ATTACK_TACTICS[tactic_key]["technique_count"]
122
+ return 0
108
123
 
109
124
 
110
- def get_sorted_tactics() -> list[str]:
125
+ def get_sorted_tactics() -> List[str]:
111
126
  """Get all tactic keys sorted by ATT&CK matrix order.
112
127
 
113
128
  Returns:
@@ -2,7 +2,7 @@
2
2
 
3
3
  import re
4
4
  from pathlib import Path
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any, Dict, List, Optional, Set
6
6
 
7
7
  from athf.core.attack_matrix import ATTACK_TACTICS, TOTAL_TECHNIQUES, get_sorted_tactics
8
8
  from athf.core.hunt_parser import parse_hunt_file
@@ -261,7 +261,7 @@ class HuntManager:
261
261
  "total_techniques": ATTACK_TACTICS[tactic_key]["technique_count"],
262
262
  }
263
263
 
264
- all_unique_techniques: set[str] = set()
264
+ all_unique_techniques: Set[str] = set()
265
265
 
266
266
  for hunt in hunts:
267
267
  hunt_id = hunt.get("hunt_id", "UNKNOWN")
@@ -8,7 +8,7 @@ Investigation parser is simpler than hunt parser:
8
8
 
9
9
  import re
10
10
  from pathlib import Path
11
- from typing import Any, Dict, List
11
+ from typing import Any, Dict, List, Tuple
12
12
 
13
13
  import yaml
14
14
 
@@ -85,7 +85,7 @@ class InvestigationParser:
85
85
 
86
86
  return content_without_fm.strip()
87
87
 
88
- def validate(self) -> tuple[bool, List[str]]:
88
+ def validate(self) -> Tuple[bool, List[str]]:
89
89
  """Validate investigation structure.
90
90
 
91
91
  Lightweight validation - only checks minimal required fields.
@@ -140,7 +140,7 @@ def parse_investigation_file(file_path: Path) -> Dict[str, Any]:
140
140
  return parser.parse()
141
141
 
142
142
 
143
- def validate_investigation_file(file_path: Path) -> tuple[bool, List[str]]:
143
+ def validate_investigation_file(file_path: Path) -> Tuple[bool, List[str]]:
144
144
  """Convenience function to validate an investigation file.
145
145
 
146
146
  Args:
@@ -25,6 +25,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
25
25
  ### Security
26
26
  - None
27
27
 
28
+ ## [0.2.2] - 2024-12-17
29
+
30
+ ### Fixed
31
+ - Type errors in `athf/core/attack_matrix.py` (added TypedDict for proper mypy checking)
32
+ - Python 3.8 compatibility: `list[str]` → `List[str]` in `athf/core/attack_matrix.py`
33
+ - Python 3.8 compatibility: `tuple[...]` → `Tuple[...]` in `athf/core/investigation_parser.py`
34
+ - Python 3.8 compatibility: `tuple[...]`, `list[str]` → `Tuple[...]`, `List[str]` in `athf/commands/investigate.py`
35
+ - Python 3.8 compatibility: `set[str]` → `Set[str]` in `athf/core/hunt_manager.py`
36
+ - Python 3.8 compatibility: `int | str` → `Union[int, str]` in `athf/commands/env.py`
37
+ - Windows UTF-8 encoding errors in `athf/commands/context.py` (3 instances) and `athf/commands/similar.py` (2 instances)
38
+ - Test assertion errors in `tests/commands/test_env.py` for env info and activate commands
39
+ - Mypy unused-ignore errors in `athf/commands/similar.py` (sklearn imports handled by --ignore-missing-imports flag)
40
+ - CI/CD pipeline errors blocking builds on Python 3.8-3.12 across all platforms
41
+
42
+ ## [0.2.1] - 2024-12-17
43
+
44
+ ### Fixed
45
+ - Type errors in `athf/core/attack_matrix.py` (added TypedDict for proper mypy checking)
46
+ - Python 3.8 compatibility: `list[str]` → `List[str]` in `athf/core/attack_matrix.py`
47
+ - Python 3.8 compatibility: `tuple[...]` → `Tuple[...]` in `athf/core/investigation_parser.py`
48
+ - Python 3.8 compatibility: `tuple[...]`, `list[str]` → `Tuple[...]`, `List[str]` in `athf/commands/investigate.py`
49
+ - Python 3.8 compatibility: `set[str]` → `Set[str]` in `athf/core/hunt_manager.py`
50
+ - Python 3.8 compatibility: `int | str` → `Union[int, str]` in `athf/commands/env.py`
51
+ - Windows UTF-8 encoding errors in `athf/commands/context.py` (3 instances) and `athf/commands/similar.py` (2 instances)
52
+ - Test assertion errors in `tests/commands/test_env.py` for env info and activate commands
53
+ - Mypy unused-ignore errors in `athf/commands/similar.py` (sklearn imports handled by --ignore-missing-imports flag)
54
+ - CI/CD pipeline errors blocking builds on Python 3.8-3.12 across all platforms
55
+
28
56
  ## [0.2.0] - 2024-12-17
29
57
 
30
58
  ### Added
@@ -148,7 +148,7 @@ edr: crowdstrike
148
148
  hunt_prefix: H
149
149
  retention_days: 90
150
150
  initialized: 2025-12-02T14:30:00
151
- version: 0.2.0
151
+ version: 0.2.1
152
152
  ```
153
153
 
154
154
  ### Exit Codes
@@ -237,7 +237,7 @@ Virtual Environment Info:
237
237
  Location: /path/to/.venv
238
238
  Python: Python 3.11.5
239
239
  Packages: 42 installed
240
- athf: ✓ Installed (version 0.2.0)
240
+ athf: ✓ Installed (version 0.2.1)
241
241
  scikit-learn: ✓ Installed (required for athf similar)
242
242
  ```
243
243
 
@@ -1658,7 +1658,7 @@ retention_days: 90
1658
1658
 
1659
1659
  # Metadata (auto-generated)
1660
1660
  initialized: 2025-12-02T14:30:00
1661
- version: 0.2.0
1661
+ version: 0.2.1
1662
1662
  ```
1663
1663
 
1664
1664
  ### Environment Variables
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agentic-threat-hunting-framework"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Agentic Threat Hunting Framework - Memory and AI for threat hunters"
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  requires-python = ">=3.8"