Skip to content
BreachPilot

Kernel — Overview (tools/kernel/)

Extracted safety/portability shims re-exported by tools/mcp_shared for backwards compatibility (Phase 2 kernel).

Package map

FileLOCRoleRe-export via
allowlist.py238Target-IP allowlist union + extractiontools.mcp_shared._allowed_target_list, _check_allowlist
audit.py374Credential redaction + audit decoratorstools.mcp_shared.make_audit_tool, make_require_allowlist
config.py25YAML load_config(path)tools.mcp_shared / tools.config_cli
workspace.py132Path containment + per-attempt dirstools.mcp_shared._resolve_workspace_file
parse.py15Re-export shimtools.exploit_agent.context._parse_reasoning_block + tool_calls._filter_and_validate_tool_calls

allowlist.py — The ONE attack-mode safety gate (allowlist.py:1, config.yaml:83-86, safety-model.md)

SymbolKindLineDescription
_allowed_target_list(config)def35exploit.allowed_targetsEXPLOIT_TARGET/_IP/_DOMAIN/DISCOVERED_TARGETS env vars (order-preserving dedupe)
_check_allowlist(target_ip, config)def67(allowed, reason); enforces require_explicit_allowlist + is_target_in_allowlist
check_targets_allowlist(targets, config)def101Batch check for multi-target tools
add_discovered_target(host, ip)def55Appends to EXPLOIT_DISCOVERED_TARGETS env
_extract_msf_rhosts(text)def83Regex RHOSTS/RHOST + portfwd/route/autoroute hosts
_extract_scanner_targets(command)def208shlex walk over _SCANNER_VERBS (nmap etc.), skipping _SCANNER_VALUE_FLAGS + _SHELL_SEPARATORS; host-shaped via _scanner_token_is_host
_SCANNER_VERBSconst128{nmap,masscan,rustscan,nikto,nuclei,gobuster,…} 16 verbs
_SCANNER_VALUE_FLAGSconst15327 flags whose value is filename/IP not target

_allowed_target_list is the allowlist union the lab build relies on (sole attack-mode safety when exploit.permission=full_access bypasses policy.py). EXPLOIT_TARGET family threaded by tools/mcp_session.py:255-266 (EXPLOIT_TARGET/_IP/_DOMAIN/DISCOVERED_TARGETS). Matcher tools/validation_utils.is_target_in_allowlist supports domains + *.wildcard + CIDR (validation_utils.py:380-420).

_check_allowlist logic: !require_explicit_allowlist → (True,"allowlist not required"); else if allowed_targets==[] → (False, "empty"); else is_target_in_allowlist(target, allowed) → (True) else (False,"Add it to exploit.allowed_targets").

audit.py — Redaction + decorators (audit.py:1)

SymbolKindLineDescription
_SECRET_ARG_NAMESfrozenset2730 names: password, ntlm_hash, private_key, api_key, creds, …
_REDACTEDconst62"***REDACTED***"
_MASK_REStuple10710 regexes: _MASK_URL_AUTH_RE, _MASK_U_FLAG_RE, _MASK_LONG_PW_RE, _MASK_HYDRA_P_RE, _MASK_MSF_SET_RE, _MASK_HASHES_RE, _MASK_NTLM_FLAG_RE, _MASK_KV_SECRET_RE, _MASK_AUTH_HDR_RE, _MASK_PY_AUTH_TUPLE_RE
_mask_secret_content(value)def123Applies _MASK_RES over string value
_redact_nested(value)def137Dict key redaction + string mask
_redact_args(args)def148Per-arg redaction + _WHOLESALE_REDACT_FIELDS={"input_text","notes"}
_audit_log(audit_path, target_ip, tool_name, approved, status, command, args, attempt_id, code_sha256, duration)def165Append {timestamp,target_ip,tool_name,approved,status,command(mask),args(redacted),…} JSONL
_result_is_blocked(result)def200upper().startswith(("BLOCKED:", "TERMINAL_RESULT: BLOCKED", …))
_extract_audit_target(bound)def208From command/script_content + lhost via _extract_msf_rhosts
make_require_allowlist(workspace, config)def228Factory → require_allowlist(target_param,audit) decorator
make_audit_tool(workspace)def310Factory → audit_tool decorator

Decorators (make_require_allowlist/make_audit_tool):

  • require_allowlist(target_param="target_ip", audit=True) wraps async or sync fn via inspect.signature + functools.wraps; pre-logs status="blocked"|"started" with _redact_args(bound.arguments); on !allowed returns BLOCKED: <reason>\nATTEMPT_ID: preflight\nTOOL: <fn>\nTARGET: <ip> string; post-logs blocked if _result_is_blocked(result). Preserves __wrapped_require_allowlist__ / __wrapped_audit_tool__ flags.
  • audit_tool always logs started then completed|blocked, target from _extract_audit_target(bound).

Lab build: no additional command-content gates; full_access bypass is intentional – allowlist is the lock.

config.py (config.py:11)

def load_config(path: Path) -> dict[str, Any]

Pure: {} if missing, yaml.safe_load + isinstance(dict) check else ValueError. Shared by tools.config_cli, tools.mcp_shared, tools.exploit_session; no global state.

workspace.py (workspace.py:15)

SymbolKindLineDescription
_is_inside_workspace(workspace, target)def15resolved.relative_to(root) or == root, OSError→False
_resolve_workspace_file(workspace, filename, suffix)def35Absolute vs. relative vs. basename → candidate resolve → inside check → is_file && suffixrglob newest mtime fallback → root/safe_name
_find_file(workspace, filename)def88_resolve_workspace_file + exists + inside
_attempt_dir(workspace)def101{workspace}/{YYYYMMDD_HHMMSS_ffffff}_{hex4}/ + mkdir
read_workspace(workspace, filename)def109Operator-box unrestricted read: Path(filename) absolute vs. workspace/ relative, FILE_NOT_FOUND, read_text with 120K truncation

Workspace layout (lab build): exploit_workspace/<ip>/<attempt_id>/ per loop.py via _attempt_dir shape; loot/ subdir under PostExploitAgent. Operator-box FS unrestricted (path-traversal protection removed; allowlist is lock).

parse.py (parse.py:1, shim)

from tools.exploit_agent.context import _parse_reasoning_block
from tools.exploit_agent.tool_calls import _filter_and_validate_tool_calls

No new behavior; single import point for both flows and future loop.py<400 refactor. loop.py:52 still imports from context/tool_calls directly; parse.py is the canonical kernel surface.

Config keys (read by allowlist.py via config dict)

KeyDefaultEffect
exploit.allowed_targets[127.0.0.1] (config.yaml:84)Base allowlist
exploit.require_explicit_allowlisttrue (config.yaml:83)Enforces allowlist
EXPLOIT_TARGET / _IP / _DOMAIN / EXPLOIT_DISCOVERED_TARGETSenv vars (mcp_session.py:255)Runtime union
exploit.workspace_direxploit_workspaceworkspace.py root
exploit.loot_workspaceexploit_workspace/lootLoot dir

No kernel-specific block; kernel reads the same exploit.* keys.

Tests

FileVerifiedCovers
tests/test_domain_allowlist.pyyes_allowed_target_list, CIDR/wildcard/domain matching
tests/test_scanner_target_extraction.pyyes_extract_scanner_targets argv-walk + value-flag skip
tests/test_audit_redaction.pyyes_mask_secret_content, _redact_args, 10 regexes
tests/test_audit_chain.pyyesverify_audit_chain (policy) + kernel audit log append
tests/test_mcp_shared_helpers.pyyesload_config, _extract_msf_rhosts
tests/test_mcp_workspace.pyyes_resolve_workspace_file, _is_inside_workspace, _find_file
tests/test_workspace_binary_write.pyyesread_workspace truncation + binary flag
tests/test_mcp_tool_registration.pyyes@require_allowlist / @audit_tool decorator wiring
tests/test_mcp_tool_scope.pyyesAllowlist gating on target-touching tools
tests/test_validate_target.pyyesis_target_in_allowlist, validate_target, is_fqdn
source: repo docs (build sync)Edit this page on GitHub →