strix-agent 0.4.0__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.
- strix/__init__.py +0 -0
- strix/agents/StrixAgent/__init__.py +4 -0
- strix/agents/StrixAgent/strix_agent.py +89 -0
- strix/agents/StrixAgent/system_prompt.jinja +404 -0
- strix/agents/__init__.py +10 -0
- strix/agents/base_agent.py +518 -0
- strix/agents/state.py +163 -0
- strix/interface/__init__.py +4 -0
- strix/interface/assets/tui_styles.tcss +694 -0
- strix/interface/cli.py +230 -0
- strix/interface/main.py +500 -0
- strix/interface/tool_components/__init__.py +39 -0
- strix/interface/tool_components/agents_graph_renderer.py +123 -0
- strix/interface/tool_components/base_renderer.py +62 -0
- strix/interface/tool_components/browser_renderer.py +120 -0
- strix/interface/tool_components/file_edit_renderer.py +99 -0
- strix/interface/tool_components/finish_renderer.py +31 -0
- strix/interface/tool_components/notes_renderer.py +108 -0
- strix/interface/tool_components/proxy_renderer.py +255 -0
- strix/interface/tool_components/python_renderer.py +34 -0
- strix/interface/tool_components/registry.py +72 -0
- strix/interface/tool_components/reporting_renderer.py +53 -0
- strix/interface/tool_components/scan_info_renderer.py +64 -0
- strix/interface/tool_components/terminal_renderer.py +131 -0
- strix/interface/tool_components/thinking_renderer.py +29 -0
- strix/interface/tool_components/user_message_renderer.py +43 -0
- strix/interface/tool_components/web_search_renderer.py +28 -0
- strix/interface/tui.py +1274 -0
- strix/interface/utils.py +559 -0
- strix/llm/__init__.py +15 -0
- strix/llm/config.py +20 -0
- strix/llm/llm.py +465 -0
- strix/llm/memory_compressor.py +212 -0
- strix/llm/request_queue.py +87 -0
- strix/llm/utils.py +87 -0
- strix/prompts/README.md +64 -0
- strix/prompts/__init__.py +109 -0
- strix/prompts/cloud/.gitkeep +0 -0
- strix/prompts/coordination/root_agent.jinja +41 -0
- strix/prompts/custom/.gitkeep +0 -0
- strix/prompts/frameworks/fastapi.jinja +142 -0
- strix/prompts/frameworks/nextjs.jinja +126 -0
- strix/prompts/protocols/graphql.jinja +215 -0
- strix/prompts/reconnaissance/.gitkeep +0 -0
- strix/prompts/technologies/firebase_firestore.jinja +177 -0
- strix/prompts/technologies/supabase.jinja +189 -0
- strix/prompts/vulnerabilities/authentication_jwt.jinja +147 -0
- strix/prompts/vulnerabilities/broken_function_level_authorization.jinja +146 -0
- strix/prompts/vulnerabilities/business_logic.jinja +171 -0
- strix/prompts/vulnerabilities/csrf.jinja +174 -0
- strix/prompts/vulnerabilities/idor.jinja +195 -0
- strix/prompts/vulnerabilities/information_disclosure.jinja +222 -0
- strix/prompts/vulnerabilities/insecure_file_uploads.jinja +188 -0
- strix/prompts/vulnerabilities/mass_assignment.jinja +141 -0
- strix/prompts/vulnerabilities/open_redirect.jinja +177 -0
- strix/prompts/vulnerabilities/path_traversal_lfi_rfi.jinja +142 -0
- strix/prompts/vulnerabilities/race_conditions.jinja +164 -0
- strix/prompts/vulnerabilities/rce.jinja +154 -0
- strix/prompts/vulnerabilities/sql_injection.jinja +151 -0
- strix/prompts/vulnerabilities/ssrf.jinja +135 -0
- strix/prompts/vulnerabilities/subdomain_takeover.jinja +155 -0
- strix/prompts/vulnerabilities/xss.jinja +169 -0
- strix/prompts/vulnerabilities/xxe.jinja +184 -0
- strix/runtime/__init__.py +19 -0
- strix/runtime/docker_runtime.py +399 -0
- strix/runtime/runtime.py +29 -0
- strix/runtime/tool_server.py +205 -0
- strix/telemetry/__init__.py +4 -0
- strix/telemetry/tracer.py +337 -0
- strix/tools/__init__.py +64 -0
- strix/tools/agents_graph/__init__.py +16 -0
- strix/tools/agents_graph/agents_graph_actions.py +621 -0
- strix/tools/agents_graph/agents_graph_actions_schema.xml +226 -0
- strix/tools/argument_parser.py +121 -0
- strix/tools/browser/__init__.py +4 -0
- strix/tools/browser/browser_actions.py +236 -0
- strix/tools/browser/browser_actions_schema.xml +183 -0
- strix/tools/browser/browser_instance.py +533 -0
- strix/tools/browser/tab_manager.py +342 -0
- strix/tools/executor.py +305 -0
- strix/tools/file_edit/__init__.py +4 -0
- strix/tools/file_edit/file_edit_actions.py +141 -0
- strix/tools/file_edit/file_edit_actions_schema.xml +128 -0
- strix/tools/finish/__init__.py +4 -0
- strix/tools/finish/finish_actions.py +174 -0
- strix/tools/finish/finish_actions_schema.xml +45 -0
- strix/tools/notes/__init__.py +14 -0
- strix/tools/notes/notes_actions.py +191 -0
- strix/tools/notes/notes_actions_schema.xml +150 -0
- strix/tools/proxy/__init__.py +20 -0
- strix/tools/proxy/proxy_actions.py +101 -0
- strix/tools/proxy/proxy_actions_schema.xml +267 -0
- strix/tools/proxy/proxy_manager.py +785 -0
- strix/tools/python/__init__.py +4 -0
- strix/tools/python/python_actions.py +47 -0
- strix/tools/python/python_actions_schema.xml +131 -0
- strix/tools/python/python_instance.py +172 -0
- strix/tools/python/python_manager.py +131 -0
- strix/tools/registry.py +196 -0
- strix/tools/reporting/__init__.py +6 -0
- strix/tools/reporting/reporting_actions.py +63 -0
- strix/tools/reporting/reporting_actions_schema.xml +30 -0
- strix/tools/terminal/__init__.py +4 -0
- strix/tools/terminal/terminal_actions.py +35 -0
- strix/tools/terminal/terminal_actions_schema.xml +146 -0
- strix/tools/terminal/terminal_manager.py +151 -0
- strix/tools/terminal/terminal_session.py +447 -0
- strix/tools/thinking/__init__.py +4 -0
- strix/tools/thinking/thinking_actions.py +18 -0
- strix/tools/thinking/thinking_actions_schema.xml +52 -0
- strix/tools/web_search/__init__.py +4 -0
- strix/tools/web_search/web_search_actions.py +80 -0
- strix/tools/web_search/web_search_actions_schema.xml +83 -0
- strix_agent-0.4.0.dist-info/LICENSE +201 -0
- strix_agent-0.4.0.dist-info/METADATA +282 -0
- strix_agent-0.4.0.dist-info/RECORD +118 -0
- strix_agent-0.4.0.dist-info/WHEEL +4 -0
- strix_agent-0.4.0.dist-info/entry_points.txt +3 -0
strix/interface/cli.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import atexit
|
|
2
|
+
import signal
|
|
3
|
+
import sys
|
|
4
|
+
import threading
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.live import Live
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
|
|
13
|
+
from strix.agents.StrixAgent import StrixAgent
|
|
14
|
+
from strix.llm.config import LLMConfig
|
|
15
|
+
from strix.telemetry.tracer import Tracer, set_global_tracer
|
|
16
|
+
|
|
17
|
+
from .utils import build_final_stats_text, build_live_stats_text, get_severity_color
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def run_cli(args: Any) -> None: # noqa: PLR0915
|
|
21
|
+
console = Console()
|
|
22
|
+
|
|
23
|
+
start_text = Text()
|
|
24
|
+
start_text.append("🦉 ", style="bold white")
|
|
25
|
+
start_text.append("STRIX CYBERSECURITY AGENT", style="bold green")
|
|
26
|
+
|
|
27
|
+
target_text = Text()
|
|
28
|
+
if len(args.targets_info) == 1:
|
|
29
|
+
target_text.append("🎯 Target: ", style="bold cyan")
|
|
30
|
+
target_text.append(args.targets_info[0]["original"], style="bold white")
|
|
31
|
+
else:
|
|
32
|
+
target_text.append("🎯 Targets: ", style="bold cyan")
|
|
33
|
+
target_text.append(f"{len(args.targets_info)} targets\n", style="bold white")
|
|
34
|
+
for i, target_info in enumerate(args.targets_info):
|
|
35
|
+
target_text.append(" • ", style="dim white")
|
|
36
|
+
target_text.append(target_info["original"], style="white")
|
|
37
|
+
if i < len(args.targets_info) - 1:
|
|
38
|
+
target_text.append("\n")
|
|
39
|
+
|
|
40
|
+
results_text = Text()
|
|
41
|
+
results_text.append("📊 Results will be saved to: ", style="bold cyan")
|
|
42
|
+
results_text.append(f"strix_runs/{args.run_name}", style="bold white")
|
|
43
|
+
|
|
44
|
+
note_text = Text()
|
|
45
|
+
note_text.append("\n\n", style="dim")
|
|
46
|
+
note_text.append("⏱️ ", style="dim")
|
|
47
|
+
note_text.append("This may take a while depending on target complexity. ", style="dim")
|
|
48
|
+
note_text.append("Vulnerabilities will be displayed in real-time.", style="dim")
|
|
49
|
+
|
|
50
|
+
startup_panel = Panel(
|
|
51
|
+
Text.assemble(
|
|
52
|
+
start_text,
|
|
53
|
+
"\n\n",
|
|
54
|
+
target_text,
|
|
55
|
+
"\n",
|
|
56
|
+
results_text,
|
|
57
|
+
note_text,
|
|
58
|
+
),
|
|
59
|
+
title="[bold green]🛡️ STRIX PENETRATION TEST INITIATED",
|
|
60
|
+
title_align="center",
|
|
61
|
+
border_style="green",
|
|
62
|
+
padding=(1, 2),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
console.print("\n")
|
|
66
|
+
console.print(startup_panel)
|
|
67
|
+
console.print()
|
|
68
|
+
|
|
69
|
+
scan_config = {
|
|
70
|
+
"scan_id": args.run_name,
|
|
71
|
+
"targets": args.targets_info,
|
|
72
|
+
"user_instructions": args.instruction or "",
|
|
73
|
+
"run_name": args.run_name,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
llm_config = LLMConfig()
|
|
77
|
+
agent_config = {
|
|
78
|
+
"llm_config": llm_config,
|
|
79
|
+
"max_iterations": 300,
|
|
80
|
+
"non_interactive": True,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if getattr(args, "local_sources", None):
|
|
84
|
+
agent_config["local_sources"] = args.local_sources
|
|
85
|
+
|
|
86
|
+
tracer = Tracer(args.run_name)
|
|
87
|
+
tracer.set_scan_config(scan_config)
|
|
88
|
+
|
|
89
|
+
def display_vulnerability(report_id: str, title: str, content: str, severity: str) -> None:
|
|
90
|
+
severity_color = get_severity_color(severity.lower())
|
|
91
|
+
|
|
92
|
+
vuln_text = Text()
|
|
93
|
+
vuln_text.append("🐞 ", style="bold red")
|
|
94
|
+
vuln_text.append("VULNERABILITY FOUND", style="bold red")
|
|
95
|
+
vuln_text.append(" • ", style="dim white")
|
|
96
|
+
vuln_text.append(title, style="bold white")
|
|
97
|
+
|
|
98
|
+
severity_text = Text()
|
|
99
|
+
severity_text.append("Severity: ", style="dim white")
|
|
100
|
+
severity_text.append(severity.upper(), style=f"bold {severity_color}")
|
|
101
|
+
|
|
102
|
+
vuln_panel = Panel(
|
|
103
|
+
Text.assemble(
|
|
104
|
+
vuln_text,
|
|
105
|
+
"\n\n",
|
|
106
|
+
severity_text,
|
|
107
|
+
"\n\n",
|
|
108
|
+
content,
|
|
109
|
+
),
|
|
110
|
+
title=f"[bold red]🔍 {report_id.upper()}",
|
|
111
|
+
title_align="left",
|
|
112
|
+
border_style="red",
|
|
113
|
+
padding=(1, 2),
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
console.print(vuln_panel)
|
|
117
|
+
console.print()
|
|
118
|
+
|
|
119
|
+
tracer.vulnerability_found_callback = display_vulnerability
|
|
120
|
+
|
|
121
|
+
def cleanup_on_exit() -> None:
|
|
122
|
+
tracer.cleanup()
|
|
123
|
+
|
|
124
|
+
def signal_handler(_signum: int, _frame: Any) -> None:
|
|
125
|
+
tracer.cleanup()
|
|
126
|
+
sys.exit(1)
|
|
127
|
+
|
|
128
|
+
atexit.register(cleanup_on_exit)
|
|
129
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
130
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
131
|
+
if hasattr(signal, "SIGHUP"):
|
|
132
|
+
signal.signal(signal.SIGHUP, signal_handler)
|
|
133
|
+
|
|
134
|
+
set_global_tracer(tracer)
|
|
135
|
+
|
|
136
|
+
def create_live_status() -> Panel:
|
|
137
|
+
status_text = Text()
|
|
138
|
+
status_text.append("🦉 ", style="bold white")
|
|
139
|
+
status_text.append("Running penetration test...", style="bold #22c55e")
|
|
140
|
+
status_text.append("\n\n")
|
|
141
|
+
|
|
142
|
+
stats_text = build_live_stats_text(tracer)
|
|
143
|
+
if stats_text:
|
|
144
|
+
status_text.append(stats_text)
|
|
145
|
+
|
|
146
|
+
return Panel(
|
|
147
|
+
status_text,
|
|
148
|
+
title="[bold #22c55e]🔍 Live Penetration Test Status",
|
|
149
|
+
title_align="center",
|
|
150
|
+
border_style="#22c55e",
|
|
151
|
+
padding=(1, 2),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
console.print()
|
|
156
|
+
|
|
157
|
+
with Live(
|
|
158
|
+
create_live_status(), console=console, refresh_per_second=2, transient=False
|
|
159
|
+
) as live:
|
|
160
|
+
stop_updates = threading.Event()
|
|
161
|
+
|
|
162
|
+
def update_status() -> None:
|
|
163
|
+
while not stop_updates.is_set():
|
|
164
|
+
try:
|
|
165
|
+
live.update(create_live_status())
|
|
166
|
+
time.sleep(2)
|
|
167
|
+
except Exception: # noqa: BLE001
|
|
168
|
+
break
|
|
169
|
+
|
|
170
|
+
update_thread = threading.Thread(target=update_status, daemon=True)
|
|
171
|
+
update_thread.start()
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
agent = StrixAgent(agent_config)
|
|
175
|
+
result = await agent.execute_scan(scan_config)
|
|
176
|
+
|
|
177
|
+
if isinstance(result, dict) and not result.get("success", True):
|
|
178
|
+
error_msg = result.get("error", "Unknown error")
|
|
179
|
+
console.print()
|
|
180
|
+
console.print(f"[bold red]❌ Penetration test failed:[/] {error_msg}")
|
|
181
|
+
console.print()
|
|
182
|
+
sys.exit(1)
|
|
183
|
+
finally:
|
|
184
|
+
stop_updates.set()
|
|
185
|
+
update_thread.join(timeout=1)
|
|
186
|
+
|
|
187
|
+
except Exception as e:
|
|
188
|
+
console.print(f"[bold red]Error during penetration test:[/] {e}")
|
|
189
|
+
raise
|
|
190
|
+
|
|
191
|
+
console.print()
|
|
192
|
+
final_stats_text = Text()
|
|
193
|
+
final_stats_text.append("📊 ", style="bold cyan")
|
|
194
|
+
final_stats_text.append("PENETRATION TEST COMPLETED", style="bold green")
|
|
195
|
+
final_stats_text.append("\n\n")
|
|
196
|
+
|
|
197
|
+
stats_text = build_final_stats_text(tracer)
|
|
198
|
+
if stats_text:
|
|
199
|
+
final_stats_text.append(stats_text)
|
|
200
|
+
|
|
201
|
+
final_stats_panel = Panel(
|
|
202
|
+
final_stats_text,
|
|
203
|
+
title="[bold green]✅ Final Statistics",
|
|
204
|
+
title_align="center",
|
|
205
|
+
border_style="green",
|
|
206
|
+
padding=(1, 2),
|
|
207
|
+
)
|
|
208
|
+
console.print(final_stats_panel)
|
|
209
|
+
|
|
210
|
+
if tracer.final_scan_result:
|
|
211
|
+
console.print()
|
|
212
|
+
|
|
213
|
+
final_report_text = Text()
|
|
214
|
+
final_report_text.append("📄 ", style="bold cyan")
|
|
215
|
+
final_report_text.append("FINAL PENETRATION TEST REPORT", style="bold cyan")
|
|
216
|
+
|
|
217
|
+
final_report_panel = Panel(
|
|
218
|
+
Text.assemble(
|
|
219
|
+
final_report_text,
|
|
220
|
+
"\n\n",
|
|
221
|
+
tracer.final_scan_result,
|
|
222
|
+
),
|
|
223
|
+
title="[bold cyan]📊 PENETRATION TEST SUMMARY",
|
|
224
|
+
title_align="center",
|
|
225
|
+
border_style="cyan",
|
|
226
|
+
padding=(1, 2),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
console.print(final_report_panel)
|
|
230
|
+
console.print()
|