pwnkit-cli 0.3.0 → 0.3.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 (91) hide show
  1. package/dist/commands/audit.d.ts +3 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +32 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/findings.d.ts +3 -0
  6. package/dist/commands/findings.d.ts.map +1 -0
  7. package/dist/commands/findings.js +110 -0
  8. package/dist/commands/findings.js.map +1 -0
  9. package/dist/commands/history.d.ts +3 -0
  10. package/dist/commands/history.d.ts.map +1 -0
  11. package/dist/commands/history.js +34 -0
  12. package/dist/commands/history.js.map +1 -0
  13. package/dist/commands/index.d.ts +7 -0
  14. package/dist/commands/index.d.ts.map +1 -0
  15. package/dist/commands/index.js +7 -0
  16. package/dist/commands/index.js.map +1 -0
  17. package/dist/commands/replay.d.ts +3 -0
  18. package/dist/commands/replay.d.ts.map +1 -0
  19. package/dist/commands/replay.js +83 -0
  20. package/dist/commands/replay.js.map +1 -0
  21. package/dist/commands/review.d.ts +3 -0
  22. package/dist/commands/review.d.ts.map +1 -0
  23. package/dist/commands/review.js +30 -0
  24. package/dist/commands/review.js.map +1 -0
  25. package/dist/commands/run.d.ts +16 -0
  26. package/dist/commands/run.d.ts.map +1 -0
  27. package/dist/commands/run.js +83 -0
  28. package/dist/commands/run.js.map +1 -0
  29. package/dist/commands/scan.d.ts +3 -0
  30. package/dist/commands/scan.d.ts.map +1 -0
  31. package/dist/commands/scan.js +187 -0
  32. package/dist/commands/scan.js.map +1 -0
  33. package/dist/event-handler.d.ts +19 -0
  34. package/dist/event-handler.d.ts.map +1 -0
  35. package/dist/event-handler.js +63 -0
  36. package/dist/event-handler.js.map +1 -0
  37. package/dist/formatters/index.d.ts +14 -0
  38. package/dist/formatters/index.d.ts.map +1 -0
  39. package/dist/formatters/index.js +56 -0
  40. package/dist/formatters/index.js.map +1 -0
  41. package/dist/formatters/json.d.ts +3 -0
  42. package/dist/formatters/json.d.ts.map +1 -0
  43. package/dist/formatters/json.js +4 -0
  44. package/dist/formatters/json.js.map +1 -0
  45. package/dist/formatters/markdown.d.ts +3 -0
  46. package/dist/formatters/markdown.d.ts.map +1 -0
  47. package/dist/formatters/markdown.js +90 -0
  48. package/dist/formatters/markdown.js.map +1 -0
  49. package/dist/formatters/replay.d.ts +24 -0
  50. package/dist/formatters/replay.d.ts.map +1 -0
  51. package/dist/formatters/replay.js +357 -0
  52. package/dist/formatters/replay.js.map +1 -0
  53. package/dist/formatters/terminal.d.ts +4 -0
  54. package/dist/formatters/terminal.d.ts.map +1 -0
  55. package/dist/formatters/terminal.js +190 -0
  56. package/dist/formatters/terminal.js.map +1 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +128 -60799
  60. package/dist/index.js.map +1 -0
  61. package/dist/spinner.d.ts +16 -0
  62. package/dist/spinner.d.ts.map +1 -0
  63. package/dist/spinner.js +97 -0
  64. package/dist/spinner.js.map +1 -0
  65. package/dist/ui/ScanUI.d.ts +37 -0
  66. package/dist/ui/ScanUI.d.ts.map +1 -0
  67. package/dist/ui/ScanUI.js +58 -0
  68. package/dist/ui/ScanUI.js.map +1 -0
  69. package/dist/ui/renderScan.d.ts +21 -0
  70. package/dist/ui/renderScan.d.ts.map +1 -0
  71. package/dist/ui/renderScan.js +191 -0
  72. package/dist/ui/renderScan.js.map +1 -0
  73. package/dist/utils.d.ts +12 -0
  74. package/dist/utils.d.ts.map +1 -0
  75. package/dist/utils.js +40 -0
  76. package/dist/utils.js.map +1 -0
  77. package/package.json +20 -50
  78. package/LICENSE +0 -188
  79. package/README.md +0 -324
  80. package/dist/attacks/data-exfiltration/pii-leakage.yaml +0 -27
  81. package/dist/attacks/encoding-bypass/base64-encoding.yaml +0 -24
  82. package/dist/attacks/jailbreak/dan-roleplay.yaml +0 -27
  83. package/dist/attacks/jailbreak/hypothetical-scenario.yaml +0 -25
  84. package/dist/attacks/jailbreak/multilingual-bypass.yaml +0 -22
  85. package/dist/attacks/output-manipulation/harmful-content.yaml +0 -25
  86. package/dist/attacks/prompt-injection/context-manipulation.yaml +0 -32
  87. package/dist/attacks/prompt-injection/direct-injection.yaml +0 -28
  88. package/dist/attacks/prompt-injection/indirect-injection.yaml +0 -33
  89. package/dist/attacks/system-prompt-extraction/direct-ask.yaml +0 -30
  90. package/dist/attacks/system-prompt-extraction/markdown-exfil.yaml +0 -26
  91. package/dist/attacks/tool-misuse/ssrf-via-tools.yaml +0 -27
@@ -0,0 +1,187 @@
1
+ import chalk from "chalk";
2
+ import { VERSION } from "@pwnkit/shared";
3
+ import { scan, agenticScan, createRuntime } from "@pwnkit/core";
4
+ import { formatReport } from "../formatters/index.js";
5
+ import { renderReplay, replayDataFromReport, createReplayCollector } from "../formatters/replay.js";
6
+ import { createpwnkitSpinner } from "../spinner.js";
7
+ import { createEventHandler } from "../event-handler.js";
8
+ import { buildShareUrl, checkRuntimeAvailability } from "../utils.js";
9
+ export function registerScanCommand(program) {
10
+ program
11
+ .command("scan")
12
+ .description("Run security scan against an LLM endpoint")
13
+ .requiredOption("--target <url>", "Target API endpoint URL")
14
+ .option("--depth <depth>", "Scan depth: quick, default, deep", "default")
15
+ .option("--format <format>", "Output format: terminal, json, md", "terminal")
16
+ .option("--runtime <runtime>", "Runtime: api, claude, codex, gemini, auto", "api")
17
+ .option("--mode <mode>", "Scan mode: probe, deep, mcp, web", "probe")
18
+ .option("--repo <path>", "Path to target repo for deep scan source analysis")
19
+ .option("--timeout <ms>", "Request timeout in milliseconds", "30000")
20
+ .option("--agentic", "Use multi-turn agentic scan with tool use and SQLite persistence", false)
21
+ .option("--db-path <path>", "Path to SQLite database (default: ~/.pwnkit/pwnkit.db)")
22
+ .option("--api-key <key>", "API key for LLM provider (or set OPENROUTER_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY)")
23
+ .option("--model <model>", "LLM model to use (or set PWNKIT_MODEL)")
24
+ .option("--verbose", "Show detailed output with live attack replay", false)
25
+ .option("--replay", "Replay the last scan's results as an animated attack chain", false)
26
+ .action(async (opts) => {
27
+ const depth = opts.depth;
28
+ const format = (opts.format === "md" ? "markdown" : opts.format);
29
+ const runtime = opts.runtime;
30
+ const mode = opts.mode;
31
+ const verbose = opts.verbose;
32
+ const replayMode = opts.replay;
33
+ // ── Replay last scan (--replay flag) ──
34
+ if (replayMode) {
35
+ try {
36
+ const { pwnkitDB } = await import("@pwnkit/db");
37
+ const db = new pwnkitDB(opts.dbPath);
38
+ const scans = db.listScans(1);
39
+ if (scans.length === 0) {
40
+ console.error(chalk.red("No scan history found. Run a scan first."));
41
+ db.close();
42
+ process.exit(2);
43
+ }
44
+ const lastScan = scans[0];
45
+ const dbFindings = db.getFindings(lastScan.id);
46
+ db.close();
47
+ const summary = lastScan.summary ? JSON.parse(lastScan.summary) : {
48
+ totalAttacks: 0, totalFindings: 0,
49
+ critical: 0, high: 0, medium: 0, low: 0, info: 0,
50
+ };
51
+ const findings = dbFindings.map((f) => ({
52
+ id: f.id,
53
+ templateId: f.templateId,
54
+ title: f.title,
55
+ description: f.description,
56
+ severity: f.severity,
57
+ category: f.category,
58
+ status: f.status,
59
+ evidence: {
60
+ request: f.evidenceRequest,
61
+ response: f.evidenceResponse,
62
+ analysis: f.evidenceAnalysis ?? undefined,
63
+ },
64
+ timestamp: f.timestamp,
65
+ }));
66
+ await renderReplay({
67
+ target: lastScan.target,
68
+ findings,
69
+ summary,
70
+ durationMs: lastScan.durationMs ?? 0,
71
+ });
72
+ return;
73
+ }
74
+ catch (err) {
75
+ console.error(chalk.red("Failed to replay: " + (err instanceof Error ? err.message : String(err))));
76
+ process.exit(2);
77
+ }
78
+ }
79
+ // Validate runtime value
80
+ const validRuntimes = ["api", "claude", "codex", "gemini", "auto"];
81
+ if (!validRuntimes.includes(runtime)) {
82
+ console.error(chalk.red(`Unknown runtime '${runtime}'. Valid: ${validRuntimes.join(", ")}`));
83
+ process.exit(2);
84
+ }
85
+ // Deep and MCP modes require a process runtime (web mode works with api runtime)
86
+ if (mode !== "probe" && mode !== "web" && runtime === "api") {
87
+ console.error(chalk.red(`Mode '${mode}' requires a process runtime (claude, codex, gemini, or auto)`));
88
+ process.exit(2);
89
+ }
90
+ // Check runtime availability (auto mode checks at scan time)
91
+ if (runtime !== "api" && runtime !== "auto") {
92
+ const rt = createRuntime({
93
+ type: runtime,
94
+ timeout: parseInt(opts.timeout, 10),
95
+ });
96
+ const available = await rt.isAvailable();
97
+ if (!available) {
98
+ console.error(chalk.red(`Runtime '${runtime}' not available. Is ${runtime} installed?`));
99
+ process.exit(2);
100
+ }
101
+ }
102
+ if (format === "terminal")
103
+ checkRuntimeAvailability();
104
+ const useInkUI = format === "terminal";
105
+ let inkUI = null;
106
+ let spinner = null;
107
+ let eventHandler;
108
+ // Set up replay collector for --verbose mode
109
+ const replayCollector = verbose ? createReplayCollector(opts.target) : null;
110
+ if (useInkUI) {
111
+ const { renderScanUI } = await import("../ui/renderScan.js");
112
+ inkUI = renderScanUI({ version: VERSION, target: opts.target, depth, mode: "scan" });
113
+ eventHandler = (event) => {
114
+ if (replayCollector)
115
+ replayCollector.onEvent(event);
116
+ inkUI.onEvent(event);
117
+ };
118
+ }
119
+ else {
120
+ spinner = createpwnkitSpinner("Initializing...");
121
+ eventHandler = (event) => {
122
+ if (replayCollector)
123
+ replayCollector.onEvent(event);
124
+ createEventHandler({ format, spinner })(event);
125
+ };
126
+ }
127
+ const scanConfig = {
128
+ target: opts.target,
129
+ depth,
130
+ format,
131
+ runtime,
132
+ mode,
133
+ repoPath: opts.repo,
134
+ timeout: parseInt(opts.timeout, 10),
135
+ verbose,
136
+ apiKey: opts.apiKey,
137
+ model: opts.model,
138
+ };
139
+ try {
140
+ // Web mode always uses agentic scanner (needs AI to reason about HTTP responses)
141
+ const useAgentic = opts.agentic || mode === "web";
142
+ const report = useAgentic
143
+ ? await agenticScan({
144
+ config: scanConfig,
145
+ dbPath: opts.dbPath,
146
+ onEvent: eventHandler,
147
+ })
148
+ : await scan(scanConfig, eventHandler, opts.dbPath);
149
+ if (inkUI) {
150
+ // In verbose mode, show the animated attack replay before the report
151
+ if (verbose) {
152
+ inkUI.setReport(report);
153
+ await inkUI.waitForExit();
154
+ await renderReplay(replayDataFromReport(report));
155
+ }
156
+ else {
157
+ inkUI.setReport(report);
158
+ await inkUI.waitForExit();
159
+ }
160
+ }
161
+ else {
162
+ // In verbose mode, show the animated attack replay before the report
163
+ if (verbose && format === "terminal") {
164
+ await renderReplay(replayDataFromReport(report));
165
+ }
166
+ const output = formatReport(report, format);
167
+ console.log(output);
168
+ if (format === "terminal") {
169
+ console.log(`\n ${chalk.gray("Share this report:")} ${chalk.cyan(buildShareUrl(report))}\n`);
170
+ }
171
+ }
172
+ // Exit with non-zero if critical/high findings
173
+ if (report.summary.critical > 0 || report.summary.high > 0) {
174
+ process.exit(1);
175
+ }
176
+ if (report.warnings.length > 0) {
177
+ process.exit(2);
178
+ }
179
+ }
180
+ catch (err) {
181
+ spinner?.fail("Scan failed");
182
+ console.error(chalk.red(err instanceof Error ? err.message : String(err)));
183
+ process.exit(2);
184
+ }
185
+ });
186
+ }
187
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { OutputFormat } from "@pwnkit/shared";
2
+ import type { createpwnkitSpinner } from "./spinner.js";
3
+ export interface EventHandlerOptions {
4
+ format: OutputFormat;
5
+ spinner: ReturnType<typeof createpwnkitSpinner> | null;
6
+ /** Enable attack:end progress tracking (used by scan command). */
7
+ trackAttacks?: {
8
+ getTotal: () => number;
9
+ getDone: () => number;
10
+ incrementDone: () => void;
11
+ };
12
+ }
13
+ export declare function createEventHandler(opts: EventHandlerOptions): (event: {
14
+ type: string;
15
+ stage?: string;
16
+ message: string;
17
+ data?: unknown;
18
+ }) => void;
19
+ //# sourceMappingURL=event-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handler.d.ts","sourceRoot":"","sources":["../src/event-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,GAAG,IAAI,CAAC;IACvD,kEAAkE;IAClE,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,MAAM,CAAC;QACvB,OAAO,EAAE,MAAM,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,IAAI,CAAC;KAC3B,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,IAGlD,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,UA+DjF"}
@@ -0,0 +1,63 @@
1
+ import chalk from "chalk";
2
+ import { renderProgressBar } from "./formatters/terminal.js";
3
+ export function createEventHandler(opts) {
4
+ const { format, spinner, trackAttacks } = opts;
5
+ return (event) => {
6
+ if (format !== "terminal")
7
+ return;
8
+ switch (event.type) {
9
+ case "stage:start": {
10
+ const msg = event.message;
11
+ if (msg.startsWith("Reading ")) {
12
+ spinner?.stop();
13
+ console.log(` ${chalk.cyan("\u2192")} ${chalk.cyan("read")} ${chalk.gray(msg.replace("Reading ", ""))}`);
14
+ spinner?.start();
15
+ }
16
+ else if (msg.startsWith("Running: ")) {
17
+ spinner?.stop();
18
+ console.log(` ${chalk.magenta("\u2192")} ${chalk.magenta("exec")} ${chalk.gray(msg.replace("Running: ", ""))}`);
19
+ spinner?.start();
20
+ }
21
+ else {
22
+ spinner?.update(msg);
23
+ spinner?.start();
24
+ }
25
+ break;
26
+ }
27
+ case "attack:end":
28
+ if (trackAttacks) {
29
+ trackAttacks.incrementDone();
30
+ const total = trackAttacks.getTotal();
31
+ if (spinner && total > 0) {
32
+ spinner.update(`Running attacks ${renderProgressBar(trackAttacks.getDone(), total)}`);
33
+ }
34
+ }
35
+ break;
36
+ case "stage:end":
37
+ if (trackAttacks && event.stage === "attack") {
38
+ const total = trackAttacks.getTotal();
39
+ spinner?.succeed(`${chalk.gray("Attacks complete")} ${renderProgressBar(total, total)}`);
40
+ }
41
+ else if (event.stage === "discovery" &&
42
+ typeof event.data === "object" &&
43
+ event.data !== null &&
44
+ "success" in event.data &&
45
+ event.data.success === false) {
46
+ spinner?.warn(event.message);
47
+ }
48
+ else {
49
+ spinner?.succeed(event.message);
50
+ }
51
+ break;
52
+ case "finding":
53
+ spinner?.stop();
54
+ console.log(` ${chalk.yellow("\u26A1")} ${chalk.yellow(event.message)}`);
55
+ spinner?.start();
56
+ break;
57
+ case "error":
58
+ spinner?.fail(event.message);
59
+ break;
60
+ }
61
+ };
62
+ }
63
+ //# sourceMappingURL=event-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-handler.js","sourceRoot":"","sources":["../src/event-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ScanReport, AuditReport, ReviewReport, OutputFormat } from "@pwnkit/shared";
2
+ export { renderReplay, renderReplayStatic, replayDataFromReport, createReplayCollector } from "./replay.js";
3
+ export type { ReplayData, ReplayCollector } from "./replay.js";
4
+ export declare function formatReport(report: ScanReport, format: OutputFormat): string;
5
+ /**
6
+ * Format an audit report. Adapts AuditReport to ScanReport for reuse,
7
+ * but adds audit-specific header information.
8
+ */
9
+ export declare function formatAuditReport(report: AuditReport, format: OutputFormat): string;
10
+ /**
11
+ * Format a review report. Adapts ReviewReport to ScanReport for reuse.
12
+ */
13
+ export declare function formatReviewReport(report: ReviewReport, format: OutputFormat): string;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI1F,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC5G,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE/D,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAS7E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,YAAY,GACnB,MAAM,CAmBR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,MAAM,CAiBR"}
@@ -0,0 +1,56 @@
1
+ import { formatTerminal } from "./terminal.js";
2
+ import { formatJson } from "./json.js";
3
+ import { formatMarkdown } from "./markdown.js";
4
+ export { renderReplay, renderReplayStatic, replayDataFromReport, createReplayCollector } from "./replay.js";
5
+ export function formatReport(report, format) {
6
+ switch (format) {
7
+ case "terminal":
8
+ return formatTerminal(report);
9
+ case "json":
10
+ return formatJson(report);
11
+ case "markdown":
12
+ return formatMarkdown(report);
13
+ }
14
+ }
15
+ /**
16
+ * Format an audit report. Adapts AuditReport to ScanReport for reuse,
17
+ * but adds audit-specific header information.
18
+ */
19
+ export function formatAuditReport(report, format) {
20
+ // Convert to ScanReport shape for formatters
21
+ const scanReport = {
22
+ target: `${report.package}@${report.version}`,
23
+ scanDepth: "deep",
24
+ startedAt: report.startedAt,
25
+ completedAt: report.completedAt,
26
+ durationMs: report.durationMs,
27
+ summary: report.summary,
28
+ findings: report.findings,
29
+ warnings: [],
30
+ };
31
+ if (format === "json") {
32
+ // For JSON, return the full audit report with extra fields
33
+ return JSON.stringify(report, null, 2);
34
+ }
35
+ return formatReport(scanReport, format);
36
+ }
37
+ /**
38
+ * Format a review report. Adapts ReviewReport to ScanReport for reuse.
39
+ */
40
+ export function formatReviewReport(report, format) {
41
+ const scanReport = {
42
+ target: report.repo,
43
+ scanDepth: "deep",
44
+ startedAt: report.startedAt,
45
+ completedAt: report.completedAt,
46
+ durationMs: report.durationMs,
47
+ summary: report.summary,
48
+ findings: report.findings,
49
+ warnings: [],
50
+ };
51
+ if (format === "json") {
52
+ return JSON.stringify(report, null, 2);
53
+ }
54
+ return formatReport(scanReport, format);
55
+ }
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAG5G,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,MAAoB;IACnE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,UAAU;YACb,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;QAChC,KAAK,MAAM;YACT,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,UAAU;YACb,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAmB,EACnB,MAAoB;IAEpB,6CAA6C;IAC7C,MAAM,UAAU,GAAe;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE;QAC7C,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,2DAA2D;QAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAoB,EACpB,MAAoB;IAEpB,MAAM,UAAU,GAAe;QAC7B,MAAM,EAAE,MAAM,CAAC,IAAI;QACnB,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ScanReport } from "@pwnkit/shared";
2
+ export declare function formatJson(report: ScanReport): string;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAErD"}
@@ -0,0 +1,4 @@
1
+ export function formatJson(report) {
2
+ return JSON.stringify(report, null, 2);
3
+ }
4
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ScanReport } from "@pwnkit/shared";
2
+ export declare function formatMarkdown(report: ScanReport): string;
3
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/formatters/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,gBAAgB,CAAC;AAE1D,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAoDzD"}
@@ -0,0 +1,90 @@
1
+ export function formatMarkdown(report) {
2
+ const lines = [];
3
+ lines.push("# pwnkit Scan Report");
4
+ lines.push("");
5
+ lines.push(`| Field | Value |`);
6
+ lines.push(`|-------|-------|`);
7
+ lines.push(`| Target | ${report.target} |`);
8
+ lines.push(`| Depth | ${report.scanDepth} |`);
9
+ lines.push(`| Started | ${report.startedAt} |`);
10
+ lines.push(`| Duration | ${(report.durationMs / 1000).toFixed(1)}s |`);
11
+ lines.push("");
12
+ // Summary
13
+ lines.push("## Summary");
14
+ lines.push("");
15
+ lines.push(`- **Attacks:** ${report.summary.totalAttacks}`);
16
+ lines.push(`- **Findings:** ${report.summary.totalFindings}`);
17
+ if (report.summary.critical > 0)
18
+ lines.push(`- **Critical:** ${report.summary.critical}`);
19
+ if (report.summary.high > 0)
20
+ lines.push(`- **High:** ${report.summary.high}`);
21
+ if (report.summary.medium > 0)
22
+ lines.push(`- **Medium:** ${report.summary.medium}`);
23
+ if (report.summary.low > 0)
24
+ lines.push(`- **Low:** ${report.summary.low}`);
25
+ lines.push("");
26
+ if (report.warnings.length > 0) {
27
+ lines.push("## Warnings");
28
+ lines.push("");
29
+ for (const warning of report.warnings) {
30
+ lines.push(`- **${warning.stage}:** ${warning.message}`);
31
+ }
32
+ lines.push("");
33
+ }
34
+ // Findings
35
+ if (report.findings.length > 0) {
36
+ lines.push("## Findings");
37
+ lines.push("");
38
+ for (const finding of report.findings) {
39
+ lines.push(formatFinding(finding));
40
+ }
41
+ }
42
+ else {
43
+ lines.push(report.warnings.length > 0 ? "## No Confirmed Vulnerabilities" : "## No Vulnerabilities Found");
44
+ lines.push("");
45
+ lines.push(report.warnings.length > 0
46
+ ? "The scanner did not confirm vulnerabilities, but target validation or probe execution produced warnings."
47
+ : "The target passed all tests.");
48
+ }
49
+ return lines.join("\n");
50
+ }
51
+ function formatFinding(finding) {
52
+ const lines = [];
53
+ const badge = severityBadge(finding.severity);
54
+ lines.push(`### ${badge} ${finding.title}`);
55
+ lines.push("");
56
+ lines.push(`- **Category:** ${finding.category}`);
57
+ lines.push(`- **Status:** ${finding.status}`);
58
+ lines.push(`- **Description:** ${finding.description}`);
59
+ lines.push("");
60
+ if (finding.evidence.analysis) {
61
+ lines.push(`**Evidence:** ${finding.evidence.analysis}`);
62
+ lines.push("");
63
+ }
64
+ lines.push("<details>");
65
+ lines.push("<summary>Request / Response</summary>");
66
+ lines.push("");
67
+ lines.push("**Request:**");
68
+ lines.push("```");
69
+ lines.push(finding.evidence.request.slice(0, 500));
70
+ lines.push("```");
71
+ lines.push("");
72
+ lines.push("**Response:**");
73
+ lines.push("```");
74
+ lines.push(finding.evidence.response.slice(0, 500));
75
+ lines.push("```");
76
+ lines.push("</details>");
77
+ lines.push("");
78
+ return lines.join("\n");
79
+ }
80
+ function severityBadge(severity) {
81
+ const badges = {
82
+ critical: "[CRITICAL]",
83
+ high: "[HIGH]",
84
+ medium: "[MEDIUM]",
85
+ low: "[LOW]",
86
+ info: "[INFO]",
87
+ };
88
+ return badges[severity] ?? `[${severity.toUpperCase()}]`;
89
+ }
90
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/formatters/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { ScanReport, Finding, AttackResult, TargetInfo } from "@pwnkit/shared";
2
+ export interface ReplayData {
3
+ target: string;
4
+ targetInfo?: TargetInfo;
5
+ findings: Finding[];
6
+ attackResults?: AttackResult[];
7
+ summary: ScanReport["summary"];
8
+ durationMs: number;
9
+ warnings?: ScanReport["warnings"];
10
+ }
11
+ export declare function renderReplay(data: ReplayData): Promise<void>;
12
+ export declare function renderReplayStatic(data: ReplayData): string;
13
+ export interface ReplayCollector {
14
+ onEvent: (event: {
15
+ type: string;
16
+ stage?: string;
17
+ message: string;
18
+ data?: unknown;
19
+ }) => void;
20
+ getReplayData: () => ReplayData;
21
+ }
22
+ export declare function createReplayCollector(target: string): ReplayCollector;
23
+ export declare function replayDataFromReport(report: ScanReport): ReplayData;
24
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/formatters/replay.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EACP,YAAY,EACZ,UAAU,EAEX,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;CACnC;AA2TD,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBlE;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAiB3D;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE;QACf,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,KAAK,IAAI,CAAC;IACX,aAAa,EAAE,MAAM,UAAU,CAAC;CACjC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAkFrE;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAQnE"}