Loading...
Loading...
Guardian is an AI-powered penetration testing automation CLI that leverages multiple AI providers (OpenAI, Claude, Gemini) and 19+ security tools to orchestrate intelligent, step-by-step penetration testing workflows with comprehensive evidence capture.
npx skill4agent add aradotso/devtools-skills guardian-ai-pentest-cliSkill by ara.so — Devtools Skills collection.
# Clone the repository
git clone https://github.com/zakirkun/guardian-cli.git
cd guardian-cli
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: .\venv\Scripts\activate
# Install Guardian
pip install -e .
# Verify installation
python -m cli.main --help# OpenAI (recommended)
export OPENAI_API_KEY="sk-your-key-here"
# Or Anthropic Claude
export ANTHROPIC_API_KEY="sk-ant-your-key-here"
# Or Google Gemini
export GOOGLE_API_KEY="your-gemini-key"
# Or OpenRouter
export OPENROUTER_API_KEY="your-router-key"config/guardian.yaml# config/guardian.yaml
ai:
provider: openai # openai, claude, gemini, openrouter
openai:
model: gpt-4o
api_key: null # Uses OPENAI_API_KEY env var
claude:
model: claude-3-5-sonnet-20241022
api_key: null # Uses ANTHROPIC_API_KEY env var
gemini:
model: gemini-2.5-pro
api_key: null # Uses GOOGLE_API_KEY env var
temperature: 0.2
max_tokens: 8000
pentest:
safe_mode: true # Prevent destructive actions
require_confirmation: true # Confirm before each step
max_parallel_tools: 3 # Concurrent tool execution
max_depth: 3 # Maximum scan depth
tool_timeout: 300 # Tool timeout in seconds
output:
format: markdown # markdown, html, json
save_path: ./reports
include_reasoning: true
verbosity: normal # quiet, normal, verbose, debug
scope:
blacklist: # Never scan these networks
- 127.0.0.0/8
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
require_scope_file: false
max_targets: 100
tools:
httpx:
threads: 50
timeout: 10
tech_detect: true
nuclei:
severity: ["critical", "high", "medium"]
templates_path: ~/nuclei-templates
nmap:
default_args: "-sV -sC"
rate: 1000# List all available workflows
python -m cli.main workflow list
# Run a specific workflow
python -m cli.main workflow run --name web_pentest --target example.com
# Run with custom AI provider
python -m cli.main workflow run --name network --target 192.168.1.0/24 --provider claude
# Run with confirmation disabled for automation
python -m cli.main workflow run --name recon --target example.com --no-confirm# List available AI providers and models
python -m cli.main models
# Test AI provider connection
python -m cli.main models --provider openai# Generate report from session (Markdown)
python -m cli.main report --session 20260203_175905 --format markdown
# Generate HTML report with evidence
python -m cli.main report --session 20260203_175905 --format html
# Generate JSON report for parsing
python -m cli.main report --session 20260203_175905 --format json
# List all sessions
python -m cli.main sessions listpython -m cli.main workflow run --name web_pentest --target https://example.compython -m cli.main workflow run --name network --target 192.168.1.0/24python -m cli.main workflow run --name recon --target example.compython -m cli.main workflow run --name autonomous --target example.comconfig/workflows/# config/workflows/my_custom_workflow.yaml
name: my_custom_workflow
description: Custom security assessment workflow
version: 1.0.0
metadata:
author: Security Team
tags:
- custom
- web
- api
parameters:
# These override config defaults
httpx:
threads: 100
timeout: 15
nuclei:
severity: ["critical", "high"]
rate_limit: 150
steps:
- name: http_discovery
tool: httpx
description: Discover live HTTP services
parameters:
tech_detect: true
status_code: true
- name: vulnerability_scan
tool: nuclei
description: Scan for known vulnerabilities
depends_on:
- http_discovery
parameters:
severity: ["critical", "high"]
- name: api_fuzzing
tool: ffuf
description: Fuzz API endpoints
depends_on:
- http_discovery
parameters:
wordlist: /usr/share/wordlists/api-endpoints.txt
threads: 50
analysis:
focus_areas:
- API security
- Authentication bypass
- Data exposure
severity_threshold: medium
ai_guidance: |
Focus on API-specific vulnerabilities including:
- Broken authentication
- Excessive data exposure
- Lack of rate limiting
- Injection flawspython -m cli.main workflow run --name my_custom_workflow --target api.example.comconfig/tools/# config/tools/my_tool.py
from core.tools.base import BaseTool, ToolResult
from typing import Dict, Any, Optional
import subprocess
import json
class MyCustomTool(BaseTool):
"""Custom security tool integration."""
name = "my_custom_tool"
description = "Performs custom security checks"
category = "web"
def __init__(self):
super().__init__()
self.required_params = ["target"]
self.optional_params = ["timeout", "verbose"]
async def execute(
self,
target: str,
timeout: int = 30,
verbose: bool = False,
**kwargs
) -> ToolResult:
"""Execute the custom tool."""
# Build command
cmd = [
"my-custom-tool",
"--target", target,
"--timeout", str(timeout),
]
if verbose:
cmd.append("--verbose")
try:
# Execute tool
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=timeout,
check=False
)
# Parse output
findings = self._parse_output(result.stdout)
return ToolResult(
success=result.returncode == 0,
output=result.stdout,
error=result.stderr if result.returncode != 0 else None,
data={
"findings": findings,
"target": target,
"exit_code": result.returncode
}
)
except subprocess.TimeoutExpired:
return ToolResult(
success=False,
output="",
error=f"Tool timed out after {timeout} seconds"
)
except Exception as e:
return ToolResult(
success=False,
output="",
error=f"Tool execution failed: {str(e)}"
)
def _parse_output(self, output: str) -> list:
"""Parse tool output into structured findings."""
findings = []
for line in output.splitlines():
if line.strip() and not line.startswith("#"):
findings.append({
"raw": line,
"severity": self._detect_severity(line)
})
return findings
def _detect_severity(self, line: str) -> str:
"""Detect finding severity from output."""
line_lower = line.lower()
if any(word in line_lower for word in ["critical", "severe"]):
return "critical"
elif any(word in line_lower for word in ["high", "important"]):
return "high"
elif any(word in line_lower for word in ["medium", "moderate"]):
return "medium"
else:
return "low"
def validate_params(self, params: Dict[str, Any]) -> tuple[bool, Optional[str]]:
"""Validate tool parameters."""
if "target" not in params:
return False, "Target parameter is required"
target = params["target"]
if not target or not isinstance(target, str):
return False, "Target must be a non-empty string"
return True, Noneconfig/tools/__init__.pyfrom .my_tool import MyCustomTool
__all__ = ["MyCustomTool"]from core.orchestrator import PentestOrchestrator
from core.ai.factory import AIProviderFactory
from core.config import Config
import asyncio
async def run_pentest():
# Load configuration
config = Config.load("config/guardian.yaml")
# Initialize AI provider
ai_provider = AIProviderFactory.create_provider(
provider_type="openai",
config=config.ai
)
# Create orchestrator
orchestrator = PentestOrchestrator(
ai_provider=ai_provider,
config=config
)
# Define target
target = "https://example.com"
# Run workflow
results = await orchestrator.run_workflow(
workflow_name="web_pentest",
target=target,
parameters={
"httpx": {"threads": 100},
"nuclei": {"severity": ["critical", "high"]}
}
)
# Access results
print(f"Total findings: {len(results.findings)}")
for finding in results.findings:
print(f"\n[{finding.severity}] {finding.title}")
print(f"Tool: {finding.tool}")
print(f"Evidence: {finding.evidence[:200]}...")
# Generate report
report = await orchestrator.generate_report(
results=results,
format="markdown"
)
with open("report.md", "w") as f:
f.write(report)
# Run the pentest
asyncio.run(run_pentest())from core.ai.agents import PlannerAgent, ToolSelectorAgent, AnalystAgent
from core.ai.factory import AIProviderFactory
# Initialize AI provider
ai_provider = AIProviderFactory.create_provider("openai")
# Create custom planner agent
planner = PlannerAgent(
ai_provider=ai_provider,
temperature=0.3,
max_tokens=4000
)
# Create plan for target
plan = await planner.create_plan(
target="example.com",
objectives=[
"Identify web technologies",
"Discover subdomains",
"Scan for common vulnerabilities"
],
constraints={
"time_limit": 3600,
"scope": ["*.example.com"],
"exclude_tools": ["sqlmap"]
}
)
# Execute plan steps
for step in plan.steps:
print(f"Step: {step.description}")
print(f"Tool: {step.tool}")
print(f"Parameters: {step.parameters}")from core.reporting import ReportGenerator
from core.evidence import EvidenceCollector
# Initialize evidence collector
evidence_collector = EvidenceCollector()
# Run tool with evidence capture
result = await tool.execute(target="example.com")
# Store evidence
evidence_collector.add_evidence(
tool_name="nuclei",
command="nuclei -u https://example.com -severity critical",
output=result.output,
finding_id="VULN-001"
)
# Generate report with evidence
report_generator = ReportGenerator(evidence_collector)
report = report_generator.generate(
format="html",
include_evidence=True,
include_commands=True
)from core.tools.executor import ToolExecutor
import asyncio
async def parallel_scan(target: str):
executor = ToolExecutor(max_parallel=5)
# Define tasks
tasks = [
executor.execute("httpx", target=target),
executor.execute("whatweb", target=target),
executor.execute("wafw00f", target=target),
executor.execute("nuclei", target=target),
]
# Execute in parallel
results = await asyncio.gather(*tasks, return_exceptions=True)
# Process results
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"Task {i} failed: {result}")
else:
print(f"Task {i} completed: {len(result.findings)} findings")
asyncio.run(parallel_scan("https://example.com"))from core.scope import ScopeValidator
# Initialize validator
validator = ScopeValidator(
blacklist=[
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16"
]
)
# Validate target
is_valid, reason = validator.validate_target("192.168.1.1")
if not is_valid:
print(f"Target rejected: {reason}")
else:
print("Target is in scope")
# Load scope from file
validator.load_scope_file("scope.txt")
# Check if target is in scope
if validator.is_in_scope("example.com"):
# Proceed with scanning
pass# Test AI provider connection
python -m cli.main models --provider openai
# Check API key is set
echo $OPENAI_API_KEY
# Verify configuration
cat config/guardian.yaml | grep -A 5 "ai:"# Check if tool is installed
which nmap
which nuclei
# Verify tool permissions
ls -la $(which nmap)
# Test tool manually
nmap -sV example.com
# Check Guardian logs
tail -f logs/guardian.log# List available workflows
python -m cli.main workflow list
# Check workflow file exists
ls config/workflows/
# Verify workflow YAML syntax
python -c "import yaml; yaml.safe_load(open('config/workflows/web_pentest.yaml'))"# List available sessions
python -m cli.main sessions list
# Check session data exists
ls -la results/sessions/
# Verify report directory permissions
ls -ld reports/
# Generate report with verbose output
python -m cli.main report --session 20260203_175905 --format markdown --verbose# Validate configuration programmatically
from core.config import Config
try:
config = Config.load("config/guardian.yaml")
print("Configuration is valid")
except Exception as e:
print(f"Configuration error: {e}")# config/guardian.yaml - Recommended safety settings
pentest:
safe_mode: true # Prevent destructive actions
require_confirmation: true # Confirm before each step
scope:
blacklist: # Block private networks
- 127.0.0.0/8
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
require_scope_file: true # Require explicit scope file