# Guardian AI Pentest CLI

> 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.

- Skill: `aradotso/guardian-ai-pentest-cli` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aradotso/guardian-ai-pentest-cli`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aradotso/guardian-ai-pentest-cli/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: aradotso (https://skillmd.com/u/aradotso)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aradotso/guardian-ai-pentest-cli

---


# Guardian AI Pentest CLI

> Skill by [ara.so](https://ara.so) — Devtools Skills collection.

Guardian is an enterprise-grade AI-powered penetration testing automation framework that combines multiple AI providers (OpenAI GPT-4, Claude, Gemini, OpenRouter) with 19+ battle-tested security tools to deliver intelligent, adaptive security assessments with comprehensive evidence capture. It uses a multi-agent architecture where specialized AI agents (Planner, Tool Selector, Analyst, Reporter) collaborate to conduct penetration tests.

## Installation

### Prerequisites

- Python 3.11 or higher
- AI Provider API Key (OpenAI, Anthropic, Google, or OpenRouter)
- Git

### Setup

```bash
# 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
```

### Environment Variables

Set your AI provider API key:

```bash
# 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"
```

## Configuration

Guardian uses `config/guardian.yaml` for configuration:

```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
```

## Key Commands

### Workflow Management

```bash
# 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
```

### AI Provider Management

```bash
# List available AI providers and models
python -m cli.main models

# Test AI provider connection
python -m cli.main models --provider openai
```

### Report Generation

```bash
# 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 list
```

## Built-in Workflows

Guardian includes several pre-configured workflows:

### 1. Web Penetration Testing
```bash
python -m cli.main workflow run --name web_pentest --target https://example.com
```

**What it does:**
- HTTP probing with httpx
- Technology fingerprinting with WhatWeb
- WAF detection with Wafw00f
- Vulnerability scanning with Nuclei
- Directory enumeration with Gobuster
- Parameter discovery with Arjun
- XSS detection with XSStrike

### 2. Network Assessment
```bash
python -m cli.main workflow run --name network --target 192.168.1.0/24
```

**What it does:**
- Port scanning with Nmap/Masscan
- Service enumeration
- SSL/TLS testing with TestSSL/SSLyze
- Vulnerability assessment

### 3. Reconnaissance
```bash
python -m cli.main workflow run --name recon --target example.com
```

**What it does:**
- Subdomain discovery with Subfinder/Amass
- DNS enumeration with DNSRecon
- HTTP discovery
- Technology mapping

### 4. Autonomous Mode
```bash
python -m cli.main workflow run --name autonomous --target example.com
```

**What it does:**
- AI-driven decision making at each step
- Adaptive testing based on findings
- Dynamic tool selection
- Continuous analysis and pivoting

## Creating Custom Workflows

Workflows are defined in `config/workflows/` as YAML files:

```yaml
# 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 flaws
```

Run your custom workflow:

```bash
python -m cli.main workflow run --name my_custom_workflow --target api.example.com
```

## Creating Custom Tools

Define custom tools in `config/tools/` as Python modules:

```python
# 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, None
```

Register your tool in `config/tools/__init__.py`:

```python
from .my_tool import MyCustomTool

__all__ = ["MyCustomTool"]
```

## Python API Usage

Guardian can be used programmatically:

```python
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())
```

## Advanced Usage Patterns

### Custom AI Agent Configuration

```python
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}")
```

### Evidence-Based Reporting

```python
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
)
```

### Parallel Tool Execution

```python
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"))
```

## Scope Validation

Guardian includes built-in scope validation to prevent unauthorized scanning:

```python
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
```

## Troubleshooting

### AI Provider Issues

```bash
# 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:"
```

### Tool Execution Failures

```bash
# 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
```

### Workflow Not Found

```bash
# 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'))"
```

### Report Generation Issues

```bash
# 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
```

### Configuration Errors

```python
# 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}")
```

## Legal and Ethical Use

**Guardian is designed exclusively for authorized security testing.**

Before using Guardian:

1. Obtain explicit written permission to test the target system
2. Understand applicable laws (CFAA, GDPR, etc.)
3. Configure scope validation to prevent unauthorized scanning
4. Enable safe mode to prevent destructive actions
5. Maintain detailed audit logs

```yaml
# 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
```

**You are fully responsible for ensuring you have authorization before testing any system.**

