network-ops 2.0: multi-agent pipeline + tool gap fills#78
network-ops 2.0: multi-agent pipeline + tool gap fills#78mkultraWasHere wants to merge 8 commits into
Conversation
Decompose the monolithic network-ops-agent into a 6-stage coordinated pipeline following the attack-surface-management pattern. Adds worker coordinator, pipeline launcher tool, methodology and tactical skills, and specialized pipeline agents for each phase of AD exploitation. - Replace single agent with netops-operator (standalone) + 6 pipeline agents (scope-normalizer, discovery-operator, ad-enumerator, exploit-operator, credential-harvester, report-synthesizer) - Add coordinator worker with event-driven orchestration, stage budgets, timeout handling, and deterministic synthesis fallback - Add run_netops_pipeline tool for programmatic pipeline invocation - Add 3 skills: network-ops-methodology (hard rules, confidence levels, anti-patterns), ad-enumeration-playbook (decision tree, tool mapping), ad-attack-patterns (attack chain sequences) - Add coordinator unit tests (20 tests covering scope validation, finding extraction, prompt threading, naming conventions) - Bump to 2.0.0 (breaking: new pipeline architecture) Co-Authored-By: Claude <noreply@anthropic.com>
Wrap five impacket remote execution scripts that were available but not exposed as tool methods: wmiexec, psexec, smbexec, atexec, and dcomexec. These fill the critical gap where the agent could recover credentials and confirm admin access but had no way to execute commands on remote hosts. Update exploit-operator and credential-harvester stage boundaries and add lateral movement method selection guidance to the ad-attack-patterns skill. Co-Authored-By: Claude <noreply@anthropic.com>
Add Coercion toolset wrapping PetitPotam (MS-EFSRPC), DFSCoerce (MS-DFSNM), and ShadowCoerce (MS-FSRVP) for authentication coercion in relay attack chains. Add smb_upload_file to SmbClient for staging files on remote shares. Update ad-attack-patterns skill with NTLM relay chain, coercion method selection table, and exploit-operator stage boundaries. Co-Authored-By: Claude <noreply@anthropic.com>
All three SmbClient methods now verify smbclient is on PATH before executing, returning a clear install hint instead of a raw traceback. Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR upgrades the network-ops capability to a 2.0 multi-agent “ASM-style” pipeline coordinated by a worker, adds an agent-facing launcher tool, and fills key AD attack tooling gaps (lateral movement + coercion), along with methodology/playbook skills.
Changes:
- Added a 6-stage worker-coordinated pipeline (
netops.engagement.*events) with per-stage agents and unit tests for coordinator logic. - Added an agent tool to launch/monitor the pipeline (
run_netops_pipeline) and introduced a newnetops-operatoragent (replacingnetwork-ops-agent). - Expanded tooling for real engagements: SMB upload support, new Impacket lateral-movement wrappers, and RPC coercion wrappers.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| capabilities/network-ops/workers/coordinator.py | New worker coordinating the staged multi-agent pipeline and report synthesis. |
| capabilities/network-ops/tools/smbclient.py | Adds smbclient binary checks and introduces SMB upload support. |
| capabilities/network-ops/tools/pipeline.py | Adds run_netops_pipeline launcher + runtime monitoring + direct coordinator fallback import. |
| capabilities/network-ops/tools/impacket.py | Adds lateral movement wrappers (wmiexec/psexec/smbexec/atexec/dcomexec). |
| capabilities/network-ops/tools/coercion.py | Adds coercion wrappers for PetitPotam/DFSCoerce/ShadowCoerce. |
| capabilities/network-ops/tests/test_worker_coordinator.py | Adds unit tests for coordinator scope handling, prompt threading, findings extraction, and utilities. |
| capabilities/network-ops/skills/network-ops-methodology/SKILL.md | Adds methodology “hard rules” + confidence/severity standards for netops. |
| capabilities/network-ops/skills/ad-enumeration-playbook/SKILL.md | Adds AD enumeration decision tree and tool mapping. |
| capabilities/network-ops/skills/ad-attack-patterns/SKILL.md | Adds AD attack-chain reference with coercion/lateral movement guidance. |
| capabilities/network-ops/capability.yaml | Bumps to 2.0.0 and enables auto-loading for agents/skills/tools/workers + adds loguru dep. |
| capabilities/network-ops/agents/pipeline/scope-normalizer.md | New dedicated scope normalization pipeline agent. |
| capabilities/network-ops/agents/pipeline/discovery-operator.md | New dedicated discovery/scanning pipeline agent. |
| capabilities/network-ops/agents/pipeline/ad-enumerator.md | New dedicated AD enumeration pipeline agent. |
| capabilities/network-ops/agents/pipeline/exploit-operator.md | New dedicated exploitation pipeline agent (pre-harvest). |
| capabilities/network-ops/agents/pipeline/credential-harvester.md | New dedicated credential dumping/cracking/verification pipeline agent. |
| capabilities/network-ops/agents/pipeline/report-synthesizer.md | New dedicated report synthesis pipeline agent. |
| capabilities/network-ops/agents/network-ops-agent.md | Removes the legacy monolithic agent (breaking change). |
| capabilities/network-ops/agents/netops-operator.md | Adds replacement operator agent with pipeline-vs-direct decision criteria + skill references. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Keep the user-facing agent name as network-ops-agent to avoid breaking existing TUI selections and saved configurations. Pipeline agents use the netops-* prefix internally but the standalone agent name stays the same as 1.x. Co-Authored-By: Claude <noreply@anthropic.com>
- Restore loguru stub in sys.modules after coordinator import (pipeline.py) - Fix max_steps docstring: per-stage clamp, not total budget (pipeline.py) - Sanitize SMB paths to prevent smbclient command injection via ; and ! - Guard local_path against UnboundLocalError in smb_upload_file finally - Include real repo URLs in coercion _resolve_script error messages Co-Authored-By: Claude <noreply@anthropic.com>
|
|
||
| # --- Stage 2: Network Discovery --- | ||
| await _publish_progress(client, run_id, "discovery_started") | ||
| discovery_report, _ = await _run_agent_turn( |
There was a problem hiding this comment.
Partially confirmed. Discovery tool_calls intentionally stay discarded — discovery only reports Targets/Services/DCs which _extract_findings filters out anyway. Fixed enumeration in 3f50678 since it can report Weakness items (unconstrained delegation, writable ACLs).
| # --- Stage 6: Report Synthesis --- | ||
| await _publish_progress(client, run_id, "report_synthesis_started") | ||
|
|
||
| all_tool_calls = exploit_tool_calls + harvest_tool_calls |
There was a problem hiding this comment.
Fixed in 3f50678 — all_tool_calls now includes enumeration_tool_calls + exploit_tool_calls + harvest_tool_calls. Discovery stays excluded since it only produces Target/Service/DC items that _extract_findings filters out.
Enumeration stage can report Weakness items via report_item (e.g., unconstrained delegation, writable ACLs). These were discarded with `_` and not included in the structured findings for synthesis. Co-Authored-By: Claude <noreply@anthropic.com>
| @worker.on_event(REQUEST_EVENT) | ||
| async def run_engagement(event: EventEnvelope, client: RuntimeClient) -> None: | ||
| """Run one network operations engagement pipeline end to end.""" | ||
| payload = event.payload or {} |
There was a problem hiding this comment.
Refuted. EventEnvelope.payload is typed dict | None in the dreadnode framework — the runtime never delivers non-dict payloads. The or {} handles the None case. ASM's coordinator uses the identical pattern at line 69.
| args.extend( | ||
| self._build_auth_flags( | ||
| hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password | ||
| ) | ||
| ) | ||
| args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) | ||
|
|
||
| return await execute( | ||
| self._build_script_command("wmiexec.py", args), | ||
| timeout=timeout or self.timeout + 60, | ||
| input=input, | ||
| env=env, | ||
| ) |
There was a problem hiding this comment.
Fixed in 6c48209 — sends exit\n via stdin when no command is given, so the shell terminates and returns the banner promptly.
| identity = self._build_identity_with_target( | ||
| target, domain=domain, username=username, password=password | ||
| ) | ||
|
|
||
| args = [identity] | ||
| if command: | ||
| args.append(command) | ||
|
|
There was a problem hiding this comment.
Fixed in 6c48209 — same exit\n stdin pattern applied to psexec for consistency with wmiexec and dcomexec.
| args.extend( | ||
| self._build_auth_flags( | ||
| hashes=hashes, kerberos=kerberos, aes_key=aes_key, password=password | ||
| ) | ||
| ) | ||
| args.extend(self._build_connection_flags(dc_ip=dc_ip, target_ip=target_ip)) | ||
|
|
||
| return await execute( | ||
| self._build_script_command("dcomexec.py", args), | ||
| timeout=timeout or self.timeout + 60, | ||
| input=input, | ||
| env=env, | ||
| ) |
There was a problem hiding this comment.
Fixed in 6c48209 — sends exit\n via stdin when command=None, matching the wmiexec fix.
wmiexec, psexec, and dcomexec hang until timeout when called without a command since the underlying scripts launch an interactive shell. Now send exit via stdin when no command is given so the process terminates and returns the banner promptly. Co-Authored-By: Claude <noreply@anthropic.com>
Restructure network-ops from a single monolithic agent into a coordinated multi-agent pipeline following the ASM pattern, then fill critical tool gaps.
Added
workers/coordinator.py)agents/pipeline/— each scoped to a single phase with explicit stage boundariesnetwork-ops-agentupdated with pipeline-vs-direct decision criteria, skill references, and specific tool namesrun_netops_pipelinetool for programmatic pipeline invocation (tools/pipeline.py)network-ops-methodology(hard rules, confidence levels, anti-patterns),ad-enumeration-playbook(decision tree, tool mapping),ad-attack-patterns(attack chain sequences, coercion/relay/lateral movement method selection)impacket_wmiexec,impacket_psexec,impacket_smbexec,impacket_atexec,impacket_dcomexecCoerciontoolset (tools/coercion.py) wrapping PetitPotam (MS-EFSRPC), DFSCoerce (MS-DFSNM), ShadowCoerce (MS-FSRVP)smb_upload_fileonSmbClientfor staging files to remote sharesChanged
capability.yamlbumped to 2.0.0 withagents/,skills/,tools/,workers/auto-load sections andlogurudependency_extract_findingsin coordinator filters to credentials, hashes, and weaknesses only — drops enumeration noise[NETOPS_STAGE_TIMEOUT]sentinel instead of substring matchingFixed
smbclientmethods now check binary existence before executing, returning an install hint instead of a raw traceback_resolve_script()with clearFileNotFoundErrormessagestools/pipeline.py) stubsloguruwhen loading coordinator in-process, preventingModuleNotFoundErrorNotes
network-ops-agentname preserved for backwards compatibility — existing TUI selections and configs continue to work