Clone git repositories internally (#10)

This commit is contained in:
Ahmed Allam
2025-08-16 15:47:36 -07:00
committed by GitHub
parent 337d64d362
commit ccab853c0f
5 changed files with 143 additions and 5 deletions

View File

@@ -26,8 +26,20 @@ class StrixAgent(BaseAgent):
task_parts = [] task_parts = []
if scan_type == "repository": if scan_type == "repository":
repo_url = target["target_repo"]
cloned_path = target.get("cloned_repo_path")
if cloned_path:
shared_workspace_path = "/shared_workspace"
task_parts.append( task_parts.append(
f"Perform a security assessment of the Git repository: {target['target_repo']}" f"Perform a security assessment of the Git repository: {repo_url}. "
f"The repository has been cloned from '{repo_url}' to '{cloned_path}' "
f"(host path) and then copied to '{shared_workspace_path}' in your environment."
f"Analyze the codebase at: {shared_workspace_path}"
)
else:
task_parts.append(
f"Perform a security assessment of the Git repository: {repo_url}"
) )
elif scan_type == "web_application": elif scan_type == "web_application":

View File

@@ -206,6 +206,27 @@ CRITICAL RULES:
- **ONE AGENT = ONE TASK** - Don't let agents do multiple unrelated jobs - **ONE AGENT = ONE TASK** - Don't let agents do multiple unrelated jobs
- **SPAWN REACTIVELY** - Create new agents based on what you discover - **SPAWN REACTIVELY** - Create new agents based on what you discover
- **ONLY REPORTING AGENTS** can use create_vulnerability_report tool - **ONLY REPORTING AGENTS** can use create_vulnerability_report tool
- **AGENT SPECIALIZATION MANDATORY** - Each agent must be highly specialized with maximum 3 prompt modules
- **NO GENERIC AGENTS** - Avoid creating broad, multi-purpose agents that dilute focus
AGENT SPECIALIZATION EXAMPLES:
GOOD SPECIALIZATION:
- "SQLi Validation Agent" with prompt_modules: sql_injection
- "XSS Discovery Agent" with prompt_modules: xss
- "Auth Testing Agent" with prompt_modules: authentication_jwt, business_logic
- "SSRF + XXE Agent" with prompt_modules: ssrf, xxe, rce (related attack vectors)
BAD SPECIALIZATION:
- "General Web Testing Agent" with prompt_modules: sql_injection, xss, csrf, ssrf, authentication_jwt (too broad)
- "Everything Agent" with prompt_modules: all available modules (completely unfocused)
- Any agent with more than 3 prompt modules (violates constraints)
FOCUS PRINCIPLES:
- Each agent should have deep expertise in 1-3 related vulnerability types
- Agents with single modules have the deepest specialization
- Related vulnerabilities (like SSRF+XXE or Auth+Business Logic) can be combined
- Never create "kitchen sink" agents that try to do everything
REALISTIC TESTING OUTCOMES: REALISTIC TESTING OUTCOMES:
- **No Findings**: Agent completes testing but finds no vulnerabilities - **No Findings**: Agent completes testing but finds no vulnerabilities

View File

@@ -248,6 +248,8 @@ class StrixCLIApp(App): # type: ignore[misc]
if args.target_type == "local_code" and "target_path" in args.target_dict: if args.target_type == "local_code" and "target_path" in args.target_dict:
config["local_source_path"] = args.target_dict["target_path"] config["local_source_path"] = args.target_dict["target_path"]
elif args.target_type == "repository" and "cloned_repo_path" in args.target_dict:
config["local_source_path"] = args.target_dict["cloned_repo_path"]
return config return config

View File

@@ -9,7 +9,9 @@ import logging
import os import os
import secrets import secrets
import shutil import shutil
import subprocess
import sys import sys
import tempfile
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from urllib.parse import urlparse from urllib.parse import urlparse
@@ -204,6 +206,84 @@ def generate_run_name() -> str:
return f"{adj}-{noun}-{number}" return f"{adj}-{noun}-{number}"
def clone_repository(repo_url: str, run_name: str) -> str:
console = Console()
git_executable = shutil.which("git")
if git_executable is None:
raise FileNotFoundError("Git executable not found in PATH")
temp_dir = Path(tempfile.gettempdir()) / "strix_repos" / run_name
temp_dir.mkdir(parents=True, exist_ok=True)
repo_name = Path(repo_url).stem if repo_url.endswith(".git") else Path(repo_url).name
clone_path = temp_dir / repo_name
if clone_path.exists():
shutil.rmtree(clone_path)
try:
with console.status(f"[bold cyan]Cloning repository {repo_name}...", spinner="dots"):
subprocess.run( # noqa: S603
[
git_executable,
"clone",
"--depth=1",
"--no-recurse-submodules",
"--single-branch",
repo_url,
str(clone_path),
],
capture_output=True,
text=True,
check=True,
)
return str(clone_path.absolute())
except subprocess.CalledProcessError as e:
error_text = Text()
error_text.append("", style="bold red")
error_text.append("REPOSITORY CLONE FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append(f"Could not clone repository: {repo_url}\n", style="white")
error_text.append(
f"Error: {e.stderr if hasattr(e, 'stderr') and e.stderr else str(e)}", style="dim red"
)
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX CLONE ERROR",
title_align="center",
border_style="red",
padding=(1, 2),
)
console.print("\n")
console.print(panel)
console.print()
sys.exit(1)
except FileNotFoundError:
error_text = Text()
error_text.append("", style="bold red")
error_text.append("GIT NOT FOUND", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("Git is not installed or not available in PATH.\n", style="white")
error_text.append("Please install Git to clone repositories.\n", style="white")
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX CLONE ERROR",
title_align="center",
border_style="red",
padding=(1, 2),
)
console.print("\n")
console.print(panel)
console.print()
sys.exit(1)
def infer_target_type(target: str) -> tuple[str, dict[str, str]]: def infer_target_type(target: str) -> tuple[str, dict[str, str]]:
if not target or not isinstance(target, str): if not target or not isinstance(target, str):
raise ValueError("Target must be a non-empty string") raise ValueError("Target must be a non-empty string")
@@ -544,16 +624,23 @@ def main() -> None:
if sys.platform == "win32": if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
args = parse_arguments()
check_docker_installed() check_docker_installed()
pull_docker_image() pull_docker_image()
validate_environment() validate_environment()
asyncio.run(warm_up_llm()) asyncio.run(warm_up_llm())
args = parse_arguments()
if not args.run_name: if not args.run_name:
args.run_name = generate_run_name() args.run_name = generate_run_name()
if args.target_type == "repository":
repo_url = args.target_dict["target_repo"]
cloned_path = clone_repository(repo_url, args.run_name)
args.target_dict["cloned_repo_path"] = cloned_path
asyncio.run(run_strix_cli(args)) asyncio.run(run_strix_cli(args))
results_path = Path("agent_runs") / args.run_name results_path = Path("agent_runs") / args.run_name

View File

@@ -80,7 +80,7 @@ Only create a new agent if no existing agent is handling the specific task.</des
<description>Whether the new agent should inherit parent's conversation history and context</description> <description>Whether the new agent should inherit parent's conversation history and context</description>
</parameter> </parameter>
<parameter name="prompt_modules" type="string" required="false"> <parameter name="prompt_modules" type="string" required="false">
<description>Comma-separated list of prompt modules to use for the agent. Most agents should have at least one module in order to be useful. {{DYNAMIC_MODULES_DESCRIPTION}}</description> <description>Comma-separated list of prompt modules to use for the agent (MAXIMUM 3 modules allowed). Most agents should have at least one module in order to be useful. Agents should be highly specialized - use 1-3 related vulnerability modules only. {{DYNAMIC_MODULES_DESCRIPTION}}</description>
</parameter> </parameter>
</parameters> </parameters>
<returns type="Dict[str, Any]"> <returns type="Dict[str, Any]">
@@ -104,6 +104,22 @@ Only create a new agent if no existing agent is handling the specific task.</des
for security vulnerabilities and bypass techniques.</parameter> for security vulnerabilities and bypass techniques.</parameter>
<parameter=name>Auth Specialist</parameter> <parameter=name>Auth Specialist</parameter>
<parameter=prompt_modules>authentication_jwt, business_logic</parameter> <parameter=prompt_modules>authentication_jwt, business_logic</parameter>
</function>
# Example of single-module specialization (most focused)
<function=create_agent>
<parameter=task>Perform comprehensive XSS testing including reflected, stored, and DOM-based
variants across all identified input points.</parameter>
<parameter=name>XSS Specialist</parameter>
<parameter=prompt_modules>xss</parameter>
</function>
# Example of maximum 3 related modules (borderline acceptable)
<function=create_agent>
<parameter=task>Test for server-side vulnerabilities including SSRF, XXE, and potential
RCE vectors in file upload and XML processing endpoints.</parameter>
<parameter=name>Server-Side Attack Specialist</parameter>
<parameter=prompt_modules>ssrf, xxe, rce</parameter>
</function> </function>
</examples> </examples>
</tool> </tool>