Shannon's Parallel Execution Capabilities for Vulnerability Analysis: A Technical Deep Dive
Shannon executes five specialized vulnerability-analysis agents concurrently using a Temporal workflow pipeline, reducing pentest duration while maintaining deterministic ordering through Promise-based mutexes and pipelined exploit stages.
The KeygraphHQ/shannon repository implements a high-performance penetration testing framework that leverages Temporal workflows to orchestrate complex security assessments. At the core of its architecture lies Shannon's parallel execution capabilities for vulnerability analysis, which enable simultaneous execution of multiple specialized agents while maintaining data integrity and deterministic workflow progression.
How Shannon Structures Parallel Vulnerability Analysis
Shannon organizes its pentest process into a pipeline-style Temporal workflow that stages execution from pre-reconnaissance through reporting. The vulnerability analysis phase represents the primary parallelization point, where computational intensity demands concurrent execution.
Defining Parallel Agent Groups in session-manager.ts
The system declares which agents may execute simultaneously through the getParallelGroups helper in src/session-manager.ts. This function returns frozen arrays specifying the five vulnerability-analysis agents and their corresponding exploit counterparts:
export const getParallelGroups = (): Readonly<{
vuln: AgentName[];
exploit: AgentName[];
}> => Object.freeze({
vuln: ['injection-vuln', 'xss-vuln', 'auth-vuln', 'ssrf-vuln', 'authz-vuln'],
exploit: ['injection-exploit', 'xss-exploit', 'auth-exploit', 'ssrf-exploit', 'authz-exploit']
});
Located at lines 103-107, this configuration enables the workflow to launch all five vulnerability agents—injection-vuln, xss-vuln, auth-vuln, ssrf-vuln, and authz-vuln—without sequential blocking.
The Vulnerability-to-Exploit Pipeline Architecture
Each vulnerability agent feeds directly into its matching exploit agent through a pipelined execution model. The runVulnExploitPipeline function in src/temporal/workflows.ts (lines 68-86) encapsulates this flow:
async function runVulnExploitPipeline(
vulnType: VulnType,
runVulnAgent: () => Promise<AgentMetrics>,
runExploitAgent: () => Promise<AgentMetrics>
): Promise<VulnExploitPipelineResult> {
// 1️⃣ Run vulnerability agent
const vulnMetrics = await runVulnAgent();
// 2️⃣ Check exploitation queue (starts immediately after vuln)
const decision = await a.checkExploitationQueue(activityInput, vulnType);
// 3️⃣ Conditionally run exploit agent
let exploitMetrics: AgentMetrics | null = null;
if (decision.shouldExploit) {
exploitMetrics = await runExploitAgent();
}
return { vulnType, vulnMetrics, exploitMetrics, exploitDecision: decision, error: null };
}
This pipelining ensures that exploitation begins immediately for a given vulnerability type without waiting for unrelated vulnerability agents to complete.
Concurrent Execution with Promise.allSettled
Shannon launches the five vulnerability-exploit pipelines simultaneously using Promise.allSettled at lines 98-107 of src/temporal/workflows.ts:
const pipelineResults = await Promise.allSettled([
runVulnExploitPipeline('injection', () => a.runInjectionVulnAgent(activityInput), () => a.runInjectionExploitAgent(activityInput)),
runVulnExploitPipeline('xss', () => a.runXssVulnAgent(activityInput), () => a.runXssExploitAgent(activityInput)),
runVulnExploitPipeline('auth', () => a.runAuthVulnAgent(activityInput), () => a.runAuthExploitAgent(activityInput)),
runVulnExploitPipeline('ssrf', () => a.runSsrfVulnAgent(activityInput), () => a.runSsrfExploitAgent(activityInput)),
runVulnExploitPipeline('authz', () => a.runAuthzVulnAgent(activityInput), () => a.runAuthzExploitAgent(activityInput)),
]);
Fault isolation represents a critical benefit of this approach. Because Promise.allSettled waits for all promises regardless of individual failures, a crash in the ssrf-vuln agent does not terminate the injection-vuln or xss-vuln pipelines. The workflow aggregates results only after all agents have either completed or failed.
Concurrency Safety with SessionMutex
Parallel execution introduces race conditions when multiple agents attempt to write to shared session files, audit logs, or deliverables. Shannon prevents these conflicts through the SessionMutex class implemented in src/utils/concurrency.ts (lines 34-56):
const mutex = new SessionMutex();
const unlock = await mutex.lock(sessionId);
try {
// modify session data safely
} finally {
unlock();
}
This Promise-based mutex ensures that only one agent modifies shared data at a time, preventing race conditions while allowing the agents themselves to run concurrently. The implementation supports async/await patterns compatible with Temporal's activity execution model.
Complete Workflow Architecture
Shannon's pentest pipeline follows a deterministic staging model that maximizes parallelization only where computationally beneficial:
- Pre-reconnaissance → Reconnaissance (sequential phases)
- Vulnerability Analysis + Exploitation (five parallel pipelines: injection, XSS, authentication, SSRF, authorization)
- Reporting (sequential, after all pipelines settle)
This architecture yields near-linear speed-up for the vulnerability-analysis phase while preserving deterministic audit trails for initial reconnaissance and final report generation.
Practical Implementation Examples
Launching a Full Pentest via CLI
Start the complete parallel workflow from the command line:
./shannon start URL=https://target.example REPO=my-repo CONFIG=./configs/default.yaml
The CLI boots the Temporal worker and initiates pentestPipelineWorkflow, which automatically switches to parallel mode for the vulnerability-analysis phase.
Programmatic Launch with Testing Mode
For development or CI environments, enable fast retries while preserving parallel execution:
import { Connection } from '@temporalio/client';
import { pentestPipelineWorkflow } from './src/temporal/workflows.js';
async function launchTest() {
const connection = await Connection.connect();
const client = connection.workflowClient;
await client.start(pentestPipelineWorkflow, {
args: [{ webUrl: 'https://staging.example', pipelineTestingMode: true }],
taskQueue: 'shannon',
workflowId: `test-${Date.now()}`
});
console.log('Test workflow started – vulnerability agents will run in parallel.');
}
launchTest();
Setting pipelineTestingMode: true swaps the activity proxy to a testing retry configuration (10-second intervals) while maintaining the same parallel execution logic.
Debugging a Single Pipeline
Isolate individual vulnerability types for targeted debugging:
import { runVulnExploitPipeline } from './src/temporal/workflows.js';
import { activities } from './src/temporal/activities.js';
async function debugInjectionPipeline(activityInput) {
const result = await runVulnExploitPipeline(
'injection',
() => activities.runInjectionVulnAgent(activityInput),
() => activities.runInjectionExploitAgent(activityInput)
);
console.log('Injection pipeline result:', result);
}
This snippet bypasses Promise.allSettled, allowing developers to focus on one pipeline while preserving internal ordering and mutex protection.
Summary
- Shannon's parallel execution capabilities for vulnerability analysis leverage a Temporal workflow to run five specialized agents (injection, XSS, authentication, SSRF, authorization) concurrently during the pentest pipeline.
- The
getParallelGroupshelper insrc/session-manager.tsdefines which agents execute simultaneously, whilerunVulnExploitPipelineinsrc/temporal/workflows.tsmaintains direct pipelining from vulnerability detection to exploitation. Promise.allSettledensures fault isolation—failures in one pipeline do not abort others—whileSessionMutexinsrc/utils/concurrency.tsprevents race conditions during shared resource access.- This architecture delivers near-linear speed-up for the computationally intensive vulnerability-analysis phase while maintaining deterministic sequencing for pre-reconnaissance, reconnaissance, and reporting stages.
Frequently Asked Questions
How does Shannon prevent one failing vulnerability agent from crashing the entire pentest?
Shannon uses Promise.allSettled rather than Promise.all when launching the five vulnerability-exploit pipelines in src/temporal/workflows.ts. This JavaScript primitive waits for all promises to either fulfill or reject, meaning a crash in the SSRF agent does not reject the promise returned by the injection or XSS pipelines. The workflow aggregates results only after all agents have settled, allowing partial success scenarios and comprehensive reporting even when individual agents fail.
What is the relationship between vulnerability agents and exploit agents in Shannon's parallel architecture?
Each vulnerability agent feeds directly into its matching exploit agent through a pipelined execution model. The runVulnExploitPipeline function in src/temporal/workflows.ts encapsulates this flow: it first executes the vulnerability agent, immediately checks the exploitation queue via checkExploitationQueue, and conditionally runs the matching exploit agent if the vulnerability is confirmed. This pipelining occurs within each parallel branch, ensuring that exploitation begins immediately for a given vulnerability type without waiting for unrelated vulnerability agents to complete.
How does Shannon handle concurrent writes to shared session data during parallel execution?
Shannon implements a SessionMutex class in src/utils/concurrency.ts to serialize access to shared session resources. When parallel agents need to write to audit logs or deliverables, they acquire a lock on the session ID using await mutex.lock(sessionId). This Promise-based mutex ensures that only one agent modifies shared data at a time, preventing race conditions while allowing the agents themselves to run concurrently. The implementation supports async/await patterns compatible with Temporal's activity execution model and automatically releases locks via finally blocks to prevent deadlocks.
Can I run Shannon's vulnerability analysis phase in parallel while keeping other phases sequential?
Yes, Shannon's workflow architecture intentionally limits parallel execution to the vulnerability-analysis and exploitation phases while maintaining sequential ordering for pre-reconnaissance, reconnaissance, and reporting. The pentestPipelineWorkflow in src/temporal/workflows.ts executes the initial phases as discrete sequential activities, then switches to the parallel Promise.allSettled pattern for the five vulnerability-exploit pipelines, and finally aggregates results into a sequential reporting phase. This hybrid approach yields near-linear speed-up where computationally beneficial while preserving deterministic audit trails for initial reconnaissance and final report generation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →