@keygraph/shannon 1.7.0 → 2.0.0-beta.2

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.
Files changed (2) hide show
  1. package/dist/index.mjs +15 -163
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -236,7 +236,6 @@ function spawnWorker(opts) {
236
236
  if (opts.promptsDir) args.push("-v", `${opts.promptsDir}:/app/apps/worker/prompts:ro`);
237
237
  if (opts.config) args.push("-v", `${opts.config.hostPath}:${opts.config.containerPath}:ro`);
238
238
  if (opts.outputDir) args.push("-v", `${opts.outputDir}:/app/output`);
239
- if (opts.credentials) args.push("-v", `${opts.credentials}:/app/credentials/google-sa-key.json:ro`);
240
239
  args.push(...opts.envFlags);
241
240
  args.push("--shm-size", "2gb", "--security-opt", "seccomp=unconfined");
242
241
  args.push(getWorkerImage(opts.version));
@@ -334,7 +333,7 @@ function build(noCache) {
334
333
  /**
335
334
  * Shannon state directory management.
336
335
  *
337
- * Local mode (cloned repo): uses ./workspaces/, ./credentials/
336
+ * Local mode (cloned repo): uses ./workspaces/
338
337
  * NPX mode: uses ~/.shannon/workspaces/, ~/.shannon/
339
338
  */
340
339
  const SHANNON_HOME$2 = path.join(os.homedir(), ".shannon");
@@ -345,27 +344,13 @@ function getWorkspacesDir() {
345
344
  return getMode() === "local" ? path.resolve("workspaces") : path.join(SHANNON_HOME$2, "workspaces");
346
345
  }
347
346
  /**
348
- * Resolve the Vertex credentials file path.
349
- *
350
- * Checks GOOGLE_APPLICATION_CREDENTIALS env var first (may be set by TOML resolver),
351
- * then falls back to mode-appropriate default location.
352
- */
353
- function getCredentialsPath() {
354
- const envPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
355
- if (envPath && fs.existsSync(envPath)) return path.resolve(envPath);
356
- if (getMode() === "local") return path.resolve("credentials", "google-sa-key.json");
357
- return path.join(SHANNON_HOME$2, "google-sa-key.json");
358
- }
359
- /**
360
347
  * Initialize state directories.
361
- * Local mode: creates ./workspaces/ and ./credentials/
348
+ * Local mode: creates ./workspaces/
362
349
  * NPX mode: creates ~/.shannon/workspaces/
363
350
  */
364
351
  function initHome() {
365
- if (getMode() === "local") {
366
- fs.mkdirSync(path.resolve("workspaces"), { recursive: true });
367
- fs.mkdirSync(path.resolve("credentials"), { recursive: true });
368
- } else fs.mkdirSync(path.join(SHANNON_HOME$2, "workspaces"), { recursive: true });
352
+ if (getMode() === "local") fs.mkdirSync(path.resolve("workspaces"), { recursive: true });
353
+ else fs.mkdirSync(path.join(SHANNON_HOME$2, "workspaces"), { recursive: true });
369
354
  }
370
355
  //#endregion
371
356
  //#region src/commands/logs.ts
@@ -481,10 +466,6 @@ async function setup() {
481
466
  {
482
467
  value: "bedrock",
483
468
  label: "Claude via AWS Bedrock"
484
- },
485
- {
486
- value: "vertex",
487
- label: "Claude via Google Vertex AI"
488
469
  }
489
470
  ]
490
471
  });
@@ -494,14 +475,13 @@ async function setup() {
494
475
  saveConfig(config);
495
476
  const configPath = path.join(SHANNON_HOME$1, "config.toml");
496
477
  p.log.success(`Configuration saved to ${configPath}`);
497
- p.outro("Run `npx @keygraph/shannon start` to begin a scan.");
478
+ p.outro("Run `npx @keygraph/shannon@beta start` to begin a scan.");
498
479
  }
499
480
  async function setupProvider(provider) {
500
481
  switch (provider) {
501
482
  case "anthropic": return setupAnthropic();
502
483
  case "custom_base_url": return setupCustomBaseUrl();
503
484
  case "bedrock": return setupBedrock();
504
- case "vertex": return setupVertex();
505
485
  }
506
486
  }
507
487
  async function setupAnthropic() {
@@ -640,65 +620,6 @@ async function setupBedrock() {
640
620
  }
641
621
  };
642
622
  }
643
- async function setupVertex() {
644
- const region = await p.text({
645
- message: "Google Cloud region",
646
- placeholder: "us-east5",
647
- validate: required("Region is required")
648
- });
649
- if (p.isCancel(region)) return cancelAndExit();
650
- const projectId = await p.text({
651
- message: "GCP Project ID",
652
- validate: required("Project ID is required")
653
- });
654
- if (p.isCancel(projectId)) return cancelAndExit();
655
- p.log.info("Select the path to your GCP Service Account JSON key file.");
656
- const keySourcePath = await p.path({
657
- message: "Service Account JSON key file",
658
- validate: (value) => {
659
- if (!value) return "Path is required";
660
- if (!fs.existsSync(value)) return "File not found";
661
- if (!value.endsWith(".json")) return "Must be a .json file";
662
- }
663
- });
664
- if (p.isCancel(keySourcePath)) return cancelAndExit();
665
- const destPath = path.join(SHANNON_HOME$1, "google-sa-key.json");
666
- fs.mkdirSync(SHANNON_HOME$1, { recursive: true });
667
- fs.copyFileSync(keySourcePath, destPath);
668
- fs.chmodSync(destPath, 384);
669
- p.log.success(`Key copied to ${destPath} (permissions: 0600)`);
670
- const models = await p.group({
671
- small: () => p.text({
672
- message: "Small model ID",
673
- placeholder: "claude-haiku-4-5@20251001",
674
- validate: required("Small model ID is required")
675
- }),
676
- medium: () => p.text({
677
- message: "Medium model ID",
678
- placeholder: "claude-sonnet-4-6",
679
- validate: required("Medium model ID is required")
680
- }),
681
- large: () => p.text({
682
- message: "Large model ID",
683
- placeholder: "claude-opus-4-8",
684
- validate: required("Large model ID is required")
685
- })
686
- });
687
- if (p.isCancel(models)) return cancelAndExit();
688
- return {
689
- vertex: {
690
- use: true,
691
- region,
692
- project_id: projectId,
693
- key_path: destPath
694
- },
695
- models: {
696
- small: models.small,
697
- medium: models.medium,
698
- large: models.large
699
- }
700
- };
701
- }
702
623
  async function maybePromptAdaptiveThinking(config) {
703
624
  const m = config.models;
704
625
  if (!(!m || [
@@ -743,11 +664,6 @@ function cancelAndExit() {
743
664
  */
744
665
  /** Maps every supported env var to its TOML path (section.key) and expected type. */
745
666
  const CONFIG_MAP = [
746
- {
747
- env: "CLAUDE_CODE_MAX_OUTPUT_TOKENS",
748
- toml: "core.max_tokens",
749
- type: "number"
750
- },
751
667
  {
752
668
  env: "CLAUDE_ADAPTIVE_THINKING",
753
669
  toml: "core.adaptive_thinking",
@@ -779,26 +695,6 @@ const CONFIG_MAP = [
779
695
  toml: "bedrock.token",
780
696
  type: "string"
781
697
  },
782
- {
783
- env: "CLAUDE_CODE_USE_VERTEX",
784
- toml: "vertex.use",
785
- type: "boolean"
786
- },
787
- {
788
- env: "CLOUD_ML_REGION",
789
- toml: "vertex.region",
790
- type: "string"
791
- },
792
- {
793
- env: "ANTHROPIC_VERTEX_PROJECT_ID",
794
- toml: "vertex.project_id",
795
- type: "string"
796
- },
797
- {
798
- env: "GOOGLE_APPLICATION_CREDENTIALS",
799
- toml: "vertex.key_path",
800
- type: "string"
801
- },
802
698
  {
803
699
  env: "ANTHROPIC_BASE_URL",
804
700
  toml: "custom_base_url.base_url",
@@ -856,7 +752,7 @@ function loadTOML() {
856
752
  } catch (err) {
857
753
  const message = err instanceof Error ? err.message : String(err);
858
754
  console.error(`\nFailed to parse ${configPath}: ${message}`);
859
- console.error(`\nRun 'npx @keygraph/shannon setup' to reconfigure.\n`);
755
+ console.error(`\nRun 'npx @keygraph/shannon@beta setup' to reconfigure.\n`);
860
756
  process.exit(1);
861
757
  }
862
758
  }
@@ -899,20 +795,9 @@ function validateProviderFields(config, provider, errors) {
899
795
  validateModelTiers(config, "bedrock", errors);
900
796
  break;
901
797
  }
902
- case "vertex": {
903
- const missing = [
904
- "use",
905
- "region",
906
- "project_id",
907
- "key_path"
908
- ].filter((k) => !keys.includes(k));
909
- if (missing.length > 0) errors.push(`[vertex] missing required keys: ${missing.join(", ")}`);
910
- validateModelTiers(config, "vertex", errors);
911
- break;
912
- }
913
798
  }
914
799
  }
915
- /** Bedrock and Vertex require a [models] section with all three tiers. */
800
+ /** Bedrock requires a [models] section with all three tiers. */
916
801
  function validateModelTiers(config, provider, errors) {
917
802
  const models = config.models;
918
803
  if (!models || typeof models !== "object") {
@@ -961,8 +846,7 @@ function validateConfig(config) {
961
846
  const present = [
962
847
  "anthropic",
963
848
  "custom_base_url",
964
- "bedrock",
965
- "vertex"
849
+ "bedrock"
966
850
  ].filter((s) => {
967
851
  const section = config[s];
968
852
  return section && typeof section === "object" && Object.keys(section).length > 0;
@@ -1014,14 +898,9 @@ const FORWARD_VARS = [
1014
898
  "CLAUDE_CODE_USE_BEDROCK",
1015
899
  "AWS_REGION",
1016
900
  "AWS_BEARER_TOKEN_BEDROCK",
1017
- "CLAUDE_CODE_USE_VERTEX",
1018
- "CLOUD_ML_REGION",
1019
- "ANTHROPIC_VERTEX_PROJECT_ID",
1020
- "GOOGLE_APPLICATION_CREDENTIALS",
1021
901
  "ANTHROPIC_SMALL_MODEL",
1022
902
  "ANTHROPIC_MEDIUM_MODEL",
1023
903
  "ANTHROPIC_LARGE_MODEL",
1024
- "CLAUDE_CODE_MAX_OUTPUT_TOKENS",
1025
904
  "CLAUDE_ADAPTIVE_THINKING"
1026
905
  ];
1027
906
  /**
@@ -1059,7 +938,6 @@ function detectProviders() {
1059
938
  if (process.env.CLAUDE_CODE_OAUTH_TOKEN) providers.push("Anthropic OAuth");
1060
939
  if (isCustomBaseUrlConfigured()) providers.push("Custom Base URL");
1061
940
  if (process.env.CLAUDE_CODE_USE_BEDROCK === "1") providers.push("AWS Bedrock");
1062
- if (process.env.CLAUDE_CODE_USE_VERTEX === "1") providers.push("Google Vertex");
1063
941
  return providers;
1064
942
  }
1065
943
  /**
@@ -1101,32 +979,10 @@ function validateCredentials() {
1101
979
  mode: "bedrock"
1102
980
  };
1103
981
  }
1104
- if (process.env.CLAUDE_CODE_USE_VERTEX === "1") {
1105
- const missing = [];
1106
- if (!process.env.CLOUD_ML_REGION) missing.push("CLOUD_ML_REGION");
1107
- if (!process.env.ANTHROPIC_VERTEX_PROJECT_ID) missing.push("ANTHROPIC_VERTEX_PROJECT_ID");
1108
- if (!process.env.ANTHROPIC_SMALL_MODEL) missing.push("ANTHROPIC_SMALL_MODEL");
1109
- if (!process.env.ANTHROPIC_MEDIUM_MODEL) missing.push("ANTHROPIC_MEDIUM_MODEL");
1110
- if (!process.env.ANTHROPIC_LARGE_MODEL) missing.push("ANTHROPIC_LARGE_MODEL");
1111
- if (missing.length > 0) return {
1112
- valid: false,
1113
- mode: "vertex",
1114
- error: `Vertex AI mode requires: ${missing.join(", ")}`
1115
- };
1116
- if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) return {
1117
- valid: false,
1118
- mode: "vertex",
1119
- error: "Vertex AI mode requires GOOGLE_APPLICATION_CREDENTIALS"
1120
- };
1121
- return {
1122
- valid: true,
1123
- mode: "vertex"
1124
- };
1125
- }
1126
982
  return {
1127
983
  valid: false,
1128
984
  mode: "api-key",
1129
- error: getMode() === "local" ? `No credentials found. Set ANTHROPIC_API_KEY in .env or export it.` : `Authentication not configured. Export variables or run 'npx @keygraph/shannon setup'.`
985
+ error: getMode() === "local" ? `No credentials found. Set ANTHROPIC_API_KEY in .env or export it.` : `Authentication not configured. Export variables or run 'npx @keygraph/shannon@beta setup'.`
1130
986
  };
1131
987
  }
1132
988
  //#endregion
@@ -1273,9 +1129,6 @@ async function start(args) {
1273
1129
  ".playwright-cli"
1274
1130
  ]) fs.mkdirSync(path.join(shannonDir, dir), { recursive: true });
1275
1131
  fs.mkdirSync(path.join(repo.hostPath, ".playwright"), { recursive: true });
1276
- const credentialsPath = getCredentialsPath();
1277
- const hasCredentials = fs.existsSync(credentialsPath);
1278
- if (hasCredentials) process.env.GOOGLE_APPLICATION_CREDENTIALS = "/app/credentials/google-sa-key.json";
1279
1132
  const outputDir = args.output ? path.resolve(args.output) : void 0;
1280
1133
  if (outputDir) fs.mkdirSync(outputDir, { recursive: true });
1281
1134
  const promptsDir = isLocal() ? path.resolve("apps/worker/prompts") : void 0;
@@ -1289,7 +1142,6 @@ async function start(args) {
1289
1142
  containerName,
1290
1143
  envFlags: buildEnvFlags(),
1291
1144
  ...config && { config },
1292
- ...hasCredentials && { credentials: credentialsPath },
1293
1145
  ...promptsDir && { promptsDir },
1294
1146
  ...outputDir && { outputDir },
1295
1147
  workspace,
@@ -1364,7 +1216,7 @@ function printDebugHint(containerName) {
1364
1216
  console.log("");
1365
1217
  }
1366
1218
  function printInfo(args, workspace, workflowId, repoPath, workspacesDir) {
1367
- const logsCmd = isLocal() ? `./shannon logs ${workspace}` : `npx @keygraph/shannon logs ${workspace}`;
1219
+ const logsCmd = isLocal() ? `./shannon logs ${workspace}` : `npx @keygraph/shannon@beta logs ${workspace}`;
1368
1220
  const reportsPath = path.join(workspacesDir, workspace);
1369
1221
  console.log(` Target: ${args.url}`);
1370
1222
  console.log(` Repository: ${repoPath}`);
@@ -1448,7 +1300,7 @@ async function uninstall() {
1448
1300
  force: true
1449
1301
  });
1450
1302
  p.log.success("All Shannon data has been removed.");
1451
- p.outro("Shannon has been uninstalled. Run `npx @keygraph/shannon setup` to start fresh.");
1303
+ p.outro("Shannon has been uninstalled. Run `npx @keygraph/shannon@beta setup` to start fresh.");
1452
1304
  }
1453
1305
  //#endregion
1454
1306
  //#region src/commands/workspaces.ts
@@ -1522,7 +1374,7 @@ function getVersion() {
1522
1374
  }
1523
1375
  function showHelp() {
1524
1376
  const mode = getMode();
1525
- const prefix = mode === "local" ? "./shannon" : "npx @keygraph/shannon";
1377
+ const prefix = mode === "local" ? "./shannon" : "npx @keygraph/shannon@beta";
1526
1378
  console.log(`
1527
1379
  Shannon - AI Penetration Testing Framework
1528
1380
 
@@ -1613,13 +1465,13 @@ function parseStartArgs(argv) {
1613
1465
  break;
1614
1466
  default:
1615
1467
  console.error(`Unknown option: ${arg}`);
1616
- console.error(`Run "${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon"} help" for usage`);
1468
+ console.error(`Run "${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon@beta"} help" for usage`);
1617
1469
  process.exit(1);
1618
1470
  }
1619
1471
  }
1620
1472
  if (!url || !repo) {
1621
1473
  console.error("ERROR: --url and --repo are required");
1622
- console.error(`Usage: ${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon"} start -u <url> -r <path>`);
1474
+ console.error(`Usage: ${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon@beta"} start -u <url> -r <path>`);
1623
1475
  process.exit(1);
1624
1476
  }
1625
1477
  return {
@@ -1649,7 +1501,7 @@ switch (command) {
1649
1501
  const workspaceId = args[1];
1650
1502
  if (!workspaceId) {
1651
1503
  console.error("ERROR: Workspace ID is required");
1652
- console.error(`Usage: ${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon"} logs <workspace>`);
1504
+ console.error(`Usage: ${getMode() === "local" ? "./shannon" : "npx @keygraph/shannon@beta"} logs <workspace>`);
1653
1505
  process.exit(1);
1654
1506
  }
1655
1507
  logs(workspaceId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keygraph/shannon",
3
- "version": "1.7.0",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "Shannon - Autonomous white-box AI pentester for web applications and APIs by Keygraph",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",