Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/cli/infra/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ services:
ports:
- "127.0.0.1:3456:3456"
volumes:
- ./router-config.json:/config/router-config.json:ro
- ./router-config.json:/config/router-config.json:ro,z
environment:
- HOST=0.0.0.0
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
Expand Down
9 changes: 6 additions & 3 deletions apps/cli/src/docker.ts
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Shannon → VS Code Copilot: Migrating the Full Agent Stack to Native IDE Customization

While this PR hardens the Docker/CLI infrastructure, I wanted to share a parallel proof-of-concept that removes the infrastructure dependency entirely by migrating Shannon's multi-agent architecture to VS Code GitHub Copilot Customization primitives.


The Migration Map

Shannon Component VS Code Copilot Primitive What Was Built
Orchestrator + Specialist Agents .github/agents/*.agent.md 14 agents: pentest-orchestrator, pre-recon, recon, 5× vuln-analysis, 5× exploit, report
Skill Methodology Libraries .github/skills/*/SKILL.md 5 skills: llm-sast-scanner, vuln-analysis, exploit-execution, security-recon, security-reporting
Safety + Format Rules .github/instructions/*.instructions.md deliverable-format (report structure), exploit-safety (ethical boundaries + scope lock)
Workflow Triggers .github/prompts/*.prompt.md run-pentest, vuln-scan-only, generate-report
Scope + Safety Guards .github/hooks/ pentest-safety.json + validate-pentest-scope.py

How It Works

  • Agents load automatically when invoked with @agent-name in Copilot Chat — Shannon's pentest-orchestrator delegates to the same specialist chain (injection → XSS → auth → SSRF → authz → exploit → report)
  • Skills are SKILL.md files with 34-class SAST references — Copilot loads them on-demand for context-aware methodology
  • Instructions apply globally to enforce deliverable format and prevent out-of-scope exploitation
  • Prompts are one-click workflow starters — run-pentest.prompt.md launches the full 5-phase pipeline
  • Hooks run validate-pentest-scope.py before any exploit phase to verify target is in scope

Proof: VulnCMS Full Pentest in VS Code

5-phase pentest on a Node.js + Python CMS — 42 findings, 18 Critical — conducted entirely inside VS Code Copilot with zero Docker / CLI dependency.

  • CF-001: Unauthenticated RCE (4 vectors) — ✅ Proven live
  • CF-002: Admin auth bypass via isAdmin=true cookie — ✅ Proven live
  • CF-003: Full credential + SSN dump unauthenticated — ✅ Proven live
  • CF-004: SSRF → internal secret exfiltration — ✅ Proven live
  • CF-005: LFI → all hardcoded secrets disclosed — ✅ Proven live
  • 14× SQL injection, stored XSS, pickle RCE, eval() RCE, node-serialize RCE

Shannon CLI vs. VS Code Copilot

Shannon CLI VS Code Copilot
Infrastructure Docker Compose + Temporal None
Agent orchestration Temporal workflows Copilot @agent routing
Skill loading Hardcoded in worker On-demand SKILL.md
Safety enforcement SHANNON_DISABLE_SPENDING_GUARD flag hooks/pentest-safety.json
Deliverable output .shannon/deliverables/ .shannon/deliverables/ (same path)
Setup time npx keygraph-shannon + Docker Zero — ships with repo

The .github/ folder as shipped in the Shannon repo already contains everything needed to make this work. Shannon's agent methodology is essentially VS Code Copilot customization — just expressed as Docker workers instead of .agent.md files. This PR's infrastructure fixes remain valuable for full autonomous runs, but the VS Code path gives teams an instant on-ramp with no ops overhead.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));

const NPX_IMAGE_REPO = 'keygraph/shannon';
const DEV_IMAGE = 'shannon-worker';
const COMPOSE_PROJECT = 'infra';

export function getWorkerImage(version: string): string {
return getMode() === 'local' ? DEV_IMAGE : `${NPX_IMAGE_REPO}:${version}`;
Expand Down Expand Up @@ -82,17 +83,19 @@ function isRouterReady(): boolean {
export async function ensureInfra(useRouter: boolean): Promise<void> {
const temporalReady = isTemporalReady();
const routerNeeded = useRouter && !isRouterReady();
const startRouterOnly = temporalReady && routerNeeded;

if (temporalReady && !routerNeeded) {
return;
}

const composeFile = getComposeFile();
const composeArgs = ['compose', '-f', composeFile];
const composeArgs = ['compose', '-p', COMPOSE_PROJECT, '-f', composeFile];
if (useRouter) composeArgs.push('--profile', 'router');
composeArgs.push('up', '-d');
if (startRouterOnly) composeArgs.push('router');

if (temporalReady && routerNeeded) {
if (startRouterOnly) {
console.log('Starting router...');
} else {
console.log('Starting Shannon infrastructure...');
Expand Down Expand Up @@ -288,7 +291,7 @@ export function stopWorkers(): void {
*/
export function stopInfra(clean: boolean): void {
const composeFile = getComposeFile();
const args = ['compose', '-f', composeFile, '--profile', 'router', 'down'];
const args = ['compose', '-p', COMPOSE_PROJECT, '-f', composeFile, '--profile', 'router', 'down'];
if (clean) args.push('-v');
execFileSync('docker', args, { stdio: 'inherit' });
}
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ services:
ports:
- "127.0.0.1:3456:3456"
volumes:
- ./apps/cli/infra/router-config.json:/config/router-config.json:ro
- ./apps/cli/infra/router-config.json:/config/router-config.json:ro,z
environment:
- HOST=0.0.0.0
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
Expand Down