pt-workflow

SkillSecurity

Autonomous pentest campaign driver. Runs a scoped engagement end to end with no operator approvals - the deterministic driver (scripts/campaign.py) owns pass state, generates the killchain board from recon, and prints the exact next action (Skill + tool) every turn. Use when starting or resuming a pentest, "run the pt workflow", "work this CIDR/domain", or when handed a client SoW/scope to reach a stated objective or domain admin. Single agent, refuter-verified, wiki-first, tool-first. Deliverable is a client report.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the pt-workflow skill

What this skill tells your AI

The instructions your AI receives, as published by encod3d-sec/torch in skills/workflow/pt-workflow/SKILL.md and read by ahel’s review.

The driver is the plan. Run one command, do exactly what it prints, record the result, repeat. The gates are enforced by scripts/campaign.py; follow its output literally.

The loop

python3 scripts/campaign.py next
python3 scripts/campaign.py note <row> --arsenal <slug>
python3 scripts/campaign.py done <row> --poc <img> --kind req   # | --dead R | --park Q | --find F

Start / resume

  1. python3 scripts/campaign.py init --type pt - validates scope.md + envelope, repairs type/schema. An empty scope.md must be filled from the client SoW first (CIDRs, domains, RoE, lockout policy). The lockout policy and any destructive-op limits live in scope.md, not here.
  2. Passes 1-3 feed state.md - rustscan/nmap/nxc/LDAP/kerbrute/BloodHound per the recon defaults, which yield to scope.md's allowed tooling. Read service output end to end.
  3. python3 scripts/campaign.py board - writes the 4a rows (plus 4b lateral/privesc/DCSync for the pentest approach). Refuses on empty state.
  4. Enter the loop, depth-first, one open row at a time.
  5. When a shell/session lands on a host (reverse shell via vm-scan.sh --win shell, or meterpreter via --win msf), record it: python3 scripts/campaign.py foothold <host> --win shell (or ride it on the closing find with done ... --win). The driver flips that host's state.md row to access=foothold, routes its 4b lateral/privesc rows through vm-rsh --win <win> (persistent session + operator visibility), and prints tmux attach -t <eng> for takeover.

Gates

Same as the shared driver: G1 arsenal-first, G2 skill-first, G3 typed evidence, G8 tool-first. AD attacks route through Skill(hunt-ad); local privesc through Skill(hunt-windows) / Skill(hunt-macos); the driver names which per row.

Autonomy

No approvals. Out-of-envelope work parks to decisions.md; the loop never blocks. A spray is gated by the lockout policy in scope.md (the envelope), never attempted blind. Destructive AD operations (Zerologon and similar) park unless the envelope authorises them.

Model routing

Explicit per-role model assignment (the driver enforces the verifier gate; the rest is operating policy):

  • Main brain - Opus 5 1M: the campaign.py loop, board/state, strategy, Burp/chrome-devtools, finding write-ups. This session.
  • Verifier - Opus (fresh context), MANDATORY: before any CONFIRMED, campaign.py verify <F> prints an Opus refuter prompt; dispatch ONE fresh Opus agent that reads the raw PoC, tries to REFUTE, and writes verdicts/<F>.json. done --find refuses unless that verdict exists, is refuted:false, and cites the finding's PoC (anti-rubber-stamp). Fails CLOSED.
  • RTL - Opus (fresh context): Skill(redteamlead) for direction at a fork or when a vector stalls.
  • Short tasks - Haiku: Skill(wiki-arsenal) deep, Skill(delegate) (mechanical exploit-run), Skill(ingest) recon-parse. Bounded, fully-specified, single-shot ONLY.

The line that keeps quota safety: Haiku is allowed for a bounded single job, never for open-ended parallel hunting.

Manual login / MFA the agent cannot do headlessly (Smart-ID, an SSO/MFA prompt, a CAPTCHA) -> Skill(chrome-devtools-browser): a VISIBLE chromium on the VM desktop (scripts/browser-visible.sh) the operator logs into, driven + observed live via the chrome-devtools MCP to capture the authenticated session + real API calls.

Discipline

  • Do NOT invoke superpowers:brainstorming/writing-plans mid-run; keep no parallel task list.
  • Model routing (see ## Model routing): Opus-1M drives; Haiku for bounded short tasks; the mandatory Opus verifier gates every finding via verdicts/<F>.json. No open-ended hunter fan-out.
  • Load-bearing requests through Burp when reachable; degrade to capture.sh req otherwise.
  • Scope, lockout policy and destructive-op limits come from scope.md.
  • RCE-first: when >1 vector is open, take the one that yields code-exec first - it is the attack vector that carries impact; chase lower-impact classes only after code-exec is ruled out or the objective needs them (the driver ranks code-exec rows first).
  • Read whole, not grep: when a sudoer has no findable password and cron/writable/SUID/group vectors dead-end, READ /etc/pam.d/{sudo,su} + /etc/sudoers.d/* whole - a pam_ssh_agent_auth (hijack a forwarded agent socket -> passwordless sudo), pam_exec, or bare NOPASSWD line IS the vector; read linpeas output WHOLE, a keyword grep skips the tell. See [[linux-privesc]].
  • Long tools: run pspy/linpeas/tcpdump via bash scripts/vm-bg.sh <eng> <win> '<tool>' (stages to /dev/shm, runs in the stabilized shell, --read/--wait 120 the logfile); never hand-roll a backgrounded watcher, and never retry a broken tool pattern >2x - switch method or call Skill(redteamlead).

Close-out

Run the printed chain: Skill(triage) -> Skill(evidence) -> Skill(report) -> Skill(learn). The pentest deliverable is a client report, not a CTF walkthrough. The report generator must run with PATH=/opt/prep_report/.venv/bin:$PATH or every finding loses its severity callout box.

If the driver is unavailable

Manual fallback: read Approach.md, take the top open row for the current host, run its wiki lookup then its hunt skill, capture req evidence, mark [x]; on exhaustion one Deadends.md line + [!].

Signals

GitHub stars
322
Forks
44
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
pt-workflow
Source
github.com/encod3d-sec/torch