sicario-red-team 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/sicario.js CHANGED
@@ -24,6 +24,7 @@ import { Command } from 'commander';
24
24
  import { pathToFileURL, fileURLToPath } from 'url';
25
25
  import pc from 'picocolors';
26
26
  import { getApiKey, setApiKey } from '../src-cli/utils/config.js';
27
+ import { Keymaster } from '../src-cli/services/keymaster.js';
27
28
  import { createRequire } from 'module';
28
29
  const require = createRequire(import.meta.url);
29
30
  const clack = require('@clack/prompts');
@@ -68,6 +69,7 @@ program
68
69
  .option('--swarm', 'Deploy multiple specialized nodes in parallel')
69
70
  .option('--tier <level>', 'Sicario Tier (SHADOW|OPERATOR|CARTEL)', 'SHADOW')
70
71
  .option('--auth <string>', 'Session token or cookie string for authenticated scans')
72
+ .option('--intent <string>', 'Focus swarm on a specific red-team intent (e.g. "bypass billing")')
71
73
  .action(async (posTarget, options) => {
72
74
  try {
73
75
  const finalTarget = posTarget || options.target; // Support both styles
@@ -103,6 +105,13 @@ program
103
105
  }
104
106
 
105
107
  console.log(`\x1b[1m\x1b[32m[+] DEPLOYING SICARIO RED-TEAM SWARM v${pkg.version}\x1b[0m`);
108
+
109
+ // Auto-Vault Detection
110
+ if (!options.auth && Keymaster.hasVault()) {
111
+ console.log(`\x1b[36m[*] Keymaster: Vaulted session detected. Injecting into swarm...\x1b[0m`);
112
+ options.vault = Keymaster.getVaultPath();
113
+ }
114
+
106
115
  // Premium Boot Sequence
107
116
  await bootSwarm();
108
117
 
@@ -122,11 +131,19 @@ program
122
131
  .description('Launch a Sustained Siege (Continuous Monitoring)')
123
132
  .argument('[target]', 'Target URL')
124
133
  .option('-t, --target <url>', 'Target URL')
134
+ .option('--intent <string>', 'Specific red-team intent for the siege')
125
135
  .action(async (posTarget, options) => {
126
136
  try {
127
137
  options.target = posTarget || options.target;
128
138
 
129
139
  console.log(`\x1b[1m\x1b[32m[+] INITIATING SUSTAINED SICARIO SIEGE v${pkg.version}\x1b[0m`);
140
+
141
+ // Auto-Vault Detection
142
+ if (!options.auth && Keymaster.hasVault()) {
143
+ console.log(`\x1b[36m[*] Keymaster: Vaulted session detected. Injecting into siege overwatch...\x1b[0m`);
144
+ options.vault = Keymaster.getVaultPath();
145
+ }
146
+
130
147
  // Premium Boot Sequence
131
148
  await bootSwarm();
132
149
 
@@ -139,6 +156,54 @@ program
139
156
  }
140
157
  });
141
158
 
159
+ program
160
+ .command('auth')
161
+ .description('Human-in-the-loop session extraction (The Keymaster)')
162
+ .argument('[target]', 'Target login URL')
163
+ .action(async (target) => {
164
+ const keymaster = new Keymaster();
165
+ const finalTarget = target || await clack.text({
166
+ message: 'Establish breach point (Login URL)',
167
+ placeholder: 'https://example.com/login'
168
+ });
169
+
170
+ if (clack.isCancel(finalTarget)) {
171
+ clack.cancel('Operation aborted.');
172
+ process.exit(0);
173
+ }
174
+
175
+ await keymaster.captureSession(finalTarget);
176
+ });
177
+
178
+ const watchCommandPath = pathToFileURL(path.join(__dirname, '../src-cli/commands/watch.js')).href;
179
+
180
+ program
181
+ .command('watch')
182
+ .description('Continuous Localhost Siege (Lazy Watcher)')
183
+ .argument('[target]', 'Target URL')
184
+ .option('-t, --target <url>', 'Target URL')
185
+ .action(async (posTarget, options) => {
186
+ try {
187
+ options.target = posTarget || options.target;
188
+
189
+ console.log(`\x1b[1m\x1b[32m[+] ACTIVATING LAZY WATCHER v${pkg.version}\x1b[0m`);
190
+
191
+ if (!options.auth && Keymaster.hasVault()) {
192
+ console.log(`\x1b[36m[*] Keymaster: Vaulted session detected. Injecting into watcher...\x1b[0m`);
193
+ options.vault = Keymaster.getVaultPath();
194
+ }
195
+
196
+ await bootSwarm();
197
+
198
+ const { watchCommand } = await import(watchCommandPath);
199
+ await watchCommand(options.target, options);
200
+ } catch (err) {
201
+ console.error('Fatal: Failed to load watcher command logic.');
202
+ console.error(err);
203
+ process.exit(1);
204
+ }
205
+ });
206
+
142
207
  try {
143
208
  program.parse(process.argv);
144
209
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sicario-red-team",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "type": "module",
5
5
  "description": "Autonomous Agentic Red-Teaming Swarm Protocol",
6
6
  "repository": {
@@ -8,6 +8,8 @@ import { ConvexClient } from 'convex/browser';
8
8
  import { runScout } from '../nodes/scout.js';
9
9
  import { runBreacher } from '../nodes/breacher.js';
10
10
  import { CriticNode } from '../nodes/critic.js';
11
+ import { runScribe } from '../nodes/scribe.js';
12
+ import { translateIntent } from '../utils/llm.js';
11
13
  import { theme } from '../utils/theme.js';
12
14
 
13
15
  // Initialize Convex Client (will use CONVEX_URL from .env)
@@ -37,6 +39,14 @@ export async function hitCommand(target, options) {
37
39
  const CURRENT_TIER = (options.tier || 'SHADOW').toUpperCase();
38
40
  log.info(pc.magenta(`◈ LICENSE TIER: ${pc.bold(CURRENT_TIER)}`));
39
41
 
42
+ // 1. Intent Translation (The Swarm Strategist Node)
43
+ let intentVectors = null;
44
+ if (options.intent) {
45
+ log.step(`[System] : Translating intent into specialized attack vectors...`);
46
+ intentVectors = await translateIntent(options.intent);
47
+ log.info(pc.magenta(`◈ INTENT VECTORS: ${intentVectors.join(', ')}`));
48
+ }
49
+
40
50
  // 2. Bounded Autonomy Manifest (The 2026 Trust Layer)
41
51
  console.log(pc.dim('\n┌ AGENT PERMISSIONS MANIFEST ─── (READ-ONLY) ──────╮'));
42
52
  console.log(pc.dim('│ ✓ DOM Observation : AUTHORIZED │'));
@@ -143,6 +153,13 @@ export async function hitCommand(target, options) {
143
153
  clean.thoughtProcess.includes("Architect") ? "THE ARCHITECT" :
144
154
  clean.thoughtProcess.includes("Ghost") ? "THE GHOST NODE" : "GENERAL BREACHER";
145
155
 
156
+ // 6.1 [Scribe] Remediation Generation (Strictly gated by Critic results)
157
+ let scribePatch = null;
158
+ if (isReal) {
159
+ log.step(`[Scribe] : Automating remedial code patch...`);
160
+ scribePatch = await runScribe(breachReport, audit);
161
+ }
162
+
146
163
  console.log('\n' + pc.bold(pc.red(` ⚠ EXPLOIT SUCCESSFUL [${clean.title}]`)));
147
164
  console.log(pc.cyan(` ◇ AGENT IDENTIFIED: ${nodeName}`));
148
165
  console.log(pc.red(` Vector: ${clean.vector}`));
@@ -191,6 +208,13 @@ export async function hitCommand(target, options) {
191
208
  console.log(pc.white(drawBoxRow(`Visit sicario-red-team.com to unlock the patch.`, boxWidth)));
192
209
  }
193
210
 
211
+ if (scribePatch) {
212
+ console.log(pc.green(`├${'─'.repeat(boxWidth - 2)}┤`));
213
+ console.log(pc.green(`│ ${pc.bold('SCRIBE REMEDIATION PATCH (CURSOR-READY)').padEnd(boxWidth - 4)} │`));
214
+ const scribeLines = wrap(scribePatch, boxWidth - 4);
215
+ scribeLines.forEach(line => console.log(pc.green(drawBoxRow(line, boxWidth))));
216
+ }
217
+
194
218
  console.log(pc.cyan(`├${'─'.repeat(boxWidth - 2)}╯`) + '\n');
195
219
  }
196
220
  }
@@ -0,0 +1,57 @@
1
+ import { hitCommand } from './hit.js';
2
+ import { runScout } from '../nodes/scout.js';
3
+ import clack from '@clack/prompts';
4
+ const { log } = clack;
5
+ import pc from 'picocolors';
6
+
7
+ /**
8
+ * Lazy Watcher: Performs continuous monitoring with heavy debouncing and DOM diffing.
9
+ * Goal: Zero API calls if no structural changes are detected.
10
+ */
11
+ export async function watchCommand(target, options) {
12
+ let lastElementsHash = null;
13
+ let debounceTime = 15000; // 15 seconds as requested
14
+
15
+ log.step(pc.cyan(`[Watcher] : Initiating Lazy Watcher for ${target}...`));
16
+ log.info(pc.dim(`Status: Monitoring structure. Min cooldown: 15s. API calls only on change.`));
17
+
18
+ // Initial run
19
+ try {
20
+ await hitCommand(target, options);
21
+ } catch (e) {}
22
+
23
+ while (true) {
24
+ try {
25
+ // 1. Silent Recon (Scout node - browser based, but local cost)
26
+ const elements = await runScout(target, options);
27
+
28
+ // Generate a structural hash (tags, types, and names)
29
+ const structuralElements = elements.map(e => ({
30
+ tag: e.tag,
31
+ id: e.id,
32
+ name: e.name,
33
+ type: e.type
34
+ }));
35
+ const currentHash = JSON.stringify(structuralElements);
36
+
37
+ if (currentHash !== lastElementsHash) {
38
+ if (lastElementsHash !== null) {
39
+ log.step(pc.yellow(`\n[Watcher] : Structural change detected. Initializing mini-siege...`));
40
+ // Trigger the hit
41
+ await hitCommand(target, options);
42
+ }
43
+ lastElementsHash = currentHash;
44
+ } else {
45
+ // No change, just log a heartbeat in debug mode if needed
46
+ process.stdout.write(pc.dim('.'));
47
+ }
48
+
49
+ // Wait for 15s before next check
50
+ await new Promise(r => setTimeout(r, debounceTime));
51
+
52
+ } catch (err) {
53
+ log.error(`[Watcher] : Connection error. Retrying...`);
54
+ await new Promise(r => setTimeout(r, 5000));
55
+ }
56
+ }
57
+ }
@@ -11,7 +11,14 @@ import path from 'path';
11
11
  */
12
12
  export async function runScout(url, options = {}) {
13
13
  const browser = await chromium.launch({ headless: true });
14
- const context = await browser.newContext();
14
+
15
+ // 0. Keymaster Session Injection (storageState)
16
+ const contextOptions = {};
17
+ if (options.vault && fs.existsSync(options.vault)) {
18
+ contextOptions.storageState = options.vault;
19
+ }
20
+
21
+ const context = await browser.newContext(contextOptions);
15
22
 
16
23
  // 0. Session Injection (The Authentication Engine)
17
24
  if (options.auth) {
@@ -0,0 +1,42 @@
1
+ import Cerebras from '@cerebras/cerebras_cloud_sdk';
2
+ import 'dotenv/config';
3
+
4
+ /**
5
+ * The Scribe Node: Generates "Cursor-ready" patches and remediation prompts.
6
+ * Strictly gated by the Critic node to stay within Cerebras Free Tier limits.
7
+ */
8
+ export async function runScribe(breachReport, audit) {
9
+ const client = new Cerebras({
10
+ apiKey: process.env.CEREBRAS_API_KEY,
11
+ });
12
+
13
+ const systemPrompt = `
14
+ You are 'The Scribe' node of the Sicario Red-Teaming Swarm.
15
+ Your goal is to provide a "Cursor-ready" remediation prompt that a developer can paste into their AI code editor to fix a confirmed vulnerability.
16
+
17
+ VULNERABILITY: ${breachReport.title}
18
+ VECTOR: ${breachReport.vector}
19
+ CRITIC JUSTIFICATION: ${audit.reasoning}
20
+
21
+ INSTRUCTIONS:
22
+ 1. Provide a concise, clinical description of the fix.
23
+ 2. Provide a "Cursor Prompt" (a prompt for another AI to use) enclosed in triple backticks.
24
+ 3. Keep it brief to save on outbound tokens.
25
+ `;
26
+
27
+ try {
28
+ const completion = await client.chat.completions.create({
29
+ messages: [
30
+ { role: 'system', content: systemPrompt },
31
+ { role: 'user', content: 'Generate remediation prompt.' }
32
+ ],
33
+ model: 'llama3.1-8b', // Using the faster, cheaper 8B model as requested
34
+ temperature: 0.1,
35
+ max_tokens: 300
36
+ });
37
+
38
+ return completion.choices[0].message.content;
39
+ } catch (error) {
40
+ return "Scribe node offline: Mitigation deferred to manual review.";
41
+ }
42
+ }
@@ -0,0 +1,70 @@
1
+ import { chromium } from 'playwright';
2
+ import fs from 'fs';
3
+ import readline from 'readline';
4
+ import path from 'path';
5
+ import pc from 'picocolors';
6
+
7
+ const VAULT_FILE = path.join(process.cwd(), '.sicario-vault.json');
8
+
9
+ /**
10
+ * Keymaster Service: Handles session state extraction and vaulting.
11
+ * Supports Human-in-the-loop (HITL) authentication for enterprise targets.
12
+ */
13
+ export class Keymaster {
14
+ constructor() {
15
+ this.rl = readline.createInterface({
16
+ input: process.stdin,
17
+ output: process.stdout
18
+ });
19
+ }
20
+
21
+ /**
22
+ * Phase 1: Human-in-the-loop Session Capture.
23
+ * Opens a visible browser for the user to authenticate manually.
24
+ */
25
+ async captureSession(targetUrl) {
26
+ console.log(`\n${pc.cyan('[?] Keymaster initiating manual breach on:')} ${pc.bold(targetUrl)}`);
27
+ console.log(` ${pc.yellow('[!] Action Required: A browser will open. Log in, pass MFA, and navigate to the dashboard.')}`);
28
+
29
+ try {
30
+ // Launch visible browser for the human operator
31
+ const browser = await chromium.launch({ headless: false });
32
+ const context = await browser.newContext();
33
+ const page = await context.newPage();
34
+
35
+ await page.goto(targetUrl);
36
+
37
+ // Wait for the operator to signal the breach is complete
38
+ await new Promise((resolve) => {
39
+ this.rl.question(`\n${pc.green('[+] Press [ENTER] here when you are fully logged in and ready for state extraction...')}`, resolve);
40
+ });
41
+
42
+ // Extract the state (Cookies, LocalStorage, etc.)
43
+ await context.storageState({ path: VAULT_FILE });
44
+
45
+ await browser.close();
46
+ this.rl.close();
47
+
48
+ console.log(`\n${pc.green('[✔] Session Extracted and Vaulted successfully.')}`);
49
+ console.log(` ${pc.red('[!] CRITICAL: Ensure .sicario-vault.json is in your .gitignore')}\n`);
50
+ } catch (err) {
51
+ console.error(pc.red(`\n[X] Keymaster capture failed: ${err.message}`));
52
+ this.rl.close();
53
+ process.exit(1);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Returns the absolute path to the session vault.
59
+ */
60
+ static getVaultPath() {
61
+ return VAULT_FILE;
62
+ }
63
+
64
+ /**
65
+ * Checks if a vaulted session exists.
66
+ */
67
+ static hasVault() {
68
+ return fs.existsSync(VAULT_FILE);
69
+ }
70
+ }
@@ -0,0 +1,38 @@
1
+ import Cerebras from '@cerebras/cerebras_cloud_sdk';
2
+ import 'dotenv/config';
3
+
4
+ /**
5
+ * Translates a high-level security intent into specific, actionable attack vectors.
6
+ * Costs exactly 1 API call per siege to Llama 8B.
7
+ */
8
+ export async function translateIntent(intent) {
9
+ const client = new Cerebras({
10
+ apiKey: process.env.CEREBRAS_API_KEY,
11
+ });
12
+
13
+ const systemPrompt = `
14
+ You are the "Swarm Strategist" for the Sicario Red-Teaming protocol.
15
+ The operator provided a target intent: "${intent}".
16
+
17
+ Your task: Translate this intent into 5 specific, technical attack vectors that node-based agents (Accountant, Admin, Chaos Monkey, Architect, Ghost) should look for in a DOM structure.
18
+
19
+ REPLY ONLY WITH A COMMA-SEPARATED LIST OF 5 BRIEF TECHNICAL VECTORS.
20
+ `;
21
+
22
+ try {
23
+ const completion = await client.chat.completions.create({
24
+ messages: [
25
+ { role: 'system', content: systemPrompt },
26
+ { role: 'user', content: 'Generate tactical vectors.' }
27
+ ],
28
+ model: 'llama3.1-8b',
29
+ temperature: 0.1,
30
+ max_tokens: 100
31
+ });
32
+
33
+ const rawResult = completion.choices[0].message.content.trim();
34
+ return rawResult.split(',').map(s => s.trim());
35
+ } catch (error) {
36
+ return ["Session State Bypass", "Hidden Field Manipulation", "Horizontal Privilege Escalation", "Input Sanitization Bypass", "Logic State Machine Exploitation"];
37
+ }
38
+ }