pwnkit-cli 0.1.5 → 0.1.7

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.js +68 -108
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10402,10 +10402,11 @@ __export(process_exports, {
10402
10402
  ProcessRuntime: () => ProcessRuntime
10403
10403
  });
10404
10404
  import { spawn } from "node:child_process";
10405
- var RUNTIME_COMMANDS, ProcessRuntime;
10405
+ var dim, RUNTIME_COMMANDS, ProcessRuntime;
10406
10406
  var init_process = __esm({
10407
10407
  "packages/core/dist/runtime/process.js"() {
10408
10408
  "use strict";
10409
+ dim = (text2) => `\x1B[2m${text2}\x1B[0m`;
10409
10410
  RUNTIME_COMMANDS = {
10410
10411
  claude: "claude",
10411
10412
  codex: "codex",
@@ -10438,7 +10439,11 @@ var init_process = __esm({
10438
10439
  stdout += chunk.toString();
10439
10440
  });
10440
10441
  proc.stderr.on("data", (chunk) => {
10441
- stderr += chunk.toString();
10442
+ const text2 = chunk.toString();
10443
+ stderr += text2;
10444
+ if (process.stderr.isTTY) {
10445
+ process.stderr.write(dim(text2));
10446
+ }
10442
10447
  });
10443
10448
  const timer = setTimeout(() => {
10444
10449
  timedOut = true;
@@ -11100,15 +11105,17 @@ async function runNativeAgentLoop(opts) {
11100
11105
  state.totalUsage.inputTokens += result.usage.inputTokens;
11101
11106
  state.totalUsage.outputTokens += result.usage.outputTokens;
11102
11107
  }
11103
- if (result.error) {
11104
- onEvent?.("agent_error", { turn: state.turnCount, error: result.error });
11108
+ if (result.error || result.content.length === 0 && (!result.usage || result.usage.outputTokens === 0)) {
11109
+ const errorMsg = result.error || "API returned empty response (0 tokens) \u2014 model may be rate-limited or unavailable";
11110
+ onEvent?.("agent_error", { turn: state.turnCount, error: errorMsg });
11111
+ state.summary = `Error: ${errorMsg}`;
11105
11112
  if (db) {
11106
11113
  db.logEvent({
11107
11114
  scanId: config.scanId,
11108
11115
  stage: config.role,
11109
11116
  eventType: "agent_error",
11110
11117
  agentRole: config.role,
11111
- payload: { turn: state.turnCount, error: result.error },
11118
+ payload: { turn: state.turnCount, error: errorMsg },
11112
11119
  timestamp: Date.now()
11113
11120
  });
11114
11121
  }
@@ -14039,7 +14046,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
14039
14046
  var source_default = chalk;
14040
14047
 
14041
14048
  // packages/shared/dist/constants.js
14042
- var VERSION = "0.1.5";
14049
+ var VERSION = "0.1.7";
14043
14050
  var DEPTH_CONFIG = {
14044
14051
  quick: { maxTemplates: 5, maxPayloadsPerTemplate: 1, multiTurn: false },
14045
14052
  default: { maxTemplates: 20, maxPayloadsPerTemplate: 3, multiTurn: false },
@@ -17395,36 +17402,6 @@ var SEVERITY_COUNT_COLOR = {
17395
17402
  low: source_default.blue,
17396
17403
  info: source_default.gray
17397
17404
  };
17398
- var BOX = {
17399
- topLeft: "\u256D",
17400
- topRight: "\u256E",
17401
- bottomLeft: "\u2570",
17402
- bottomRight: "\u256F",
17403
- horizontal: "\u2500",
17404
- vertical: "\u2502",
17405
- teeRight: "\u251C",
17406
- teeLeft: "\u2524"
17407
- };
17408
- function boxLine(width) {
17409
- return BOX.horizontal.repeat(width);
17410
- }
17411
- function boxTop(width) {
17412
- return ` ${source_default.gray(BOX.topLeft + boxLine(width) + BOX.topRight)}`;
17413
- }
17414
- function boxBottom(width) {
17415
- return ` ${source_default.gray(BOX.bottomLeft + boxLine(width) + BOX.bottomRight)}`;
17416
- }
17417
- function boxRow(content, width) {
17418
- const visible = stripAnsi2(content);
17419
- const pad = Math.max(0, width - visible.length);
17420
- return ` ${source_default.gray(BOX.vertical)} ${content}${" ".repeat(pad)}${source_default.gray(BOX.vertical)}`;
17421
- }
17422
- function boxDivider(width) {
17423
- return ` ${source_default.gray(BOX.teeRight + boxLine(width) + BOX.teeLeft)}`;
17424
- }
17425
- function stripAnsi2(s) {
17426
- return s.replace(/\x1b\[[0-9;]*m/g, "");
17427
- }
17428
17405
  function formatTerminal(report) {
17429
17406
  const W3 = 60;
17430
17407
  const lines = [];
@@ -17459,20 +17436,18 @@ function formatTerminal(report) {
17459
17436
  }
17460
17437
  }
17461
17438
  lines.push("");
17462
- lines.push(boxTop(W3));
17463
- lines.push(boxRow(source_default.bold.white(" SUMMARY"), W3));
17464
- lines.push(boxDivider(W3));
17439
+ lines.push(` ${source_default.gray("\u2500".repeat(50))}`);
17440
+ lines.push("");
17465
17441
  const { summary } = report;
17466
- const severityCounts = buildSeverityLine(summary);
17467
- lines.push(boxRow(severityCounts, W3));
17468
- lines.push(boxRow("", W3));
17469
- const statsLine = [
17470
- `${source_default.white.bold(String(summary.totalFindings))} findings`,
17471
- `${source_default.white.bold(String(summary.totalAttacks))} probes`,
17472
- `${source_default.white.bold(formatDuration(report.durationMs))}`
17473
- ].join(source_default.gray(" \u2502 "));
17474
- lines.push(boxRow(` ${statsLine}`, W3));
17475
- lines.push(boxBottom(W3));
17442
+ const sev = [
17443
+ summary.critical > 0 ? source_default.red.bold(`${summary.critical} critical`) : source_default.gray(`${summary.critical} critical`),
17444
+ summary.high > 0 ? source_default.hex("#f97316").bold(`${summary.high} high`) : source_default.gray(`${summary.high} high`),
17445
+ summary.medium > 0 ? source_default.yellow.bold(`${summary.medium} medium`) : source_default.gray(`${summary.medium} medium`),
17446
+ source_default.gray(`${summary.low} low`),
17447
+ source_default.gray(`${summary.info} info`)
17448
+ ].join(source_default.gray(" "));
17449
+ lines.push(` ${sev}`);
17450
+ lines.push(` ${source_default.white.bold(String(summary.totalFindings))} findings ${source_default.gray("in")} ${source_default.white(formatDuration(report.durationMs))}`);
17476
17451
  lines.push("");
17477
17452
  return lines.join("\n");
17478
17453
  }
@@ -17497,17 +17472,6 @@ function formatFinding(finding) {
17497
17472
  lines.push("");
17498
17473
  return lines.join("\n");
17499
17474
  }
17500
- function buildSeverityLine(summary) {
17501
- const parts = [];
17502
- const severities = ["critical", "high", "medium", "low", "info"];
17503
- for (const sev of severities) {
17504
- const count = summary[sev];
17505
- const color = SEVERITY_COUNT_COLOR[sev];
17506
- const icon = SEVERITY_STYLE[sev].icon;
17507
- parts.push(` ${color(icon)} ${color(String(count))} ${source_default.gray(SEVERITY_STYLE[sev].label)}`);
17508
- }
17509
- return parts.join(source_default.gray(" "));
17510
- }
17511
17475
  function formatCategory(cat) {
17512
17476
  return cat.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
17513
17477
  }
@@ -17628,21 +17592,21 @@ function severityBadge(severity) {
17628
17592
  function sleep(ms) {
17629
17593
  return new Promise((resolve3) => setTimeout(resolve3, ms));
17630
17594
  }
17631
- function stripAnsi3(s) {
17595
+ function stripAnsi2(s) {
17632
17596
  return s.replace(/\x1b\[[0-9;]*m/g, "");
17633
17597
  }
17634
17598
  var BOX_WIDTH = 55;
17635
- function boxTop2(label) {
17599
+ function boxTop(label) {
17636
17600
  const inner = ` ${label} `;
17637
17601
  const remaining = BOX_WIDTH - inner.length - 1;
17638
17602
  return source_default.dim("\u250C\u2500 ") + source_default.bold.white(label) + source_default.dim(" " + "\u2500".repeat(Math.max(0, remaining)) + "\u2510");
17639
17603
  }
17640
- function boxRow2(content) {
17641
- const visible = stripAnsi3(content);
17604
+ function boxRow(content) {
17605
+ const visible = stripAnsi2(content);
17642
17606
  const pad = Math.max(0, BOX_WIDTH - visible.length - 2);
17643
17607
  return source_default.dim("\u2502") + " " + content + " ".repeat(pad) + source_default.dim("\u2502");
17644
17608
  }
17645
- function boxBottom2(withArrow) {
17609
+ function boxBottom(withArrow) {
17646
17610
  if (withArrow) {
17647
17611
  const half = Math.floor((BOX_WIDTH - 1) / 2);
17648
17612
  const rest = BOX_WIDTH - half - 1;
@@ -17676,19 +17640,19 @@ function buildReplayLines(data) {
17676
17640
  const MED = 75;
17677
17641
  const SLOW = 100;
17678
17642
  const PAUSE = 200;
17679
- lines.push({ text: boxTop2("DISCOVER"), delay: PAUSE });
17643
+ lines.push({ text: boxTop("DISCOVER"), delay: PAUSE });
17680
17644
  if (data.targetInfo) {
17681
17645
  const t2 = data.targetInfo;
17682
17646
  const truncUrl = t2.url.length > 30 ? t2.url.slice(0, 27) + "..." : t2.url;
17683
17647
  lines.push({
17684
- text: boxRow2(
17648
+ text: boxRow(
17685
17649
  source_default.dim("\u25B8") + " " + source_default.white(`GET ${truncUrl}`) + source_default.dim(" \u2192 ") + source_default.white(`200`) + source_default.gray(` (${t2.type} endpoint detected)`)
17686
17650
  ),
17687
17651
  delay: MED
17688
17652
  });
17689
17653
  if (t2.systemPrompt) {
17690
17654
  lines.push({
17691
- text: boxRow2(
17655
+ text: boxRow(
17692
17656
  source_default.dim("\u25B8") + " " + source_default.white(`System prompt extracted`) + source_default.gray(` (${t2.systemPrompt.length} chars)`)
17693
17657
  ),
17694
17658
  delay: MED
@@ -17696,7 +17660,7 @@ function buildReplayLines(data) {
17696
17660
  }
17697
17661
  if (t2.detectedFeatures && t2.detectedFeatures.length > 0) {
17698
17662
  lines.push({
17699
- text: boxRow2(
17663
+ text: boxRow(
17700
17664
  source_default.dim("\u25B8") + " " + source_default.white(`${t2.detectedFeatures.length} features detected: `) + source_default.gray(t2.detectedFeatures.slice(0, 3).join(", "))
17701
17665
  ),
17702
17666
  delay: MED
@@ -17704,7 +17668,7 @@ function buildReplayLines(data) {
17704
17668
  }
17705
17669
  if (t2.endpoints && t2.endpoints.length > 0) {
17706
17670
  lines.push({
17707
- text: boxRow2(
17671
+ text: boxRow(
17708
17672
  source_default.dim("\u25B8") + " " + source_default.white(`${t2.endpoints.length} endpoints found`)
17709
17673
  ),
17710
17674
  delay: MED
@@ -17713,15 +17677,15 @@ function buildReplayLines(data) {
17713
17677
  } else {
17714
17678
  const truncTarget = data.target.length > 30 ? data.target.slice(0, 27) + "..." : data.target;
17715
17679
  lines.push({
17716
- text: boxRow2(
17680
+ text: boxRow(
17717
17681
  source_default.dim("\u25B8") + " " + source_default.white(`GET ${truncTarget}`) + source_default.dim(" \u2192 ") + source_default.white("200") + source_default.gray(" (LLM endpoint detected)")
17718
17682
  ),
17719
17683
  delay: MED
17720
17684
  });
17721
17685
  }
17722
- lines.push({ text: boxBottom2(true), delay: FAST });
17686
+ lines.push({ text: boxBottom(true), delay: FAST });
17723
17687
  lines.push({ text: connector(), delay: PAUSE });
17724
- lines.push({ text: boxTop2("ATTACK"), delay: PAUSE });
17688
+ lines.push({ text: boxTop("ATTACK"), delay: PAUSE });
17725
17689
  const vulnerableFindings = data.findings.filter(
17726
17690
  (f) => f.status !== "false-positive"
17727
17691
  );
@@ -17733,7 +17697,7 @@ function buildReplayLines(data) {
17733
17697
  if (cat === "system-prompt-extraction") outcome = "LEAKED";
17734
17698
  if (cat === "jailbreak") outcome = "BYPASSED";
17735
17699
  lines.push({
17736
- text: boxRow2(
17700
+ text: boxRow(
17737
17701
  source_default.dim("\u25B8") + " " + source_default.white(truncTitle) + source_default.dim(" \u2192 ") + " " + outcomeLabel(outcome.toLowerCase())
17738
17702
  ),
17739
17703
  delay: MED
@@ -17741,7 +17705,7 @@ function buildReplayLines(data) {
17741
17705
  }
17742
17706
  if (vulnerableFindings.length > 8) {
17743
17707
  lines.push({
17744
- text: boxRow2(
17708
+ text: boxRow(
17745
17709
  source_default.gray(
17746
17710
  ` ... and ${vulnerableFindings.length - 8} more attacks`
17747
17711
  )
@@ -17751,15 +17715,15 @@ function buildReplayLines(data) {
17751
17715
  }
17752
17716
  } else {
17753
17717
  lines.push({
17754
- text: boxRow2(
17718
+ text: boxRow(
17755
17719
  source_default.dim("\u25B8") + " " + source_default.white(`${data.summary.totalAttacks} probes executed`) + source_default.dim(" \u2192 ") + source_default.green("ALL SAFE")
17756
17720
  ),
17757
17721
  delay: MED
17758
17722
  });
17759
17723
  }
17760
- lines.push({ text: boxBottom2(true), delay: FAST });
17724
+ lines.push({ text: boxBottom(true), delay: FAST });
17761
17725
  lines.push({ text: connector(), delay: PAUSE });
17762
- lines.push({ text: boxTop2("VERIFY"), delay: PAUSE });
17726
+ lines.push({ text: boxTop("VERIFY"), delay: PAUSE });
17763
17727
  const confirmed = data.findings.filter(
17764
17728
  (f) => f.status === "confirmed" || f.status === "verified" || f.status === "scored" || f.status === "reported"
17765
17729
  );
@@ -17769,7 +17733,7 @@ function buildReplayLines(data) {
17769
17733
  if (confirmed.length > 0 || data.findings.length > 0) {
17770
17734
  const reproduced = confirmed.length > 0 ? confirmed.length : data.findings.length;
17771
17735
  lines.push({
17772
- text: boxRow2(
17736
+ text: boxRow(
17773
17737
  source_default.green("\u2713") + " " + source_default.white(`Reproduced ${reproduced}/${reproduced} findings`)
17774
17738
  ),
17775
17739
  delay: MED
@@ -17777,7 +17741,7 @@ function buildReplayLines(data) {
17777
17741
  }
17778
17742
  if (falsePositives.length > 0) {
17779
17743
  lines.push({
17780
- text: boxRow2(
17744
+ text: boxRow(
17781
17745
  source_default.red("\u2717") + " " + source_default.white(`Eliminated ${falsePositives.length} false positives`)
17782
17746
  ),
17783
17747
  delay: MED
@@ -17785,13 +17749,13 @@ function buildReplayLines(data) {
17785
17749
  }
17786
17750
  if (confirmed.length === 0 && falsePositives.length === 0 && data.findings.length === 0) {
17787
17751
  lines.push({
17788
- text: boxRow2(source_default.green("\u2713") + " " + source_default.white("No findings to verify")),
17752
+ text: boxRow(source_default.green("\u2713") + " " + source_default.white("No findings to verify")),
17789
17753
  delay: MED
17790
17754
  });
17791
17755
  }
17792
- lines.push({ text: boxBottom2(true), delay: FAST });
17756
+ lines.push({ text: boxBottom(true), delay: FAST });
17793
17757
  lines.push({ text: connector(), delay: PAUSE });
17794
- lines.push({ text: boxTop2("REPORT"), delay: PAUSE });
17758
+ lines.push({ text: boxTop("REPORT"), delay: PAUSE });
17795
17759
  const totalFindings = data.summary.totalFindings;
17796
17760
  if (totalFindings > 0) {
17797
17761
  const parts = [];
@@ -17801,25 +17765,25 @@ function buildReplayLines(data) {
17801
17765
  if (data.summary.low > 0) parts.push(source_default.blue(`${data.summary.low} LOW`));
17802
17766
  if (data.summary.info > 0) parts.push(source_default.gray(`${data.summary.info} INFO`));
17803
17767
  lines.push({
17804
- text: boxRow2(
17768
+ text: boxRow(
17805
17769
  source_default.white(`${totalFindings} verified findings: `) + parts.join(source_default.dim(", "))
17806
17770
  ),
17807
17771
  delay: MED
17808
17772
  });
17809
17773
  } else {
17810
17774
  lines.push({
17811
- text: boxRow2(source_default.green.bold("0 findings") + source_default.white(" - target appears secure")),
17775
+ text: boxRow(source_default.green.bold("0 findings") + source_default.white(" - target appears secure")),
17812
17776
  delay: MED
17813
17777
  });
17814
17778
  }
17815
17779
  const duration = data.durationMs < 1e3 ? `${data.durationMs}ms` : `${(data.durationMs / 1e3).toFixed(1)}s`;
17816
17780
  lines.push({
17817
- text: boxRow2(
17781
+ text: boxRow(
17818
17782
  source_default.white(`Completed in ${duration}`) + source_default.dim(" \u2192 ") + source_default.gray("./pwnkit-report.json")
17819
17783
  ),
17820
17784
  delay: MED
17821
17785
  });
17822
- lines.push({ text: boxBottom2(false), delay: FAST });
17786
+ lines.push({ text: boxBottom(false), delay: FAST });
17823
17787
  return lines;
17824
17788
  }
17825
17789
  async function renderReplay(data) {
@@ -18197,7 +18161,7 @@ program2.command("scan").description("Run security scan against an LLM endpoint"
18197
18161
  if (format !== "terminal") return;
18198
18162
  switch (event.type) {
18199
18163
  case "stage:start":
18200
- if (verbose) {
18164
+ {
18201
18165
  const msg = event.message;
18202
18166
  if (msg.startsWith("Reading ")) {
18203
18167
  spinner?.stop();
@@ -18209,16 +18173,8 @@ program2.command("scan").description("Run security scan against an LLM endpoint"
18209
18173
  spinner?.start();
18210
18174
  } else {
18211
18175
  spinner?.update(msg);
18176
+ spinner?.start();
18212
18177
  }
18213
- } else if (event.stage === "attack") {
18214
- const match = event.message.match(/(\d+)/);
18215
- if (match) attackTotal = parseInt(match[1], 10);
18216
- attacksDone = 0;
18217
- spinner?.update(`Running attacks ${renderProgressBar(0, attackTotal || 1)}`);
18218
- spinner?.start();
18219
- } else {
18220
- spinner?.update(event.message);
18221
- spinner?.start();
18222
18178
  }
18223
18179
  break;
18224
18180
  case "attack:end":
@@ -18241,11 +18197,11 @@ program2.command("scan").description("Run security scan against an LLM endpoint"
18241
18197
  }
18242
18198
  break;
18243
18199
  case "finding":
18244
- if (verbose) {
18245
- console.log(
18246
- ` ${source_default.yellow("\u26A1")} ${source_default.yellow(event.message)}`
18247
- );
18248
- }
18200
+ spinner?.stop();
18201
+ console.log(
18202
+ ` ${source_default.yellow("\u26A1")} ${source_default.yellow(event.message)}`
18203
+ );
18204
+ spinner?.start();
18249
18205
  break;
18250
18206
  case "error":
18251
18207
  spinner?.fail(event.message);
@@ -18496,11 +18452,11 @@ program2.command("review").description("Deep source code security review of a re
18496
18452
  switch (event.type) {
18497
18453
  case "stage:start": {
18498
18454
  const msg = event.message;
18499
- if (verbose && msg.startsWith("Reading ")) {
18455
+ if (msg.startsWith("Reading ")) {
18500
18456
  spinner?.stop();
18501
18457
  console.log(` ${source_default.cyan("\u2192")} ${source_default.cyan("read")} ${source_default.gray(msg.replace("Reading ", ""))}`);
18502
18458
  spinner?.start();
18503
- } else if (verbose && msg.startsWith("Running: ")) {
18459
+ } else if (msg.startsWith("Running: ")) {
18504
18460
  spinner?.stop();
18505
18461
  console.log(` ${source_default.magenta("\u2192")} ${source_default.magenta("exec")} ${source_default.gray(msg.replace("Running: ", ""))}`);
18506
18462
  spinner?.start();
@@ -18514,10 +18470,12 @@ program2.command("review").description("Deep source code security review of a re
18514
18470
  spinner?.succeed(event.message);
18515
18471
  break;
18516
18472
  case "finding":
18517
- if (verbose) {
18473
+ {
18474
+ spinner?.stop();
18518
18475
  console.log(
18519
18476
  ` ${source_default.yellow("\u26A1")} ${source_default.yellow(event.message)}`
18520
18477
  );
18478
+ spinner?.start();
18521
18479
  }
18522
18480
  break;
18523
18481
  case "error":
@@ -18612,11 +18570,11 @@ program2.command("audit").description("Audit an npm package for security vulnera
18612
18570
  switch (event.type) {
18613
18571
  case "stage:start": {
18614
18572
  const msg = event.message;
18615
- if (verbose && msg.startsWith("Reading ")) {
18573
+ if (msg.startsWith("Reading ")) {
18616
18574
  spinner?.stop();
18617
18575
  console.log(` ${source_default.cyan("\u2192")} ${source_default.cyan("read")} ${source_default.gray(msg.replace("Reading ", ""))}`);
18618
18576
  spinner?.start();
18619
- } else if (verbose && msg.startsWith("Running: ")) {
18577
+ } else if (msg.startsWith("Running: ")) {
18620
18578
  spinner?.stop();
18621
18579
  console.log(` ${source_default.magenta("\u2192")} ${source_default.magenta("exec")} ${source_default.gray(msg.replace("Running: ", ""))}`);
18622
18580
  spinner?.start();
@@ -18630,10 +18588,12 @@ program2.command("audit").description("Audit an npm package for security vulnera
18630
18588
  spinner?.succeed(event.message);
18631
18589
  break;
18632
18590
  case "finding":
18633
- if (verbose) {
18591
+ {
18592
+ spinner?.stop();
18634
18593
  console.log(
18635
18594
  ` ${source_default.yellow("\u26A1")} ${source_default.yellow(event.message)}`
18636
18595
  );
18596
+ spinner?.start();
18637
18597
  }
18638
18598
  break;
18639
18599
  case "error":
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pwnkit-cli",
3
3
  "type": "module",
4
- "version": "0.1.5",
4
+ "version": "0.1.7",
5
5
  "description": "AI-powered agentic security scanner. Scan endpoints, audit packages, review source code. Autonomous agents discover, attack, verify, and report.",
6
6
  "bin": {
7
7
  "pwnkit": "dist/index.js"