0sec-cli 0.22.0 → 0.22.4

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 (107) hide show
  1. package/0.js +56 -45
  2. package/README.md +12 -0
  3. package/chunks/{adapt-loop-7I57LXXR.js → adapt-loop-3CCOWE43.js} +4 -4
  4. package/chunks/{artifact-scraper-PYZ3RU3O.js → artifact-scraper-Z4UUIOH3.js} +2 -2
  5. package/chunks/{assumption-mining-MFLF43IR.js → assumption-mining-2UAKQB6V.js} +18 -14
  6. package/chunks/{chunk-RE5EZDG2.js → chunk-2WWAPKAW.js} +126 -1089
  7. package/chunks/{chunk-LPTRPRZR.js → chunk-3BPX75OR.js} +1 -1
  8. package/chunks/chunk-4ZYYX5GY.js +74 -0
  9. package/chunks/{chunk-RSIUX3RW.js → chunk-5JNTMWPK.js} +2 -2
  10. package/chunks/{chunk-RRD4XXPU.js → chunk-5WAJGLCW.js} +3 -3
  11. package/chunks/{chunk-76KSBWOQ.js → chunk-6KFB6AYN.js} +515 -20
  12. package/chunks/{chunk-HR2TU42B.js → chunk-6WQDXWQC.js} +169 -15
  13. package/chunks/chunk-6YZE552K.js +5603 -0
  14. package/chunks/chunk-BGX53365.js +309 -0
  15. package/chunks/{chunk-7DEHG7YT.js → chunk-C6JPA32H.js} +1 -1
  16. package/chunks/chunk-CF3MNS3O.js +990 -0
  17. package/chunks/{chunk-4VGLO2YS.js → chunk-CPCHLL6A.js} +5 -2
  18. package/chunks/{chunk-DM5C5L5D.js → chunk-DPUXXMJW.js} +1 -1
  19. package/chunks/{chunk-LYUAM3TG.js → chunk-E3OOBVOK.js} +30 -12
  20. package/chunks/{chunk-HUNAPTKV.js → chunk-E74LXQFY.js} +1 -1
  21. package/chunks/{chunk-UU7PQP6N.js → chunk-ELI3BVIK.js} +3 -3
  22. package/chunks/chunk-FFHRANYC.js +547 -0
  23. package/chunks/{chunk-IO7R7WBM.js → chunk-G2BE2FC7.js} +1 -1
  24. package/chunks/chunk-GQ3DGHWE.js +1659 -0
  25. package/chunks/{chunk-V36HVTUL.js → chunk-GVY3S5E5.js} +21 -18
  26. package/chunks/{chunk-UV5QWZGE.js → chunk-H4DH7COV.js} +192 -40
  27. package/chunks/{chunk-SJBCK2EI.js → chunk-H6Q2QAIY.js} +23475 -22747
  28. package/chunks/{chunk-VMRRNRMR.js → chunk-IHPTOTLL.js} +1 -1
  29. package/chunks/chunk-IXAHQICR.js +31 -0
  30. package/chunks/{chunk-TH2LW437.js → chunk-KCA35IL3.js} +2 -190
  31. package/chunks/{chunk-VNRY6AWF.js → chunk-L2CCO4KE.js} +282 -34
  32. package/chunks/{chunk-6YNKRUMC.js → chunk-NJLKFC66.js} +321 -5
  33. package/chunks/{chunk-W6UWZFKL.js → chunk-O6KPVYOI.js} +100 -5
  34. package/chunks/{chunk-EGZGZFAH.js → chunk-OAS5SAVZ.js} +6768 -2100
  35. package/chunks/chunk-PS5E7LUQ.js +277 -0
  36. package/chunks/{chunk-2GV4HQKE.js → chunk-QVIRWJ45.js} +257 -145
  37. package/chunks/{chunk-OWLJYJ5O.js → chunk-QWK4R3DB.js} +9 -9
  38. package/chunks/{chunk-XFCTUKXR.js → chunk-RCRTSKQN.js} +1 -1
  39. package/chunks/chunk-RS4MAN3Q.js +73 -0
  40. package/chunks/{chunk-7UFUALR2.js → chunk-RTBZ36BD.js} +8 -274
  41. package/chunks/{chunk-TZFIAMWZ.js → chunk-SCWWLABR.js} +1 -1
  42. package/chunks/chunk-VDOWARMJ.js +63 -0
  43. package/chunks/{chunk-5MWAG3FT.js → chunk-WBRGXCU2.js} +79 -18
  44. package/chunks/{chunk-LCRTAQN2.js → chunk-WHUAUFSX.js} +1 -1
  45. package/chunks/{chunk-YIQSGNAA.js → chunk-XODDLNBI.js} +1535 -1306
  46. package/chunks/chunk-YAZARMJY.js +355 -0
  47. package/chunks/{chunk-OAYUPGF6.js → chunk-YED25PA4.js} +1 -1
  48. package/chunks/{codex-models-7TLJSY3L.js → codex-models-Z43V3427.js} +9 -3
  49. package/chunks/{commands-NEI7L3QA.js → commands-EUGF4FUZ.js} +5844 -4095
  50. package/chunks/{db-5AP3JB4W.js → db-NVAW4WWR.js} +3 -3
  51. package/chunks/{dist-3FNZIBB4.js → dist-27BNG6WD.js} +195 -112
  52. package/chunks/{dist-5YHYNLI3.js → dist-7RUOKPRJ.js} +12 -2
  53. package/chunks/{dist-KEULE5IQ.js → dist-LNXGATR2.js} +2 -2
  54. package/chunks/{dist-XZB53PS5.js → dist-M2X367VW.js} +2 -2
  55. package/chunks/{dist-DD4H6HMQ.js → dist-NG2HT5XU.js} +27 -1
  56. package/chunks/{eval-runner-43BO2C4T.js → eval-runner-6Q3H52SP.js} +13 -9
  57. package/chunks/{exploit-agent-N4A5ELBK.js → exploit-agent-FCCR2HYX.js} +1 -1
  58. package/chunks/{exploit-autoclimb-N7P6KIF5.js → exploit-autoclimb-X5ZS5FAO.js} +1 -1
  59. package/chunks/{exploit-climb-WNEJUB5W.js → exploit-climb-3JHGEO36.js} +2 -2
  60. package/chunks/{fix-Z452M4EC.js → fix-NSNPU33B.js} +12 -6
  61. package/chunks/{harness-QJJJVSG4.js → harness-KXQOVIDQ.js} +3 -3
  62. package/chunks/{hunt-scan-K6D2V3PX.js → hunt-scan-ELTKGKC4.js} +16 -12
  63. package/chunks/{kernel-primitive-TKUACPKD.js → kernel-primitive-MT7YZSIG.js} +2 -2
  64. package/chunks/{kernel-vm-runner-RAAO2PGT.js → kernel-vm-runner-YFRHYC6G.js} +2 -2
  65. package/chunks/{native-loop-2ZRJENZ3.js → native-loop-OFJDRHPI.js} +18 -8
  66. package/chunks/orchestrate-DRZ2SVCP.js +62 -0
  67. package/chunks/{prepare-KYHGFWCJ.js → prepare-72GWTRVI.js} +6 -2
  68. package/chunks/{process-N245QIQG.js → process-MJYJ2K5E.js} +2 -1
  69. package/chunks/{run-U3XU4CTC.js → run-WTJCZZHV.js} +3091 -6037
  70. package/chunks/{runtime-G75TEWQY.js → runtime-FCKOUB7V.js} +10 -4
  71. package/chunks/{runtime-XFWJTBUO.js → runtime-LCJ4XSKE.js} +5 -1
  72. package/chunks/{scan-stream-BMOCPKQX.js → scan-stream-GT6GKQ3U.js} +7 -1
  73. package/chunks/{scope-WXI46UHJ.js → scope-E5QZUOOH.js} +2 -2
  74. package/chunks/service-plugins-MSK2EQP6.js +62 -0
  75. package/chunks/{session-store-27L3ZU73.js → session-store-H3Q7KCYG.js} +6 -4
  76. package/chunks/{variant-candidates-YWZORZMK.js → variant-candidates-SZKDCOLK.js} +9 -3
  77. package/chunks/{web-recon-prepass-YVMFXCIK.js → web-recon-prepass-IO3GXQMW.js} +11 -6
  78. package/dashboard/apple-touch-icon.png +0 -0
  79. package/dashboard/assets/operations-BvB5Qpmk.css +1 -0
  80. package/dashboard/assets/operations-D8Ii01SV.js +114 -0
  81. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
  82. package/dashboard/favicon.ico +0 -0
  83. package/dashboard/favicon.svg +10 -0
  84. package/dashboard/index.html +5 -3
  85. package/package.json +1 -1
  86. package/chunks/chunk-6GHSR47F.js +0 -147
  87. package/chunks/chunk-CAYANSH6.js +0 -3524
  88. package/chunks/chunk-GHWODZMR.js +0 -16
  89. package/chunks/chunk-MICHDTBK.js +0 -193
  90. package/chunks/orchestrate-2GWGNTBF.js +0 -58
  91. package/dashboard/assets/bot-Bg1Tp9_d.js +0 -1
  92. package/dashboard/assets/dist-B_dDCPbu.js +0 -1
  93. package/dashboard/assets/findings-page-mayGhNx6.js +0 -5
  94. package/dashboard/assets/format--susmHX7.js +0 -1
  95. package/dashboard/assets/input-TuVPR3Zl.js +0 -1
  96. package/dashboard/assets/jsx-runtime-MGseXjj5.js +0 -3
  97. package/dashboard/assets/live-page-HWWHX99U.js +0 -1
  98. package/dashboard/assets/meta-tile-ckHo-w7k.js +0 -1
  99. package/dashboard/assets/operations-BxZ0OoXO.js +0 -10
  100. package/dashboard/assets/operations-CMFVrXEe.css +0 -2
  101. package/dashboard/assets/operations-app-D3d35rgo.js +0 -46
  102. package/dashboard/assets/overview-page-W_4IteEr.js +0 -1
  103. package/dashboard/assets/page-header-Bw9AJgBV.js +0 -1
  104. package/dashboard/assets/scans-page-CgzVXHnn.js +0 -1
  105. package/dashboard/assets/siren-KQj8QAnJ.js +0 -1
  106. package/dashboard/assets/table-8EDklulN.js +0 -1
  107. package/dashboard/assets/tabs-CFHPOwg8.js +0 -1
@@ -5,6 +5,28 @@ import {
5
5
  external_exports
6
6
  } from "./chunk-VIT5ALXF.js";
7
7
 
8
+ // packages/shared/dist/types.js
9
+ function validateScanPlan(plan) {
10
+ if (!Number.isInteger(plan.runCount) || plan.runCount < 1) {
11
+ throw new Error("Scan plan runCount must be a positive integer");
12
+ }
13
+ if (plan.depth !== "quick" && plan.depth !== "default" && plan.depth !== "deep") {
14
+ throw new Error(`Unknown scan depth "${String(plan.depth)}"`);
15
+ }
16
+ if (!Number.isFinite(plan.timeCapMs) || plan.timeCapMs <= 0) {
17
+ throw new Error("Scan plan timeCapMs must be a positive finite number");
18
+ }
19
+ if (!Number.isFinite(plan.costCapUsd) || plan.costCapUsd <= 0) {
20
+ throw new Error("Scan plan costCapUsd must be a positive finite number");
21
+ }
22
+ if (plan.executionMode !== "sequential" && plan.executionMode !== "parallel") {
23
+ throw new Error(`Unknown scan execution mode "${String(plan.executionMode)}"`);
24
+ }
25
+ if (plan.goal !== "known-vulnerabilities" && plan.goal !== "unknown-vulnerabilities" && plan.goal !== "misconfigurations") {
26
+ throw new Error(`Unknown scan goal "${String(plan.goal)}"`);
27
+ }
28
+ }
29
+
8
30
  // packages/shared/dist/identity.js
9
31
  function defaultRoleFor(auth) {
10
32
  return auth ? "user" : "anonymous";
@@ -45,7 +67,7 @@ import { fileURLToPath } from "node:url";
45
67
  import { dirname, join } from "node:path";
46
68
  function loadVersion() {
47
69
  if (true) {
48
- return "0.22.0";
70
+ return "0.22.4";
49
71
  }
50
72
  try {
51
73
  const here = dirname(fileURLToPath(import.meta.url));
@@ -224,13 +246,14 @@ var MODEL_PRICING = {
224
246
  };
225
247
  var DISCOVERED_PRICING = /* @__PURE__ */ new Map();
226
248
  function registerModelPricing(model, rates) {
227
- if (!model || model !== model.trim() || /[\s\x00-\x1f\x7f]/.test(model) || Object.hasOwn(MODEL_PRICING, model) || !Number.isFinite(rates.input) || rates.input < 0 || !Number.isFinite(rates.output) || rates.output < 0 || rates.cachedInput !== void 0 && (!Number.isFinite(rates.cachedInput) || rates.cachedInput < 0)) {
249
+ if (!model || model !== model.trim() || /[\s\x00-\x1f\x7f]/.test(model) || Object.hasOwn(MODEL_PRICING, model) || !Number.isFinite(rates.input) || rates.input < 0 || !Number.isFinite(rates.output) || rates.output < 0 || rates.cachedInput !== void 0 && (!Number.isFinite(rates.cachedInput) || rates.cachedInput < 0) || rates.cacheWrite !== void 0 && (!Number.isFinite(rates.cacheWrite) || rates.cacheWrite < 0)) {
228
250
  return false;
229
251
  }
230
252
  DISCOVERED_PRICING.set(model, Object.freeze({
231
253
  input: rates.input,
232
254
  output: rates.output,
233
- ...rates.cachedInput !== void 0 ? { cachedInput: rates.cachedInput } : {}
255
+ ...rates.cachedInput !== void 0 ? { cachedInput: rates.cachedInput } : {},
256
+ ...rates.cacheWrite !== void 0 ? { cacheWrite: rates.cacheWrite } : {}
234
257
  }));
235
258
  return true;
236
259
  }
@@ -302,8 +325,9 @@ function estimateCost(usage, model) {
302
325
  const rates = getRates(model);
303
326
  const cachedInputRate = rates.cachedInput ?? rates.input;
304
327
  const cached = usage.cachedInputTokens ?? 0;
305
- const uncachedInput = Math.max(0, usage.inputTokens - cached);
306
- return uncachedInput / 1e6 * rates.input + cached / 1e6 * cachedInputRate + usage.outputTokens / 1e6 * rates.output;
328
+ const writes = usage.cacheWriteTokens ?? 0;
329
+ const uncachedInput = Math.max(0, usage.inputTokens - cached - writes);
330
+ return uncachedInput / 1e6 * rates.input + cached / 1e6 * cachedInputRate + writes / 1e6 * (rates.cacheWrite ?? rates.input * 1.25) + usage.outputTokens / 1e6 * rates.output;
307
331
  }
308
332
  function priceRun(usage, model) {
309
333
  return estimateCost(usage, model);
@@ -367,9 +391,10 @@ function splitCost(usage, model) {
367
391
  const rates = getRates(model);
368
392
  const cachedInputRate = rates.cachedInput ?? rates.input;
369
393
  const cached = usage.cachedInputTokens ?? 0;
370
- const uncachedInput = Math.max(0, usage.inputTokens - cached);
394
+ const writes = usage.cacheWriteTokens ?? 0;
395
+ const uncachedInput = Math.max(0, usage.inputTokens - cached - writes);
371
396
  const split = {
372
- cost_in: uncachedInput / 1e6 * rates.input,
397
+ cost_in: uncachedInput / 1e6 * rates.input + writes / 1e6 * (rates.cacheWrite ?? rates.input * 1.25),
373
398
  cost_out: usage.outputTokens / 1e6 * rates.output
374
399
  };
375
400
  if (usage.cachedInputTokens !== void 0) {
@@ -769,27 +794,27 @@ var DANGEROUS_WINDOWS_PRIVILEGES = /* @__PURE__ */ new Set([
769
794
  "SeTakeOwnershipPrivilege",
770
795
  "SeLoadDriverPrivilege"
771
796
  ]);
772
- function coherentTokenSnapshot(token) {
773
- if (typeof token !== "object" || token === null)
797
+ function coherentTokenSnapshot(token2) {
798
+ if (typeof token2 !== "object" || token2 === null)
774
799
  return false;
775
- const candidate = token;
800
+ const candidate = token2;
776
801
  return TOKEN_ID.test(candidate.tokenId) && SID.test(candidate.userSid) && Number.isSafeInteger(candidate.integrityRid) && candidate.integrityRid >= 0 && ["default", "limited", "full"].includes(candidate.elevationType) && typeof candidate.elevated === "boolean" && ["absent", "deny-only", "enabled"].includes(candidate.adminGroup) && typeof candidate.appContainer === "boolean" && Number.isSafeInteger(candidate.restrictedSidCount) && candidate.restrictedSidCount >= 0 && Array.isArray(candidate.enabledPrivileges) && candidate.enabledPrivileges.length <= 128 && candidate.enabledPrivileges.every((privilege) => typeof privilege === "string" && PRIVILEGE.test(privilege)) && new Set(candidate.enabledPrivileges).size === candidate.enabledPrivileges.length;
777
802
  }
778
803
  function equalTokenSnapshot(left, right) {
779
804
  return left.tokenId === right.tokenId && left.userSid === right.userSid && left.integrityRid === right.integrityRid && left.elevationType === right.elevationType && left.elevated === right.elevated && left.adminGroup === right.adminGroup && left.appContainer === right.appContainer && left.restrictedSidCount === right.restrictedSidCount && left.enabledPrivileges.length === right.enabledPrivileges.length && left.enabledPrivileges.every((privilege, index) => privilege === right.enabledPrivileges[index]);
780
805
  }
781
- function unprivilegedWindowsToken(token) {
782
- return token.integrityRid <= 8448 && !token.elevated && token.elevationType !== "full" && token.adminGroup !== "enabled" && (token.appContainer || token.restrictedSidCount > 0 || token.adminGroup === "absent") && !token.enabledPrivileges.some((privilege) => DANGEROUS_WINDOWS_PRIVILEGES.has(privilege));
806
+ function unprivilegedWindowsToken(token2) {
807
+ return token2.integrityRid <= 8448 && !token2.elevated && token2.elevationType !== "full" && token2.adminGroup !== "enabled" && (token2.appContainer || token2.restrictedSidCount > 0 || token2.adminGroup === "absent") && !token2.enabledPrivileges.some((privilege) => DANGEROUS_WINDOWS_PRIVILEGES.has(privilege));
783
808
  }
784
- function validWindowsStart(startingContext, token) {
809
+ function validWindowsStart(startingContext, token2) {
785
810
  if (startingContext === "lpac")
786
811
  return false;
787
812
  if (startingContext === "standard-user") {
788
- return !token.appContainer && token.restrictedSidCount === 0;
813
+ return !token2.appContainer && token2.restrictedSidCount === 0;
789
814
  }
790
815
  if (startingContext === "appcontainer")
791
- return token.appContainer;
792
- return token.appContainer || token.restrictedSidCount > 0;
816
+ return token2.appContainer;
817
+ return token2.appContainer || token2.restrictedSidCount > 0;
793
818
  }
794
819
  function validWindowsFinish(principal, start, finish) {
795
820
  if (finish.appContainer || finish.restrictedSidCount !== 0)
@@ -1062,7 +1087,7 @@ var DEFAULT_AUTONOMY_MODE = "yolo";
1062
1087
  var DEFAULT_ALLOW_MODEL_SELF_EXTENSION = true;
1063
1088
 
1064
1089
  // packages/shared/dist/jev.js
1065
- var FEATURES = ["browser", "memory", "dedupe", "redteam", "kernel", "crash", "radar", "foxguard"];
1090
+ var FEATURES = ["browser", "memory", "dedupe", "rank", "specialist", "redteam", "kernel", "crash", "radar", "foxguard"];
1066
1091
  var INPUT_USD_PER_TOKEN = 0.042 / 1e6;
1067
1092
  var MAX_INPUT_TOKENS = 65536;
1068
1093
  var REQUEST_RESERVATION_USD = MAX_INPUT_TOKENS * INPUT_USD_PER_TOKEN;
@@ -1180,8 +1205,8 @@ function createJevEvaluator(config) {
1180
1205
  rawAnswers = body.answers;
1181
1206
  } else {
1182
1207
  const [{ experimental_evaluate: evaluate }, { createGateway }] = await Promise.all([
1183
- import("./dist-KEULE5IQ.js"),
1184
- import("./dist-XZB53PS5.js")
1208
+ import("./dist-LNXGATR2.js"),
1209
+ import("./dist-M2X367VW.js")
1185
1210
  ]);
1186
1211
  signal.throwIfAborted();
1187
1212
  const gateway = createGateway({ apiKey: config.apiKey, fetch: fetchImpl });
@@ -1231,7 +1256,465 @@ function createJevEvaluator(config) {
1231
1256
  };
1232
1257
  }
1233
1258
 
1259
+ // packages/shared/dist/slash-commands.js
1260
+ var SLASH_COMMANDS = [
1261
+ // ── info ────────────────────────────────────────────────────────────────
1262
+ {
1263
+ name: "help",
1264
+ aliases: ["?", "commands"],
1265
+ category: "info",
1266
+ description: "List commands",
1267
+ usage: "/help [command]"
1268
+ },
1269
+ {
1270
+ name: "capabilities",
1271
+ aliases: ["caps"],
1272
+ category: "info",
1273
+ description: "What 0 can do and what needs approval",
1274
+ usage: "/capabilities",
1275
+ tuiOnly: true
1276
+ },
1277
+ {
1278
+ name: "status",
1279
+ aliases: [],
1280
+ category: "info",
1281
+ description: "Session status"
1282
+ },
1283
+ {
1284
+ name: "tools",
1285
+ aliases: [],
1286
+ category: "info",
1287
+ description: "List available tools"
1288
+ },
1289
+ {
1290
+ name: "new-chat",
1291
+ aliases: ["new"],
1292
+ category: "navigation",
1293
+ description: "Start a fresh audit",
1294
+ tuiOnly: true
1295
+ },
1296
+ {
1297
+ name: "onboard",
1298
+ aliases: [],
1299
+ category: "navigation",
1300
+ description: "Run setup again",
1301
+ tuiOnly: true
1302
+ },
1303
+ // ── session ─────────────────────────────────────────────────────────────
1304
+ {
1305
+ name: "clear",
1306
+ aliases: [],
1307
+ category: "session",
1308
+ description: "Clear the conversation"
1309
+ },
1310
+ {
1311
+ name: "history",
1312
+ aliases: [],
1313
+ category: "session",
1314
+ description: "Past scans",
1315
+ tuiOnly: true
1316
+ },
1317
+ {
1318
+ name: "findings",
1319
+ aliases: ["finds"],
1320
+ category: "session",
1321
+ description: "Show findings",
1322
+ tuiOnly: true
1323
+ },
1324
+ {
1325
+ name: "fix",
1326
+ aliases: [],
1327
+ category: "session",
1328
+ description: "Write and test a fix; you approve any PR",
1329
+ usage: "/fix [finding-id] | /fix publish <finding-id> | /fix cancel",
1330
+ tuiOnly: true
1331
+ },
1332
+ {
1333
+ name: "copy",
1334
+ aliases: ["export", "dump"],
1335
+ category: "session",
1336
+ description: "Copy the conversation",
1337
+ usage: "/copy",
1338
+ tuiOnly: true
1339
+ },
1340
+ {
1341
+ name: "sessions",
1342
+ aliases: [],
1343
+ category: "session",
1344
+ description: "Switch or resume a conversation",
1345
+ usage: "/sessions",
1346
+ tuiOnly: true
1347
+ },
1348
+ {
1349
+ name: "explain",
1350
+ aliases: ["eli5"],
1351
+ category: "session",
1352
+ description: "Explain simply",
1353
+ usage: "/explain [topic]",
1354
+ tuiOnly: true
1355
+ },
1356
+ {
1357
+ name: "feedback",
1358
+ aliases: [],
1359
+ category: "system",
1360
+ description: "Send feedback",
1361
+ usage: "/feedback <message> | /feedback submit <message> | /feedback send | /feedback cancel",
1362
+ tuiOnly: true
1363
+ },
1364
+ {
1365
+ name: "settings",
1366
+ aliases: ["config", "prefs"],
1367
+ category: "system",
1368
+ description: "Open settings",
1369
+ usage: "/settings",
1370
+ tuiOnly: true
1371
+ },
1372
+ {
1373
+ name: "keybindings",
1374
+ aliases: ["keys", "keymap"],
1375
+ category: "system",
1376
+ description: "Keyboard shortcuts",
1377
+ usage: "/keybindings",
1378
+ tuiOnly: true
1379
+ },
1380
+ {
1381
+ name: "theme",
1382
+ aliases: ["themes"],
1383
+ category: "system",
1384
+ description: "Change the colour theme",
1385
+ usage: "/theme [name]",
1386
+ tuiOnly: true
1387
+ },
1388
+ {
1389
+ name: "model",
1390
+ aliases: ["models"],
1391
+ category: "session",
1392
+ description: "Choose a model",
1393
+ usage: "/model [id]",
1394
+ tuiOnly: true
1395
+ },
1396
+ // ── navigation ──────────────────────────────────────────────────────────
1397
+ {
1398
+ name: "chat",
1399
+ aliases: [],
1400
+ category: "navigation",
1401
+ description: "Back to the conversation",
1402
+ tuiOnly: true
1403
+ },
1404
+ {
1405
+ name: "launcher",
1406
+ aliases: ["run", "home"],
1407
+ category: "navigation",
1408
+ description: "Scan one target",
1409
+ tuiOnly: true
1410
+ },
1411
+ {
1412
+ name: "ops",
1413
+ aliases: ["runs"],
1414
+ category: "navigation",
1415
+ description: "Running and recent scans",
1416
+ tuiOnly: true
1417
+ },
1418
+ {
1419
+ name: "hackstore",
1420
+ aliases: ["store", "market", "marketplace"],
1421
+ category: "navigation",
1422
+ description: "Install extensions and themes",
1423
+ tuiOnly: true
1424
+ },
1425
+ {
1426
+ name: "connect",
1427
+ aliases: [],
1428
+ category: "navigation",
1429
+ description: "Add an API key or sign in",
1430
+ usage: "/connect",
1431
+ tuiOnly: true
1432
+ },
1433
+ {
1434
+ name: "usage",
1435
+ aliases: ["cost", "tokens"],
1436
+ category: "navigation",
1437
+ description: "Tokens, cost and context",
1438
+ usage: "/usage",
1439
+ tuiOnly: true
1440
+ },
1441
+ {
1442
+ name: "back",
1443
+ aliases: [],
1444
+ category: "navigation",
1445
+ description: "Previous screen",
1446
+ tuiOnly: true
1447
+ },
1448
+ {
1449
+ name: "scope",
1450
+ aliases: [],
1451
+ category: "navigation",
1452
+ description: "What 0 is allowed to test",
1453
+ tuiOnly: true
1454
+ },
1455
+ // ── system ──────────────────────────────────────────────────────────────
1456
+ {
1457
+ name: "doctor",
1458
+ aliases: [],
1459
+ category: "system",
1460
+ description: "Check your setup",
1461
+ tuiOnly: true
1462
+ },
1463
+ {
1464
+ name: "exit",
1465
+ aliases: ["quit"],
1466
+ category: "system",
1467
+ description: "Quit"
1468
+ }
1469
+ ];
1470
+ var NAME_INDEX = {};
1471
+ for (const cmd of SLASH_COMMANDS) {
1472
+ NAME_INDEX[cmd.name] = cmd.name;
1473
+ for (const alias of cmd.aliases) {
1474
+ NAME_INDEX[alias] = cmd.name;
1475
+ }
1476
+ }
1477
+ function getCommandByName(name) {
1478
+ const canonical = NAME_INDEX[name];
1479
+ if (!canonical)
1480
+ return void 0;
1481
+ for (const cmd of SLASH_COMMANDS) {
1482
+ if (cmd.name === canonical)
1483
+ return cmd;
1484
+ }
1485
+ return void 0;
1486
+ }
1487
+ function findCommand(input) {
1488
+ const trimmed = input.trimStart();
1489
+ if (!trimmed.startsWith("/")) {
1490
+ return {
1491
+ isSlash: false,
1492
+ command: void 0,
1493
+ rawName: "",
1494
+ args: "",
1495
+ isKnown: false,
1496
+ isUnknown: false
1497
+ };
1498
+ }
1499
+ const afterSlash = trimmed.slice(1);
1500
+ const spaceIndex = afterSlash.indexOf(" ");
1501
+ const rawName = spaceIndex >= 0 ? afterSlash.slice(0, spaceIndex) : afterSlash;
1502
+ const args = spaceIndex >= 0 ? afterSlash.slice(spaceIndex + 1).trim() : "";
1503
+ const canonical = NAME_INDEX[rawName];
1504
+ if (canonical) {
1505
+ return {
1506
+ isSlash: true,
1507
+ command: canonical,
1508
+ rawName,
1509
+ args,
1510
+ isKnown: true,
1511
+ isUnknown: false
1512
+ };
1513
+ }
1514
+ return {
1515
+ isSlash: true,
1516
+ command: void 0,
1517
+ rawName,
1518
+ args,
1519
+ isKnown: false,
1520
+ isUnknown: true
1521
+ };
1522
+ }
1523
+ function filterCommands(query) {
1524
+ const trimmed = query.trim().toLowerCase();
1525
+ if (!trimmed)
1526
+ return [...SLASH_COMMANDS];
1527
+ return SLASH_COMMANDS.filter((cmd) => {
1528
+ if (cmd.name.startsWith(trimmed))
1529
+ return true;
1530
+ return cmd.aliases.some((a) => a.startsWith(trimmed));
1531
+ });
1532
+ }
1533
+
1534
+ // packages/shared/dist/security-workflows.js
1535
+ var DEFAULT_SECURITY_WORKFLOW_PLAN = Object.freeze({ goal: "known-vulnerabilities", depth: "default", runCount: 1, executionMode: "sequential", timeCapMs: 6e5, costCapUsd: 5 });
1536
+ var identifier = external_exports.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/).refine((value) => !["__proto__", "constructor", "prototype"].includes(value), "Reserved identifier.");
1537
+ var planSchema = external_exports.object({
1538
+ goal: external_exports.enum(["known-vulnerabilities", "unknown-vulnerabilities", "misconfigurations"]),
1539
+ depth: external_exports.enum(["quick", "default", "deep"]),
1540
+ runCount: external_exports.number().int().min(1).max(16),
1541
+ executionMode: external_exports.enum(["sequential", "parallel"]),
1542
+ timeCapMs: external_exports.number().int().finite().positive().max(864e5),
1543
+ costCapUsd: external_exports.number().finite().positive().max(1e3)
1544
+ }).strict();
1545
+ var executionSchema = external_exports.object({
1546
+ instructions: external_exports.string().trim().max(16e3),
1547
+ allowedAgentTools: external_exports.array(external_exports.string().trim().min(1).max(128).regex(/^[A-Za-z0-9_.:-]+$/)).max(128).refine((tools) => new Set(tools).size === tools.length, "Agent tool names must be unique.").optional()
1548
+ }).strict();
1549
+ var nodeSchema = external_exports.object({ id: identifier, type: external_exports.enum(["trigger", "audit", "report"]), label: external_exports.string().trim().min(1).max(160), enabled: external_exports.boolean(), plan: planSchema.optional(), execution: executionSchema.optional() }).strict();
1550
+ var SecurityWorkflowInputSchema = external_exports.object({
1551
+ id: identifier.optional(),
1552
+ revision: external_exports.number().int().positive().optional(),
1553
+ name: external_exports.string().trim().min(1).max(160),
1554
+ instructions: external_exports.string().trim().max(16e3),
1555
+ target: external_exports.string().trim().max(4096),
1556
+ nodes: external_exports.array(nodeSchema).min(2).max(16),
1557
+ edges: external_exports.array(external_exports.object({ source: identifier, target: identifier }).strict()).min(1).max(120)
1558
+ }).strict().superRefine((workflow, context) => {
1559
+ const issue = (message) => context.addIssue({ code: external_exports.ZodIssueCode.custom, message });
1560
+ const ids = new Set(workflow.nodes.map((node) => node.id));
1561
+ if (ids.size !== workflow.nodes.length)
1562
+ issue("Workflow node IDs must be unique.");
1563
+ const triggers = workflow.nodes.filter((node) => node.type === "trigger");
1564
+ if (triggers.length !== 1)
1565
+ issue("A workflow requires exactly one trigger.");
1566
+ if (triggers.some((node) => !node.enabled))
1567
+ issue("The manual trigger must remain enabled.");
1568
+ if (!workflow.nodes.some((node) => node.type === "audit"))
1569
+ issue("A workflow requires at least one audit.");
1570
+ if (workflow.nodes.filter((node) => node.type === "report").length > 1)
1571
+ issue("A workflow supports at most one report.");
1572
+ if (workflow.nodes.some((node) => node.type !== "audit" && (node.plan !== void 0 || node.execution !== void 0)))
1573
+ issue("Only audit nodes accept scan plans and execution policies.");
1574
+ const edges = /* @__PURE__ */ new Set();
1575
+ const successors = /* @__PURE__ */ new Map();
1576
+ for (const edge of workflow.edges) {
1577
+ if (!ids.has(edge.source) || !ids.has(edge.target))
1578
+ issue("Edges must reference existing nodes.");
1579
+ const key = `${edge.source}:${edge.target}`;
1580
+ if (edges.has(key))
1581
+ issue("Workflow edges must be unique.");
1582
+ edges.add(key);
1583
+ successors.set(edge.source, [...successors.get(edge.source) ?? [], edge.target]);
1584
+ const source = workflow.nodes.find((node) => node.id === edge.source);
1585
+ const target = workflow.nodes.find((node) => node.id === edge.target);
1586
+ if (target?.type === "trigger" || source?.type === "report")
1587
+ issue("Triggers must start the graph and reports must end it.");
1588
+ }
1589
+ const visiting = /* @__PURE__ */ new Set();
1590
+ const visited = /* @__PURE__ */ new Set();
1591
+ const visit = (id) => {
1592
+ if (visiting.has(id))
1593
+ return false;
1594
+ if (visited.has(id))
1595
+ return true;
1596
+ visiting.add(id);
1597
+ for (const next of successors.get(id) ?? [])
1598
+ if (!visit(next))
1599
+ return false;
1600
+ visiting.delete(id);
1601
+ visited.add(id);
1602
+ return true;
1603
+ };
1604
+ if (workflow.nodes.some((node) => !visit(node.id)))
1605
+ issue("Workflow graphs cannot contain cycles.");
1606
+ if (triggers.length === 1) {
1607
+ const reachable = /* @__PURE__ */ new Set();
1608
+ const walk = (id) => {
1609
+ if (reachable.has(id))
1610
+ return;
1611
+ reachable.add(id);
1612
+ for (const next of successors.get(id) ?? [])
1613
+ walk(next);
1614
+ };
1615
+ walk(triggers[0].id);
1616
+ if (workflow.nodes.some((node) => !reachable.has(node.id)))
1617
+ issue("Every node must be reachable from the trigger.");
1618
+ }
1619
+ });
1620
+ function parseSecurityWorkflowInput(value) {
1621
+ const workflow = SecurityWorkflowInputSchema.parse(value);
1622
+ return { ...workflow, nodes: workflow.nodes.map((node) => node.type === "audit" ? { ...node, plan: node.plan ?? { ...DEFAULT_SECURITY_WORKFLOW_PLAN } } : node) };
1623
+ }
1624
+ var codeEnvelope = external_exports.object({ schemaVersion: external_exports.literal(1), workflow: external_exports.unknown() }).strict();
1625
+ function exportSecurityWorkflowCode(value) {
1626
+ const { name, instructions, target, nodes, edges } = value;
1627
+ const parsed = parseSecurityWorkflowInput({ name, instructions, target, nodes, edges });
1628
+ const json = JSON.stringify({ schemaVersion: 1, workflow: parsed }, null, 2);
1629
+ if (new TextEncoder().encode(json).byteLength > 65536)
1630
+ throw new Error("Workflow JSON must be at most 64 KiB.");
1631
+ return json;
1632
+ }
1633
+ function parseSecurityWorkflowCode(value) {
1634
+ if (typeof value === "string") {
1635
+ if (new TextEncoder().encode(value).byteLength > 65536)
1636
+ throw new Error("Workflow JSON must be at most 64 KiB.");
1637
+ value = JSON.parse(value);
1638
+ }
1639
+ const envelope = codeEnvelope.parse(value);
1640
+ if (!envelope.workflow || typeof envelope.workflow !== "object" || Array.isArray(envelope.workflow))
1641
+ throw new Error("Workflow must be an object.");
1642
+ const { id: _id, revision: _revision, createdAt: _createdAt, updatedAt: _updatedAt, ...draft } = envelope.workflow;
1643
+ if (new TextEncoder().encode(JSON.stringify(envelope)).byteLength > 65536)
1644
+ throw new Error("Workflow JSON must be at most 64 KiB.");
1645
+ return parseSecurityWorkflowInput(draft);
1646
+ }
1647
+
1648
+ // packages/shared/dist/security-workflow-templates.js
1649
+ function phase(id, label, goal, instructions, depth = "default") {
1650
+ return { id, type: "audit", label, enabled: true, plan: { goal, depth, runCount: 1, executionMode: "sequential", timeCapMs: 6e5, costCapUsd: 5 }, execution: { instructions } };
1651
+ }
1652
+ function template(id, name, description, category, phases) {
1653
+ const nodes = [{ id: "start", type: "trigger", label: "Start manually", enabled: true }, ...phases, { id: "report", type: "report", label: "Collect reports", enabled: true }];
1654
+ return { id, name, description, category, definition: parseSecurityWorkflowInput({ name, instructions: description, target: "", nodes, edges: nodes.slice(1).map((node, index) => ({ source: nodes[index].id, target: node.id })) }) };
1655
+ }
1656
+ var SECURITY_WORKFLOW_TEMPLATES = [
1657
+ template("repository-review", "Repository security review", "Review a local repository's trust boundaries, dependency exposure, and security-sensitive code.", "repository", [
1658
+ phase("dependencies", "Dependency exposure", "known-vulnerabilities", "Inspect dependency manifests and lockfiles. Prioritize reachable vulnerable dependencies and supply-chain trust boundaries; distinguish confirmed exposure from version-only matches.", "quick"),
1659
+ phase("boundaries", "Trust boundaries", "unknown-vulnerabilities", "Trace authentication, authorization, tenant isolation, and privileged entry points in the authorized repository. Follow input-to-sink paths and report only supported security findings.", "deep"),
1660
+ phase("configuration", "Configuration and secrets", "misconfigurations", "Review repository configuration, credential handling, unsafe defaults, and sensitive debug surfaces. Do not expose secret values in reports.")
1661
+ ]),
1662
+ template("dependency-review", "Dependency and supply-chain review", "Assess an authorized package or repository for advisories and suspicious dependency behavior.", "package", [
1663
+ phase("advisories", "Advisory triage", "known-vulnerabilities", "Review declared and locked dependencies against supported advisory sources. Check affected versions and whether vulnerable functionality is used.", "quick"),
1664
+ phase("lifecycle", "Lifecycle and trust", "unknown-vulnerabilities", "Inspect package installation hooks, dynamic downloads, credential access, and dependency trust changes. Support suspicious behavior with code evidence, without executing untrusted installation scripts.", "deep")
1665
+ ]),
1666
+ template("api-security", "API authorization review", "Review an explicitly authorized API for authorization gaps, unsafe inputs, and exposed configuration.", "web", [
1667
+ phase("surface", "API surface and defaults", "misconfigurations", "Map documented and reachable authorized API endpoints, exposed documentation, error disclosures, and security defaults. Stay within the supplied scope and avoid destructive requests.", "quick"),
1668
+ phase("authorization", "Authorization boundaries", "unknown-vulnerabilities", "Assess object ownership, role boundaries, tenant isolation, and authentication requirements using only identities and targets explicitly authorized for the engagement. Do not invent credentials.", "deep"),
1669
+ phase("inputs", "Input handling", "unknown-vulnerabilities", "Review request parsing, injection boundaries, resource references, and validation. Use bounded non-destructive checks and retain evidence for confirmed impact.")
1670
+ ]),
1671
+ template("web-configuration", "Web configuration review", "Assess an authorized web target's exposure, browser security controls, and session configuration.", "web", [
1672
+ phase("exposure", "Public exposure", "misconfigurations", "Review in-scope publicly reachable files, admin/debug surfaces, transport defaults, and error disclosures using non-destructive checks.", "quick"),
1673
+ phase("sessions", "Browser and session controls", "misconfigurations", "Review observed cookie attributes, cache handling of sensitive responses, cross-origin policy, redirect handling, and browser security headers. Explain practical impact rather than treating every absent header as a vulnerability."),
1674
+ phase("advisories", "Known component exposure", "known-vulnerabilities", "Assess observed components against supported known-vulnerability sources. Separate inferred versions from verified affected versions and avoid unsupported exploit claims.")
1675
+ ]),
1676
+ template("scoped-penetration-test", "Scoped penetration test", "Plan and assess only an explicitly authorized target, with bounded discovery and non-destructive validation.", "security", [
1677
+ phase("discovery", "Scoped discovery", "misconfigurations", "Map only the authorized attack surface and identify exposed configuration and trust boundaries. Honor exclusions and rate limits; do not enumerate unrelated hosts.", "quick"),
1678
+ phase("known", "Known vulnerability triage", "known-vulnerabilities", "Check supported known-vulnerability leads against observed target behavior. Verify applicability with bounded evidence; do not run broad third-party scanners or destructive exploit payloads."),
1679
+ phase("validation", "Targeted validation", "unknown-vulnerabilities", "Investigate authorization, input handling, and sensitive state transitions within explicit scope. Prefer minimal non-destructive proof; stop before destructive actions or accessing unrelated user data.", "deep")
1680
+ ]),
1681
+ template("package-behavior", "Package behavior investigation", "Review an authorized package's security-relevant code paths and suspicious behavior.", "package", [
1682
+ phase("entrypoints", "Entrypoints and advisories", "known-vulnerabilities", "Inspect package metadata, entrypoints, and supported advisories; identify security-sensitive or remotely reachable behavior.", "quick"),
1683
+ phase("behavior", "Suspicious behavior", "unknown-vulnerabilities", "Trace filesystem and credential access, network destinations, obfuscated code, dynamic evaluation, and lifecycle hooks. Distinguish legitimate functionality from suspicious behavior with evidence; do not execute untrusted install scripts.", "deep")
1684
+ ]),
1685
+ template("contract-review", "Smart contract source review", "Review an authorized contract source repository for access control and asset-accounting defects.", "contracts", [
1686
+ phase("access", "Authority and upgrade paths", "unknown-vulnerabilities", "Review contract source for privileged roles, initialization, upgrades, trust in external calls, and missing authorization. Identify the contract ecosystem from source; do not submit transactions or invent specialized verification results.", "deep"),
1687
+ phase("accounting", "Asset and state invariants", "unknown-vulnerabilities", "Trace value transfers, balance accounting, state transitions, rounding, and reentrancy boundaries in the authorized source. Support findings with concrete call sequences; do not move assets or publish exploits.", "deep"),
1688
+ phase("configuration", "Deployment assumptions", "misconfigurations", "Review source-visible deployment and initialization assumptions, privileged configuration, and dependency trust. Clearly distinguish code evidence from unverified deployed state.")
1689
+ ]),
1690
+ template("native-code-review", "Native code boundary review", "Review an authorized native source repository for parser, memory, and privilege-boundary issues.", "repository", [
1691
+ phase("parsers", "Parsers and memory boundaries", "unknown-vulnerabilities", "Trace untrusted input through parsing, length calculations, ownership, and memory operations. Prioritize reachable paths and concrete invalid-state evidence in the authorized source.", "deep"),
1692
+ phase("privileges", "Privilege and resource boundaries", "unknown-vulnerabilities", "Review privilege transitions, filesystem paths, subprocess inputs, concurrency, and resource lifetime. Avoid speculative issues without a supported attacker-controlled path.", "deep")
1693
+ ])
1694
+ ];
1695
+ function createSecurityWorkflowTemplate(id) {
1696
+ const found = SECURITY_WORKFLOW_TEMPLATES.find((entry) => entry.id === id);
1697
+ if (!found)
1698
+ throw new Error("Unknown security workflow template.");
1699
+ return parseSecurityWorkflowInput(found.definition);
1700
+ }
1701
+
1702
+ // packages/shared/dist/service-plugins.js
1703
+ var token = { key: "token", label: "API token", type: "secret", required: true };
1704
+ var SERVICE_PLUGIN_CATALOG = [
1705
+ { id: "github", name: "GitHub", description: "Review repositories, security alerts and pull requests.", category: "Code", docsUrl: "https://github.com/github/github-mcp-server", fields: [{ ...token, label: "Personal access token" }] },
1706
+ { id: "elastic", name: "Elastic", description: "Search security alerts and telemetry.", category: "Security", docsUrl: "https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/mcp-server-api-keys", fields: [{ key: "url", label: "Kibana URL", type: "url", required: true }, { ...token, label: "Encoded API key" }], credentialNote: "Requires Elastic Agent Builder access." },
1707
+ { id: "semgrep", name: "Semgrep", description: "Investigate code, dependency and secret findings.", category: "Security", docsUrl: "https://semgrep.dev/docs/semgrep-appsec-platform/api", fields: [token, { key: "deploymentId", label: "Deployment ID", type: "text", required: true }] },
1708
+ { id: "snyk", name: "Snyk", description: "Review vulnerable projects and dependencies.", category: "Security", docsUrl: "https://docs.snyk.io/snyk-api", fields: [token, { key: "organizationId", label: "Organization ID", type: "text", required: true }, { key: "url", label: "API URL (optional)", type: "url", required: false }] },
1709
+ { id: "linear", name: "Linear", description: "Create and track remediation issues.", category: "Issues", docsUrl: "https://linear.app/developers/graphql", fields: [token] },
1710
+ { id: "jira", name: "Jira", description: "Turn security findings into assigned issues.", category: "Issues", docsUrl: "https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/", fields: [{ key: "url", label: "Jira Cloud URL", type: "url", required: true }, { key: "email", label: "Account email", type: "text", required: true }, token] },
1711
+ { id: "cloudflare", name: "Cloudflare", description: "Inspect zones, DNS and security configuration.", category: "Cloud", docsUrl: "https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", fields: [token] },
1712
+ { id: "slack", name: "Slack", description: "Read channels and share workflow summaries.", category: "Messaging", docsUrl: "https://docs.slack.dev/authentication/tokens/", fields: [{ ...token, label: "Bot or user token" }] },
1713
+ { id: "teams", name: "Microsoft Teams", description: "Read teams and share channel summaries.", category: "Messaging", docsUrl: "https://learn.microsoft.com/en-us/graph/auth/auth-concepts", fields: [{ ...token, label: "Microsoft Graph access token" }], credentialNote: "Delegated token with Teams access. Reconnect when it expires." }
1714
+ ];
1715
+
1234
1716
  export {
1717
+ validateScanPlan,
1235
1718
  defaultRoleFor,
1236
1719
  resolveIdentities,
1237
1720
  hasMultipleIdentities,
@@ -1310,5 +1793,17 @@ export {
1310
1793
  DEFAULT_AUTONOMY_MODE,
1311
1794
  DEFAULT_ALLOW_MODEL_SELF_EXTENSION,
1312
1795
  jevConfigFromEnvironment,
1313
- createJevEvaluator
1796
+ createJevEvaluator,
1797
+ SLASH_COMMANDS,
1798
+ getCommandByName,
1799
+ findCommand,
1800
+ filterCommands,
1801
+ DEFAULT_SECURITY_WORKFLOW_PLAN,
1802
+ SecurityWorkflowInputSchema,
1803
+ parseSecurityWorkflowInput,
1804
+ exportSecurityWorkflowCode,
1805
+ parseSecurityWorkflowCode,
1806
+ SECURITY_WORKFLOW_TEMPLATES,
1807
+ createSecurityWorkflowTemplate,
1808
+ SERVICE_PLUGIN_CATALOG
1314
1809
  };