Skip to content
BreachPilot

Exploit Agent — Policy (policy.py)

Permission + budgets + tamper-evident audit. 589 lines.

Verified symbols

SymbolKindLineNotes
ExploitPermissionEnum13FULL_ACCESS/APPROVE_ONLY/READ_ONLY
ExploitSettingsdataclass24Budgets + flags; effective_max_* props
ExploitRecorddataclass143prev_hash/hash chain
ExploitPolicyclass277approve_action, record, can_proceed, is_attack_mode
_TOOL_ACTION_CATEGORYdict92Tool → ScopeGate category
_record_chain_hashdef192Canonical JSON sha256 excluding hash
verify_audit_chaindef205Startup verifier; skips MCP unchained rows
EXPLOIT_AUDIT_FILENAMEconst129exploit_audit.jsonl
MAX_INMEMORY_AUDIT_RECORDSconst139500 ring buffer

ExploitPermission (policy.py:13)

ValueStringBehavior
FULL_ACCESSfull_accessAuto-approve after mission-scope check (_enforce_mission_scope); no command-content inspection
APPROVE_ONLYapprove_onlyEvery action prompts operator (ALLOW <host>)
READ_ONLYread_onlyPropose-only (status="proposed", returns False)

Resolution: tools/cli_exploit_settings.py:_resolve_exploit_permission – missing/unknown key → READ_ONLY. Recon always READ_ONLY (cli_exploit_settings.py:157).

ExploitSettings (policy.py:24)

FieldDefaultNotes
permissionAPPROVE_ONLY
attack_modefalseEnables raised budgets
max_commands_per_session50Pre-attack
max_rounds30Pre-attack
attack_max_commands150When attack_mode
attack_max_rounds50
attack_max_duration_minutes360Time budget
long_session_enabled / persist_messagesfalse
context_summarize_every10Compaction gap
max_pivot_depth2Unused in policy; enforced in orchestrator
enforce_rate_limittrueScopeGate rate limiter
adaptive_exploits_enabled / max_mutationsfalse / 5
outcome_judgment_flow_afalseOpt-in

Props: preapproved (policy.py:80), effective_max_commands (:84), effective_max_rounds (:87).

ExploitPolicy (policy.py:277)

Constructor binds workspace, prompt_func, approval_provider, scope_gate, loads exploit_audit.jsonl tail into _last_hash (_load_last_hash at policy.py:510), verifies chain (verify_audit_chain), sets _locked_ip / _allowed_targets.

MemberLineDescription
approve_action(action, command, detail)368Returns True if approved
record(action, command, ...)477Appends ExploitRecord + hash + JSONL
can_proceed360command_count < effective_max_commands
is_full_access / is_attack_mode356Permission checks
read_audit_records()540Full on-disk read (authoritative)
_load_last_hash()510Seeds chain from existing log
_write_record()535Append JSONL

approve_action flow (policy.py:373):

  1. attack_mode without FULL_ACCESSSECURITY_EVENT warning
  2. !can_proceedstatus="denied" row, False
  3. READ_ONLYstatus="proposed", False
  4. FULL_ACCESS_enforce_mission_scope consults scope_gate (forbidden categories + asset rules; None = permissive); on deny → status="SCOPE_DENIED" row, False; else increment _command_count, True (no command-content inspection)
  5. APPROVE_ONLY → delegate to approval_provider or prompt_func (ALLOW <host>); every denial/abort/budget refusal writes a status="denied" row (_record_denial)

Audit: ring buffer MAX_INMEMORY_AUDIT_RECORDS=500 (policy.py:505); disk JSONL is authoritative.

Hash chain

_record_chain_hash (policy.py:192) = sha256(sorted_json_without_hash). prev_hash links to prior record's hash. verify_audit_chain skips MCP rows without hash (policy.py:237).

_TOOL_ACTION_CATEGORY (policy.py:102)

Maps concrete MCP tools (dump_credentials, kerberoast, lateral_exec, generate_payload, run_exploit_terminal, msf*) to ScopeGate categories (credential_dumping, lateral_movement, payload_generation, exploit_execution). Category names intentionally absent from scope_gate._HARD_FORBIDDEN_SUBSTRINGS so full_access keeps them available; operator opts out via exploit.forbidden_actions.

Config keys

KeyEffect
exploit.permissionMode
exploit.modeStandalone etc.
exploit.max_commands_per_session / max_rounds / attack_max_*Budgets
exploit.forbidden_actionsCategory deny via _TOOL_ACTION_CATEGORY
exploit.allowed_targets / require_explicit_allowlistAllowlist (checked in MCP layer, not here)
exploit.long_session.*long_session_enabled
exploit.adaptive_exploits_*Mutator
outcome_judgment.flow_aJudge bridge

Tests

FileVerifiedCovers
tests/test_exploit_permission.pyyesPermission matrix
tests/test_exploit_scope_gate.pyyesMission-gate enforcement (SCOPE_DENIED) + rate limit via policy
tests/test_approval_denial_audit.pyyesDenial rows + chain integrity for every deny exit
tests/test_exploit_action_category.pyyes_TOOL_ACTION_CATEGORY
tests/test_audit_chain.pyyesHash chain + tamper detection
tests/test_audit_memory_bound.pyyes500 ring buffer
tests/test_audit_redaction.pyyesRedaction in MCP audit rows
tests/test_tool_outcome_tracker.pyyes_ToolOutcomeTracker
source: repo docs (build sync)Edit this page on GitHub →