Initialize repository snapshot
This commit is contained in:
898
OFFSEC-AGENTS-PLAN.md
Normal file
898
OFFSEC-AGENTS-PLAN.md
Normal file
@@ -0,0 +1,898 @@
|
||||
# OffSec Agent Workers Plan
|
||||
|
||||
> *Shield commands. Agents execute. Receipts prove.*
|
||||
|
||||
## Current State Assessment
|
||||
|
||||
### What Exists
|
||||
|
||||
| Component | Status | Location |
|
||||
|-----------|--------|----------|
|
||||
| **Guardian Engine (Rust)** | ✅ Implemented | `vaultmesh-guardian/src/lib.rs` |
|
||||
| **OffSec Engine (Rust)** | ⚠️ Stub only | `vaultmesh-offsec/src/lib.rs` |
|
||||
| **Console Engine (Python)** | ✅ Receipts + Approvals | `engines/console/` |
|
||||
| **Shield Portal (Node.js)** | ✅ Web UI | `vaultmesh-shield-portal/` |
|
||||
| **CLI OffSec Commands** | ✅ Full implementation | `cli/vm_cli.py` |
|
||||
| **OffSec Spec** | ✅ Complete | `VAULTMESH-OFFSEC-ENGINE.md` |
|
||||
|
||||
### What's Missing
|
||||
|
||||
1. **OffSec Agent Workers** - Autonomous AI agents that perform security tasks
|
||||
2. **Agent Orchestration Layer** - Dispatch, monitor, control agents
|
||||
3. **Shield ↔ Agent Protocol** - Communication and approval flow
|
||||
4. **CAI Integration** - Leverage existing security AI tools
|
||||
|
||||
---
|
||||
|
||||
## Architecture: Shield-Agent Pattern
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SHIELD (Guardian/Overseer) │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Shield Portal (vaultmesh-shield-portal) │ │
|
||||
│ │ - Mission control UI │ │
|
||||
│ │ - Agent status dashboard │ │
|
||||
│ │ - Approval workflow │ │
|
||||
│ │ - Receipt viewer │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Agent Orchestrator (new: engines/offsec_agents/) │ │
|
||||
│ │ - Agent registry │ │
|
||||
│ │ - Mission dispatch │ │
|
||||
│ │ - Approval enforcement │ │
|
||||
│ │ - Receipt emission │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌────────────────┼────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
|
||||
│ RECON AGENT │ │ VULN AGENT │ │ EXPLOIT AGENT │
|
||||
│ (Worker) │ │ (Worker) │ │ (Worker) │
|
||||
│ │ │ │ │ │
|
||||
│ • Target enum │ │ • CVE scanning │ │ • PoC execution │
|
||||
│ • Port scanning │ │ • Config audit │ │ • Payload delivery │
|
||||
│ • OSINT gathering │ │ • Dependency check │ │ • Post-exploit │
|
||||
│ • Service ID │ │ • Web vuln scan │ │ • Priv escalation │
|
||||
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
|
||||
│ │ │
|
||||
└───────────────────────┴───────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────┐
|
||||
│ OFFSEC SCROLL │
|
||||
│ receipts/offsec/ │
|
||||
│ offsec_events.jsonl │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent Types
|
||||
|
||||
### Phase 1: Core Agents (Nigredo)
|
||||
|
||||
| Agent | Purpose | Risk Level | Approval Required |
|
||||
|-------|---------|------------|-------------------|
|
||||
| **Recon Agent** | Target enumeration, OSINT | Low | Auto-approve |
|
||||
| **Vuln Agent** | Vulnerability scanning | Medium | Manager approve |
|
||||
| **Analyze Agent** | Code/binary analysis | Low | Auto-approve |
|
||||
| **Report Agent** | Finding aggregation | Low | Auto-approve |
|
||||
|
||||
### Phase 2: Active Agents (Albedo)
|
||||
|
||||
| Agent | Purpose | Risk Level | Approval Required |
|
||||
|-------|---------|------------|-------------------|
|
||||
| **Exploit Agent** | PoC execution | High | Multi-party approve |
|
||||
| **CTF Agent** | CTF challenge solving | Medium | Engagement scope |
|
||||
| **Red Team Agent** | Full adversary emulation | Critical | Executive approve |
|
||||
|
||||
### Phase 3: Response Agents (Citrinitas)
|
||||
|
||||
| Agent | Purpose | Risk Level | Approval Required |
|
||||
|-------|---------|------------|-------------------|
|
||||
| **DFIR Agent** | Incident response | Medium | Incident commander |
|
||||
| **Remediation Agent** | Automated patching | High | Change approval |
|
||||
| **Threat Intel Agent** | IOC correlation | Low | Auto-approve |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Step 1: Agent Base Framework
|
||||
|
||||
**File:** `engines/offsec_agents/__init__.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
OffSec Agent Workers - Base Framework
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Optional
|
||||
import uuid
|
||||
|
||||
class AgentType(str, Enum):
|
||||
RECON = "recon"
|
||||
VULN = "vuln"
|
||||
EXPLOIT = "exploit"
|
||||
CTF = "ctf"
|
||||
ANALYZE = "analyze"
|
||||
DFIR = "dfir"
|
||||
REMEDIATION = "remediation"
|
||||
THREAT_INTEL = "threat_intel"
|
||||
REPORT = "report"
|
||||
|
||||
class AgentStatus(str, Enum):
|
||||
IDLE = "idle"
|
||||
ASSIGNED = "assigned"
|
||||
RUNNING = "running"
|
||||
AWAITING_APPROVAL = "awaiting_approval"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
class RiskLevel(str, Enum):
|
||||
LOW = "low"
|
||||
MEDIUM = "medium"
|
||||
HIGH = "high"
|
||||
CRITICAL = "critical"
|
||||
|
||||
@dataclass
|
||||
class Mission:
|
||||
"""A task assigned to an agent."""
|
||||
mission_id: str
|
||||
agent_type: AgentType
|
||||
target: str
|
||||
objectives: List[str]
|
||||
scope: Dict[str, Any]
|
||||
risk_level: RiskLevel
|
||||
requested_by: str
|
||||
engagement_id: Optional[str] = None
|
||||
incident_id: Optional[str] = None
|
||||
created_at: str = field(
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat()
|
||||
)
|
||||
status: str = "pending"
|
||||
|
||||
@dataclass
|
||||
class AgentResult:
|
||||
"""Result from agent execution."""
|
||||
mission_id: str
|
||||
agent_id: str
|
||||
status: AgentStatus
|
||||
findings: List[Dict[str, Any]]
|
||||
evidence_paths: List[str]
|
||||
started_at: str
|
||||
completed_at: str
|
||||
duration_seconds: float
|
||||
receipt_hash: Optional[str] = None
|
||||
```
|
||||
|
||||
### Step 2: Agent Orchestrator
|
||||
|
||||
**File:** `engines/offsec_agents/orchestrator.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Agent Orchestrator - Dispatch, monitor, and control agents.
|
||||
"""
|
||||
|
||||
class AgentOrchestrator:
|
||||
"""
|
||||
Central control for OffSec agents.
|
||||
|
||||
Responsibilities:
|
||||
- Register available agents
|
||||
- Dispatch missions to appropriate agents
|
||||
- Enforce approval workflows
|
||||
- Emit receipts for all agent actions
|
||||
- Track agent status and results
|
||||
"""
|
||||
|
||||
def __init__(self, vaultmesh_root: str):
|
||||
self.vaultmesh_root = vaultmesh_root
|
||||
self.agents: Dict[str, BaseAgent] = {}
|
||||
self.missions: Dict[str, Mission] = {}
|
||||
self.approval_manager = ApprovalManager(vaultmesh_root)
|
||||
|
||||
def register_agent(self, agent: "BaseAgent") -> None:
|
||||
"""Register an agent with the orchestrator."""
|
||||
self.agents[agent.agent_id] = agent
|
||||
|
||||
async def dispatch(self, mission: Mission) -> str:
|
||||
"""
|
||||
Dispatch a mission to an appropriate agent.
|
||||
|
||||
Flow:
|
||||
1. Validate mission scope
|
||||
2. Check if approval required
|
||||
3. Request approval if needed
|
||||
4. Assign to available agent
|
||||
5. Emit mission_assigned receipt
|
||||
"""
|
||||
# Check approval requirements
|
||||
if self._requires_approval(mission):
|
||||
approval = await self._request_approval(mission)
|
||||
if not approval.approved:
|
||||
return "rejected"
|
||||
|
||||
# Find available agent
|
||||
agent = self._find_agent(mission.agent_type)
|
||||
if not agent:
|
||||
raise NoAgentAvailable(mission.agent_type)
|
||||
|
||||
# Assign mission
|
||||
agent.assign(mission)
|
||||
self.missions[mission.mission_id] = mission
|
||||
|
||||
# Emit receipt
|
||||
self._emit_mission_receipt("offsec_mission_assigned", mission)
|
||||
|
||||
return mission.mission_id
|
||||
|
||||
def _requires_approval(self, mission: Mission) -> bool:
|
||||
"""Check if mission requires approval based on risk level."""
|
||||
approval_matrix = {
|
||||
RiskLevel.LOW: False,
|
||||
RiskLevel.MEDIUM: True,
|
||||
RiskLevel.HIGH: True,
|
||||
RiskLevel.CRITICAL: True,
|
||||
}
|
||||
return approval_matrix.get(mission.risk_level, True)
|
||||
```
|
||||
|
||||
### Step 3: Base Agent Class
|
||||
|
||||
**File:** `engines/offsec_agents/base.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Base Agent - Abstract class for all OffSec agents.
|
||||
"""
|
||||
|
||||
class BaseAgent(ABC):
|
||||
"""
|
||||
Abstract base class for OffSec agents.
|
||||
|
||||
All agents must:
|
||||
1. Implement execute() for their core logic
|
||||
2. Emit receipts for significant actions
|
||||
3. Respect scope boundaries
|
||||
4. Handle approval checkpoints
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
agent_id: str,
|
||||
agent_type: AgentType,
|
||||
did: str,
|
||||
orchestrator: AgentOrchestrator,
|
||||
):
|
||||
self.agent_id = agent_id
|
||||
self.agent_type = agent_type
|
||||
self.did = did # e.g., did:vm:agent:recon-01
|
||||
self.orchestrator = orchestrator
|
||||
self.status = AgentStatus.IDLE
|
||||
self.current_mission: Optional[Mission] = None
|
||||
|
||||
def assign(self, mission: Mission) -> None:
|
||||
"""Accept a mission assignment."""
|
||||
self.current_mission = mission
|
||||
self.status = AgentStatus.ASSIGNED
|
||||
|
||||
async def run(self) -> AgentResult:
|
||||
"""
|
||||
Execute the assigned mission.
|
||||
|
||||
Flow:
|
||||
1. Validate mission is assigned
|
||||
2. Emit mission_started receipt
|
||||
3. Execute core logic
|
||||
4. Emit findings as receipts
|
||||
5. Emit mission_completed receipt
|
||||
"""
|
||||
if not self.current_mission:
|
||||
raise NoMissionAssigned()
|
||||
|
||||
self.status = AgentStatus.RUNNING
|
||||
started_at = datetime.now(timezone.utc)
|
||||
|
||||
self._emit_receipt("offsec_agent_started", {
|
||||
"mission_id": self.current_mission.mission_id,
|
||||
"agent_id": self.agent_id,
|
||||
"agent_type": self.agent_type.value,
|
||||
})
|
||||
|
||||
try:
|
||||
findings = await self.execute()
|
||||
self.status = AgentStatus.COMPLETED
|
||||
except Exception as e:
|
||||
self.status = AgentStatus.FAILED
|
||||
findings = [{"error": str(e)}]
|
||||
|
||||
completed_at = datetime.now(timezone.utc)
|
||||
|
||||
result = AgentResult(
|
||||
mission_id=self.current_mission.mission_id,
|
||||
agent_id=self.agent_id,
|
||||
status=self.status,
|
||||
findings=findings,
|
||||
evidence_paths=self.evidence_paths,
|
||||
started_at=started_at.isoformat(),
|
||||
completed_at=completed_at.isoformat(),
|
||||
duration_seconds=(completed_at - started_at).total_seconds(),
|
||||
)
|
||||
|
||||
self._emit_receipt("offsec_agent_completed", asdict(result))
|
||||
|
||||
self.current_mission = None
|
||||
self.status = AgentStatus.IDLE
|
||||
|
||||
return result
|
||||
|
||||
@abstractmethod
|
||||
async def execute(self) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Core agent logic - must be implemented by subclasses.
|
||||
|
||||
Returns:
|
||||
List of findings/results
|
||||
"""
|
||||
pass
|
||||
|
||||
async def checkpoint(self, action: str, details: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
Request approval for a risky action mid-execution.
|
||||
|
||||
Use for actions that exceed initial mission scope or risk level.
|
||||
"""
|
||||
if self._action_exceeds_scope(action, details):
|
||||
approval = await self.orchestrator.request_approval(
|
||||
session_id=self.current_mission.mission_id,
|
||||
action_type=action,
|
||||
action_details=details,
|
||||
requested_by=self.did,
|
||||
approvers=self._get_approvers(action),
|
||||
)
|
||||
return approval.approved
|
||||
return True
|
||||
```
|
||||
|
||||
### Step 4: Concrete Agent Implementations
|
||||
|
||||
**File:** `engines/offsec_agents/agents/recon.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Recon Agent - Target enumeration and OSINT gathering.
|
||||
"""
|
||||
|
||||
class ReconAgent(BaseAgent):
|
||||
"""
|
||||
Reconnaissance agent for target enumeration.
|
||||
|
||||
Capabilities:
|
||||
- Port scanning (nmap integration)
|
||||
- Service identification
|
||||
- OSINT gathering
|
||||
- DNS enumeration
|
||||
- Technology fingerprinting
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
agent_type=AgentType.RECON,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
async def execute(self) -> List[Dict[str, Any]]:
|
||||
"""Execute reconnaissance mission."""
|
||||
mission = self.current_mission
|
||||
target = mission.target
|
||||
findings = []
|
||||
|
||||
# Phase 1: DNS/Host resolution
|
||||
dns_results = await self._dns_enum(target)
|
||||
findings.extend(dns_results)
|
||||
|
||||
# Phase 2: Port scanning
|
||||
if "port_scan" in mission.objectives:
|
||||
ports = await self._port_scan(target, mission.scope)
|
||||
findings.extend(ports)
|
||||
|
||||
# Phase 3: Service identification
|
||||
if "service_id" in mission.objectives:
|
||||
services = await self._identify_services(target, ports)
|
||||
findings.extend(services)
|
||||
|
||||
# Phase 4: Technology fingerprinting
|
||||
if "tech_fingerprint" in mission.objectives:
|
||||
tech = await self._fingerprint(target)
|
||||
findings.extend(tech)
|
||||
|
||||
return findings
|
||||
|
||||
async def _port_scan(self, target: str, scope: Dict) -> List[Dict]:
|
||||
"""Run port scan within scope constraints."""
|
||||
# Use CAI recon or nmap
|
||||
from cai_mcp_client import cai_recon
|
||||
|
||||
depth = scope.get("scan_depth", "quick")
|
||||
result = await cai_recon(target=target, depth=depth)
|
||||
|
||||
return self._parse_scan_results(result)
|
||||
```
|
||||
|
||||
**File:** `engines/offsec_agents/agents/vuln.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Vuln Agent - Vulnerability scanning and assessment.
|
||||
"""
|
||||
|
||||
class VulnAgent(BaseAgent):
|
||||
"""
|
||||
Vulnerability scanning agent.
|
||||
|
||||
Capabilities:
|
||||
- CVE detection
|
||||
- Configuration auditing
|
||||
- Dependency vulnerability checks
|
||||
- Web application scanning
|
||||
- API security testing
|
||||
"""
|
||||
|
||||
async def execute(self) -> List[Dict[str, Any]]:
|
||||
"""Execute vulnerability scan mission."""
|
||||
mission = self.current_mission
|
||||
target = mission.target
|
||||
findings = []
|
||||
|
||||
# Determine scan type
|
||||
scan_type = mission.scope.get("scan_type", "all")
|
||||
|
||||
# Checkpoint for web scans (can be noisy)
|
||||
if scan_type in ["web", "all"]:
|
||||
approved = await self.checkpoint(
|
||||
"web_vuln_scan",
|
||||
{"target": target, "reason": "Web scanning may generate traffic"}
|
||||
)
|
||||
if not approved:
|
||||
scan_type = "network" # Fall back to quieter scan
|
||||
|
||||
# Use CAI vuln scanner
|
||||
from cai_mcp_client import cai_vuln_scan
|
||||
|
||||
result = await cai_vuln_scan(target=target, scan_type=scan_type)
|
||||
|
||||
# Convert to findings
|
||||
for vuln in result.get("vulnerabilities", []):
|
||||
finding = {
|
||||
"type": "vulnerability",
|
||||
"title": vuln.get("title"),
|
||||
"severity": vuln.get("severity"),
|
||||
"cvss": vuln.get("cvss_score"),
|
||||
"cve": vuln.get("cve_id"),
|
||||
"affected_asset": target,
|
||||
"evidence": vuln.get("evidence"),
|
||||
}
|
||||
findings.append(finding)
|
||||
|
||||
# Auto-create vuln receipt for high+ severity
|
||||
if vuln.get("severity") in ["high", "critical"]:
|
||||
self._emit_vuln_discovery(finding)
|
||||
|
||||
return findings
|
||||
```
|
||||
|
||||
**File:** `engines/offsec_agents/agents/exploit.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Exploit Agent - Controlled exploitation and PoC execution.
|
||||
|
||||
⚠️ HIGH RISK - Requires multi-party approval
|
||||
"""
|
||||
|
||||
class ExploitAgent(BaseAgent):
|
||||
"""
|
||||
Exploitation agent for controlled PoC execution.
|
||||
|
||||
CRITICAL: All exploits require:
|
||||
1. Valid engagement/incident context
|
||||
2. Multi-party approval
|
||||
3. Detailed evidence capture
|
||||
4. Immediate rollback capability
|
||||
"""
|
||||
|
||||
async def execute(self) -> List[Dict[str, Any]]:
|
||||
"""Execute exploitation mission with strict controls."""
|
||||
mission = self.current_mission
|
||||
|
||||
# Verify engagement context
|
||||
if not mission.engagement_id and not mission.incident_id:
|
||||
raise NoEngagementContext(
|
||||
"Exploitation requires valid engagement or incident context"
|
||||
)
|
||||
|
||||
# Mandatory checkpoint before any exploit
|
||||
approved = await self.checkpoint(
|
||||
"exploit_execution",
|
||||
{
|
||||
"target": mission.target,
|
||||
"vulnerability": mission.scope.get("vuln_id"),
|
||||
"technique": mission.scope.get("technique"),
|
||||
"engagement_id": mission.engagement_id,
|
||||
}
|
||||
)
|
||||
|
||||
if not approved:
|
||||
return [{"status": "blocked", "reason": "Approval denied"}]
|
||||
|
||||
# Execute with full evidence capture
|
||||
findings = []
|
||||
|
||||
try:
|
||||
# Start evidence capture
|
||||
self._start_capture()
|
||||
|
||||
# Use CAI exploit
|
||||
from cai_mcp_client import cai_exploit
|
||||
|
||||
result = await cai_exploit(
|
||||
target=mission.target,
|
||||
vulnerability=mission.scope.get("vuln_id"),
|
||||
)
|
||||
|
||||
findings.append({
|
||||
"type": "exploit_result",
|
||||
"success": result.get("success"),
|
||||
"access_gained": result.get("access_level"),
|
||||
"evidence_path": self._stop_capture(),
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
findings.append({
|
||||
"type": "exploit_error",
|
||||
"error": str(e),
|
||||
"evidence_path": self._stop_capture(),
|
||||
})
|
||||
|
||||
return findings
|
||||
```
|
||||
|
||||
### Step 5: CAI Integration Bridge
|
||||
|
||||
**File:** `engines/offsec_agents/cai_bridge.py`
|
||||
|
||||
```python
|
||||
"""
|
||||
Bridge to CAI MCP tools for agent use.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
class CAIBridge:
|
||||
"""
|
||||
Bridge to CAI security tools via MCP.
|
||||
|
||||
Wraps CAI tools for use by OffSec agents:
|
||||
- cai_recon → ReconAgent
|
||||
- cai_vuln_scan → VulnAgent
|
||||
- cai_exploit → ExploitAgent
|
||||
- cai_ctf → CTFAgent
|
||||
- cai_analyze → AnalyzeAgent
|
||||
"""
|
||||
|
||||
async def recon(
|
||||
self,
|
||||
target: str,
|
||||
depth: str = "standard"
|
||||
) -> Dict[str, Any]:
|
||||
"""Run CAI reconnaissance."""
|
||||
# Call MCP tool
|
||||
result = await self._call_mcp("cai_recon", {
|
||||
"target": target,
|
||||
"depth": depth,
|
||||
})
|
||||
return result
|
||||
|
||||
async def vuln_scan(
|
||||
self,
|
||||
target: str,
|
||||
scan_type: str = "all"
|
||||
) -> Dict[str, Any]:
|
||||
"""Run CAI vulnerability scan."""
|
||||
result = await self._call_mcp("cai_vuln_scan", {
|
||||
"target": target,
|
||||
"scan_type": scan_type,
|
||||
})
|
||||
return result
|
||||
|
||||
async def exploit(
|
||||
self,
|
||||
target: str,
|
||||
vulnerability: str
|
||||
) -> Dict[str, Any]:
|
||||
"""Run CAI exploitation (requires authorization)."""
|
||||
result = await self._call_mcp("cai_exploit", {
|
||||
"target": target,
|
||||
"vulnerability": vulnerability,
|
||||
})
|
||||
return result
|
||||
|
||||
async def analyze(
|
||||
self,
|
||||
file_path: str,
|
||||
analysis_type: str = "static"
|
||||
) -> Dict[str, Any]:
|
||||
"""Run CAI code/binary analysis."""
|
||||
result = await self._call_mcp("cai_analyze", {
|
||||
"file_path": file_path,
|
||||
"analysis_type": analysis_type,
|
||||
})
|
||||
return result
|
||||
|
||||
async def ctf(
|
||||
self,
|
||||
challenge: str,
|
||||
category: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Run CAI CTF solver."""
|
||||
params = {"challenge": challenge}
|
||||
if category:
|
||||
params["category"] = category
|
||||
result = await self._call_mcp("cai_ctf", params)
|
||||
return result
|
||||
```
|
||||
|
||||
### Step 6: Shield Portal Integration
|
||||
|
||||
**File:** `vaultmesh-shield-portal/app/src/routes/agents.js`
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Agent management routes for Shield Portal
|
||||
*/
|
||||
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// GET /agents - List all registered agents
|
||||
router.get('/', async (req, res) => {
|
||||
const agents = await getAgentRegistry();
|
||||
res.render('agents/list', { agents });
|
||||
});
|
||||
|
||||
// GET /agents/:id - Agent detail view
|
||||
router.get('/:id', async (req, res) => {
|
||||
const agent = await getAgent(req.params.id);
|
||||
const missions = await getAgentMissions(req.params.id);
|
||||
res.render('agents/detail', { agent, missions });
|
||||
});
|
||||
|
||||
// POST /agents/dispatch - Dispatch a new mission
|
||||
router.post('/dispatch', async (req, res) => {
|
||||
const { agent_type, target, objectives, scope } = req.body;
|
||||
|
||||
const mission = await dispatchMission({
|
||||
agent_type,
|
||||
target,
|
||||
objectives,
|
||||
scope,
|
||||
requested_by: req.user.did,
|
||||
});
|
||||
|
||||
res.redirect(`/missions/${mission.mission_id}`);
|
||||
});
|
||||
|
||||
// GET /missions - List all missions
|
||||
router.get('/missions', async (req, res) => {
|
||||
const missions = await getMissions({
|
||||
status: req.query.status,
|
||||
agent_type: req.query.agent_type,
|
||||
});
|
||||
res.render('missions/list', { missions });
|
||||
});
|
||||
|
||||
// POST /missions/:id/approve - Approve a pending mission
|
||||
router.post('/missions/:id/approve', async (req, res) => {
|
||||
await approveMission(req.params.id, {
|
||||
approver: req.user.did,
|
||||
reason: req.body.reason,
|
||||
});
|
||||
res.redirect(`/missions/${req.params.id}`);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
```
|
||||
|
||||
### Step 7: CLI Commands
|
||||
|
||||
**Add to:** `cli/vm_cli.py`
|
||||
|
||||
```python
|
||||
# ============================================================================
|
||||
# Agent Commands
|
||||
# ============================================================================
|
||||
|
||||
@cli.group()
|
||||
def agent():
|
||||
"""OffSec Agent management."""
|
||||
pass
|
||||
|
||||
@agent.command("list")
|
||||
def agent_list():
|
||||
"""List registered agents."""
|
||||
orchestrator = get_orchestrator()
|
||||
for agent in orchestrator.agents.values():
|
||||
status_icon = "🟢" if agent.status == AgentStatus.IDLE else "🔴"
|
||||
click.echo(f"{status_icon} {agent.agent_id} ({agent.agent_type.value})")
|
||||
|
||||
@agent.command("dispatch")
|
||||
@click.option("--type", "agent_type", required=True,
|
||||
type=click.Choice(["recon", "vuln", "exploit", "ctf", "analyze"]))
|
||||
@click.option("--target", required=True, help="Target for the mission")
|
||||
@click.option("--objective", multiple=True, help="Mission objectives")
|
||||
@click.option("--engagement", help="Link to engagement ID")
|
||||
@click.option("--incident", help="Link to incident ID")
|
||||
def agent_dispatch(agent_type, target, objective, engagement, incident):
|
||||
"""Dispatch a mission to an agent."""
|
||||
orchestrator = get_orchestrator()
|
||||
|
||||
mission = Mission(
|
||||
mission_id=generate_mission_id(),
|
||||
agent_type=AgentType(agent_type),
|
||||
target=target,
|
||||
objectives=list(objective),
|
||||
scope={},
|
||||
risk_level=RiskLevel.MEDIUM,
|
||||
requested_by=get_actor_did(),
|
||||
engagement_id=engagement,
|
||||
incident_id=incident,
|
||||
)
|
||||
|
||||
result = asyncio.run(orchestrator.dispatch(mission))
|
||||
click.echo(f"[agent] Mission dispatched: {result}")
|
||||
|
||||
@agent.command("status")
|
||||
@click.argument("mission_id")
|
||||
def agent_status(mission_id):
|
||||
"""Check mission status."""
|
||||
orchestrator = get_orchestrator()
|
||||
mission = orchestrator.missions.get(mission_id)
|
||||
|
||||
if not mission:
|
||||
click.echo(f"Mission not found: {mission_id}")
|
||||
return
|
||||
|
||||
click.echo(f"Mission: {mission.mission_id}")
|
||||
click.echo(f"Type: {mission.agent_type.value}")
|
||||
click.echo(f"Target: {mission.target}")
|
||||
click.echo(f"Status: {mission.status}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Receipt Types
|
||||
|
||||
New receipt types for agent operations:
|
||||
|
||||
| Type | When Emitted |
|
||||
|------|--------------|
|
||||
| `offsec_mission_created` | Mission created and pending |
|
||||
| `offsec_mission_assigned` | Mission assigned to agent |
|
||||
| `offsec_mission_approved` | Mission approved to proceed |
|
||||
| `offsec_mission_rejected` | Mission approval rejected |
|
||||
| `offsec_agent_started` | Agent began execution |
|
||||
| `offsec_agent_checkpoint` | Agent requested mid-execution approval |
|
||||
| `offsec_agent_finding` | Agent discovered a finding |
|
||||
| `offsec_agent_completed` | Agent finished mission |
|
||||
| `offsec_agent_failed` | Agent encountered error |
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
engines/offsec_agents/
|
||||
├── __init__.py # Exports
|
||||
├── base.py # BaseAgent class
|
||||
├── orchestrator.py # AgentOrchestrator
|
||||
├── mission.py # Mission dataclass
|
||||
├── cai_bridge.py # CAI MCP integration
|
||||
├── receipts.py # Receipt emission
|
||||
├── agents/
|
||||
│ ├── __init__.py
|
||||
│ ├── recon.py # ReconAgent
|
||||
│ ├── vuln.py # VulnAgent
|
||||
│ ├── exploit.py # ExploitAgent
|
||||
│ ├── ctf.py # CTFAgent
|
||||
│ ├── analyze.py # AnalyzeAgent
|
||||
│ ├── dfir.py # DFIRAgent
|
||||
│ ├── remediation.py # RemediationAgent
|
||||
│ └── threat_intel.py # ThreatIntelAgent
|
||||
└── tests/
|
||||
├── test_orchestrator.py
|
||||
├── test_agents.py
|
||||
└── test_receipts.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Foundation (Week 1)
|
||||
- [ ] Create `engines/offsec_agents/` package structure
|
||||
- [ ] Implement `BaseAgent` abstract class
|
||||
- [ ] Implement `AgentOrchestrator` with basic dispatch
|
||||
- [ ] Implement `Mission` and `AgentResult` dataclasses
|
||||
- [ ] Add agent receipt types to OffSec scroll
|
||||
|
||||
### Phase 2: Core Agents (Week 2)
|
||||
- [ ] Implement `ReconAgent` with CAI bridge
|
||||
- [ ] Implement `VulnAgent` with CAI bridge
|
||||
- [ ] Implement `AnalyzeAgent` with CAI bridge
|
||||
- [ ] Add CLI commands for agent management
|
||||
- [ ] Write unit tests for each agent
|
||||
|
||||
### Phase 3: Approval Integration (Week 3)
|
||||
- [ ] Integrate with Console approval system
|
||||
- [ ] Implement checkpoint flow for risky actions
|
||||
- [ ] Add multi-party approval for high-risk agents
|
||||
- [ ] Update Shield Portal with approval UI
|
||||
|
||||
### Phase 4: Active Agents (Week 4)
|
||||
- [ ] Implement `ExploitAgent` with strict controls
|
||||
- [ ] Implement `CTFAgent` for CTF engagements
|
||||
- [ ] Add engagement context validation
|
||||
- [ ] Full evidence capture pipeline
|
||||
|
||||
### Phase 5: Response Agents (Week 5)
|
||||
- [ ] Implement `DFIRAgent` for incident response
|
||||
- [ ] Implement `ThreatIntelAgent` for IOC correlation
|
||||
- [ ] Implement `RemediationAgent` with change approval
|
||||
- [ ] Integration testing with real incidents
|
||||
|
||||
### Phase 6: Shield Portal UI (Week 6)
|
||||
- [ ] Agent dashboard page
|
||||
- [ ] Mission control view
|
||||
- [ ] Real-time status updates
|
||||
- [ ] Finding browser
|
||||
- [ ] Approval workflow UI
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Scope Enforcement**: Agents cannot operate outside defined scope
|
||||
2. **Approval Gates**: Risky actions require human approval
|
||||
3. **Evidence Trail**: All actions produce receipts
|
||||
4. **Capability Limits**: Agents have DID-based capabilities
|
||||
5. **Kill Switch**: Orchestrator can terminate any agent
|
||||
6. **Rate Limiting**: Prevent runaway agent behavior
|
||||
7. **Isolation**: Agents run in sandboxed environments
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Agents can be dispatched via CLI and Portal
|
||||
- [ ] All agent actions emit receipts to OffSec scroll
|
||||
- [ ] High-risk actions require approval
|
||||
- [ ] CAI tools accessible to agents via bridge
|
||||
- [ ] Full audit trail for any mission
|
||||
- [ ] Guardian can anchor agent activity
|
||||
|
||||
---
|
||||
|
||||
*Shield commands. Agents execute. Receipts prove.*
|
||||
Reference in New Issue
Block a user