Skip to content

Configuration

blackbuble edited this page Oct 30, 2026 · 1 revision

Complete Configuration

All PentestAI settings and how to change them.

Docker is the supported runtime. install.sh is Docker-only by default; set PENTESTAI_ALLOW_LOCAL_TOOLS=1 only for the legacy bare-metal install.


config/settings.py — Full Reference

Setting Default Env Var Description
ANTHROPIC_API_KEY "" ANTHROPIC_API_KEY Anthropic API key
ANTHROPIC_MODEL claude-sonnet-4-6 ANTHROPIC_MODEL Default model
SESSIONS_DIR ./sessions/ — Session files directory
LOGS_DIR ./logs/ — Audit logs directory
REPORTS_DIR ./reports/output/ — Report output directory
MAX_AUTO_ITERATIONS 20 — Max autonomous iterations (SkillMode caps: junior 15, mid 12, advanced 20)
TOOL_TIMEOUT 120 — Tool timeout (seconds)
LLM_MAX_TOKENS 4096 — Max tokens per LLM request
LLM_TEMPERATURE 0.2 — LLM temperature
NVD_TIMEOUT 5 NVD_TIMEOUT NVD request timeout (seconds); offline CVE bundle is used first
HIGH_RISK_ACTIONS {sqlmap,nikto,brute_force,exploit} — Actions that require confirmation
SKILL_MODE junior PENTESTAI_MODE Active skill mode (junior/mid/advanced)
PENTESTAI_MAX_SECONDS 0 (unlimited) PENTESTAI_MAX_SECONDS Wall-clock budget for the ReAct loop
PENTESTAI_MAX_TOKENS 0 (unlimited) PENTESTAI_MAX_TOKENS Approximate token budget (4 chars ≈ 1 token)
PENTESTAI_REQUIRE_FLAG 0 PENTESTAI_REQUIRE_FLAG Force the flag-evidence stop guard even when the objective does not mention a flag
REPORT_AUTHOR PentestAI REPORT_AUTHOR Name in reports
REPORT_COMPANY Security Assessment REPORT_COMPANY Company in reports
APP_VERSION 0.1.0 — Application version
EVIDENCE_DIR reports/evidence/ — PoC evidence files directory

SkillMode — Level Adaptation System

PENTESTAI_MODE=junior|mid|advanced or mode junior from inside the shell.

Setting Junior Mid Advanced
Verbose output ✅ every iteration ✅ ❌ findings only
Phase gates ✅ ask before transition ❌ ❌
RAG enrichment ✅ CVE context ✅ ❌ skip
AutoPlanner ✅ auto-generate ❌ ask first ❌ ask first
Scanner explain ✅ show payload ✅ ❌ raw output
Notifications ✅ ❌ ❌
Max ReAct iterations 15 12 20
Default autonomy semi_auto semi_auto autonomous
from config.settings import SkillMode, mode_cfg, SKILL_MODE

# Read the current config
verbose = mode_cfg("react_verbose")   # True/False
max_iter = mode_cfg("max_react_iterations")  # int

EngagementBrief — Per-Client Guardrail

Set at the start of every engagement to enforce client-specific rules:

from memory.session import EngagementBrief

brief = EngagementBrief(
    client_name="AcmeCorp",
    engagement_type="external",      # external/internal/red_team/web_app
    no_brute_force=True,             # block hydra/kerberoast/cred_spray
    no_dos=True,                     # always True unless explicitly disallowed
    notify_before_exploit=True,      # warning before exploit action
    production_systems=["10.0.0.1"], # block direct actions on prod
    emergency_contact="08xx-xxxx",
    reporting_deadline="2026-12-01",
)
session.set_brief(brief)

# Automatic enforcement in PermissionGate
allowed, msg = session.check_action_brief("hydra", "10.0.0.1")
# → (False, "Brute force prohibited...")

CLI: brief set (interactive wizard), brief no-brute-force, brief production <ip>


.env File — All Variables

# ════ LLM PROVIDERS ════
ANTHROPIC_API_KEY=          # required if using Anthropic
ANTHROPIC_MODEL=claude-sonnet-4-6
OPENAI_API_KEY=             # optional
GROQ_API_KEY=               # optional, cheap fast tasks
GOOGLE_API_KEY=             # Gemini
MISTRAL_API_KEY=            # Mistral AI
XAI_API_KEY=                # xAI Grok
DEEPSEEK_API_KEY=           # DeepSeek, very cheap
TOGETHER_API_KEY=           # Together AI, open-source models
PERPLEXITY_API_KEY=         # Perplexity, online models
COHERE_API_KEY=             # Cohere
OPENROUTER_API_KEY=         # 100+ models via a single key
AZURE_OPENAI_API_KEY=       # Azure OpenAI (also requires ENDPOINT)
AZURE_OPENAI_ENDPOINT=      # https://your-resource.openai.azure.com
AZURE_OPENAI_DEPLOYMENT=    # deployment name (default: gpt-4o)
NINEROUTER_API_KEY=         # 9router local gateway

# Custom OpenAI-compatible endpoint (WorkBuddy, LM Studio, vLLM, etc.)
CUSTOM_LLM_BASE_URL=
CUSTOM_LLM_API_KEY=
CUSTOM_LLM_MODEL=
CUSTOM_LLM_NAME=
CUSTOM_LLM_TIER=all

# Ollama (local, no API key)
OLLAMA_BASE_URL=http://localhost:11434

# ════ SKILL MODE ════
PENTESTAI_MODE=junior        # junior | mid | advanced (default: junior)

# ════ RUN BUDGET (0 = unlimited) ════
PENTESTAI_MAX_SECONDS=0       # wall-clock limit for the ReAct loop
PENTESTAI_MAX_TOKENS=0        # approximate token limit (4 chars ≈ 1 token)
PENTESTAI_LLM_STEP_TIMEOUT=60 # hard ceiling for one reasoning call (seconds)
PENTESTAI_MAX_RECON_STEPS=4   # scanner actions before the M3 pivot guard blocks them
PENTESTAI_REQUIRE_FLAG=0      # 1 = reject `done` until a flag is captured (auto-on for flag objectives)
PENTESTAI_BENCH_HARD_GRACE=30 # benchmark-only: exit after max_seconds + grace
PENTESTAI_STRATEGY=1          # 1 = retrieve/store generic strategy lessons
PENTESTAI_BUDGET_PROFILE=benchmark # benchmark | engagement
PENTESTAI_IDLE_TIMEOUT=120    # engagement only: stop after no new progress
PENTESTAI_MAX_EXTENSIONS=2    # engagement only: max +60s extensions
PENTESTAI_EXTENSION_SECONDS=60 # engagement only: extension size

# ════ AGENT LLM CALLS (M1: off by default = 1 call/step) ════
PENTESTAI_LLM_ANALYSIS=0     # 1 = extra per-step output analysis
PENTESTAI_LLM_FINDINGS=0     # 1 = LLM finding extraction (adds candidates)
PENTESTAI_NATIVE_TOOLS=1     # 1 = native tool calling, 0 = JSON plan
PENTESTAI_AUTO_LOGIN=0       # 1 = auto-submit login form when detected
PENTESTAI_AUTO_IDOR=0        # 1 = probe IDOR after a successful login
PENTESTAI_AUTO_EXPLOIT=0     # 1 = probe forms for SSTI / command injection
PENTESTAI_AUTO_JWT=0         # 1 = test JWT weaknesses and forge claims
PENTESTAI_AUTO_MONGO=0       # 1 = predict Mongo ObjectIds from timestamps
PENTESTAI_AUTO_PRIV=0        # 1 = probe privilege-escalation paths
PENTESTAI_AUTO_SSRF=0        # 1 = run the verified form-SSRF chain after a URL field
PENTESTAI_EXPERIENCE=1       # 1 = inject generic cross-run lessons (0 = off)
PENTESTAI_LOGIN_EMAIL=       # single credential for auto-login
PENTESTAI_LOGIN_PASSWORD=
# Or a JSON list (max 3 attempts), e.g. [["admin","password"],["test","test"]]
PENTESTAI_LOGIN_CREDENTIALS=

# ════ TOOLS (optional, if not on PATH) ════
NMAP_PATH=nmap
GOBUSTER_PATH=gobuster
SQLMAP_PATH=sqlmap
NIKTO_PATH=nikto
PENTESTAI_LHOST=             # override LHOST for MSF reverse shells

# ════ TOOL INTEGRATIONS (optional) ════
MSF_HOST=127.0.0.1
MSF_PORT=55553
MSF_PASSWORD=msfrpc
BURP_API_URL=http://localhost:8090
BURP_API_KEY=

# ════ MCP SERVERS (opsional) ════
# JSON array; servers start on first use.
PENTESTAI_MCP_SERVERS=

# ════ CVE / NVD ════
NVD_API_KEY=                 # optional, increases the NVD rate limit
NVD_TIMEOUT=5                # offline bundle is still used first

# ════ REPORT ════
REPORT_AUTHOR=Security Assessor
REPORT_COMPANY=Your Company

# ════ API SERVER ════
API_HOST=127.0.0.1
API_PORT=8080

# ════ TEST TARGET (web app engagements only) ════
TEST_LOGIN_URL=
TEST_LOGIN_EMAIL_FIELD=      # NAME of the HTML field, not an email address
TEST_LOGIN_PASS_FIELD=
TEST_ACCOUNT_A_EMAIL=
TEST_ACCOUNT_A_PASS=
TEST_ACCOUNT_B_EMAIL=
TEST_ACCOUNT_B_PASS=
TEST_TENANT_A=
TEST_TENANT_B=
TEST_OBJECT_ID=
TEST_OBJECT_TYPE=

How .env gets into the container

Mode Mechanism
Bare metal python-dotenv (load_dotenv()) reads .env in the project root
docker run --env-file .env
docker compose env_file: .env in the pentestai service + ${VAR} interpolation in the environment: block

docker-compose.yml defines env_file: .env, so all the variables above get into the container — not just the handful of keys explicitly listed in environment:.

.env is never included in the image: .dockerignore excludes .env, .env.*, and *.env.local. Do not remove those entries.

Verify from inside the container:

docker compose exec -T pentestai sh -c 'env | grep -cE "^(ANTHROPIC|OPENAI|GROQ|GOOGLE|DEEPSEEK|PENTESTAI|REPORT|TEST)_"'
# 35 (= number of relevant variables injected)

Parameters that are still empty

scripts/env_test.py will flag empty parameters as FAIL. That condition is not a container bug — the values simply have not been filled in .env yet. Providers with empty keys are automatically skipped by build_router_from_env().

Baseline 2026-10-20 (only Anthropic filled in; Ollama was later verified locally on 2026-10-24):

Empty Impact
OPENAI_API_KEY, XAI_API_KEY, MISTRAL_API_KEY, DEEPSEEK_API_KEY, GROQ_API_KEY, GOOGLE_API_KEY, PERPLEXITY_API_KEY, COHERE_API_KEY, TOGETHER_API_KEY, OPENROUTER_API_KEY The relevant provider is inactive; routing goes only to Anthropic
AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT Azure OpenAI is inactive
TEST_TENANT_A, TEST_TENANT_B, TEST_OBJECT_ID Multi-tenant test metadata is incomplete

After filling in keys: docker compose up -d pentestai (the container is recreated and reads env_file again), then run the smoke test again.

⚠️ TEST_LOGIN_EMAIL_FIELD / TEST_LOGIN_PASS_FIELD must contain the HTML element name (e.g. email, password), not an email address. If both contain the same email, the test login form will not be filled in correctly.


Exploit validation gate

Every new finding starts as candidate. It becomes validated only when there is reproducible evidence:

Evidence Method label
Evidence-vault hash attached evidence_vault
Captured HTTP request and response in evidence http_exchange
Verified PoC (poc verify ...) poc
Benchmark flag FLAG{...} benchmark_flag
Operator approval (validate <id>) operator

A bare curl command is not enough: it shows intent, not proof. It stays a candidate until a response or PoC is attached.

validate                 # re-run the gate over all findings
validate <id>            # approve one finding manually
report sarif             # export validated findings only
report sarif all         # include candidates (marked as such)

Machine-readable output uses SARIF 2.1.0 with validationStatus in result properties. The CI gate (scripts/ci_gate.py) blocks only on validated findings at/above the configured severity.


MCP servers

PentestAI can use external Model Context Protocol servers over stdio. Configure them as a JSON array:

PENTESTAI_MCP_SERVERS=[{"name":"fs","command":["npx","-y","@modelcontextprotocol/server-filesystem","/tmp"]}]

Optional per-server keys: env (object) and timeout (seconds, default 30).

mcp list                 # configured servers and status
mcp tools fs             # tools exposed by one server
mcp call fs read_file '{"path":"/tmp/report.txt"}'
mcp close fs             # stop a server (or all)

Servers start lazily on first use, so a broken server cannot block shell startup. A non-zero server exit or timeout is reported as an error and does not crash the session.


Scope Enforcement + Expansion

from core.scope import ScopeEnforcer

sc = ScopeEnforcer()
sc.add_ip("10.10.11.0/24")
sc.add_ip("10.10.11.100")
sc.add_domain("htb.local")
sc.add_domain("*.htb.local")

# Scope expansion workflow
req = sc.request_expansion("192.168.1.5", "Trust relationship via SMB")
sc.approve_expansion(req.id)   # add to scope, log approved
sc.deny_expansion(req.id)      # log denied, do not add to scope
log = sc.expansion_log()       # audit trail of all requests

CLI: expand <target> <reason> → scope approve <ref> → scope deny <ref>


Valid Provider IDs (15 total)

anthropic · openai · groq · ollama · openrouter · google · mistral · xai · deepseek · together · perplexity · azure · cohere · 9router · custom

Valid Tiers

simple · medium · complex · all


Phase 6 Commands

orchestrate — Multi-agent parallel execution

orchestrate [target] [--seq]

Reads the target from the active session if not provided. The --seq flag for sequential (default: parallel). Skill mode affects this: advanced = no phase gates, junior = ask approval per phase.

ptes — PTES format report

ptes

Output to reports/output/*_ptes.json and *_ptes.md.

iso27001 — ISO 27001 risk register

iso27001

Output to reports/output/*_iso27001.json.

marketplace — Plugin marketplace

marketplace [list|search <q>|install <id>|uninstall <id>|info <id>|installed|fetch]

Plugins are stored in the plugins/ directory. Default registry: github.com/pentestai/marketplace. Override with the MARKETPLACE_REGISTRY_URL env var.

Clone this wiki locally