@clawvard/sdk 0.14.0 → 0.15.0

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.
@@ -0,0 +1,519 @@
1
+ /**
2
+ * `cv.security.pentestRun` — hand-written orchestration for the
3
+ * `agent-pentest` course.
4
+ *
5
+ * The pentest agent (open-source `strix-agent`, Apache-2.0) runs
6
+ * locally against a target the user owns — usually a self-hosted
7
+ * OWASP Juice Shop or a staging build of their own web app. The SDK
8
+ * mints a one-time LLM credential scoped to this run via
9
+ * `service.clawvard`, spawns the `strix` CLI as a subprocess with the
10
+ * credential exposed as `LLM_API_KEY`, and normalises the
11
+ * `strix_runs/<name>/` directory into the typed
12
+ * `SecurityPentestRunOutput` shape when the process exits.
13
+ *
14
+ * Node-only. Attempting to call `pentestRun` in a browser (or any
15
+ * environment without `child_process`) throws
16
+ * `SandboxMissingError` early — Strix launches its agent sandbox in a
17
+ * local Docker container.
18
+ *
19
+ * The credential handed to Strix expires when the run resolves or
20
+ * hits the wall-clock timeout. The SDK does NOT hard-code an
21
+ * OpenAI-compatible relay base URL in the run — the endpoint is
22
+ * chosen by `service.clawvard` at mint time.
23
+ *
24
+ * Callers can pattern-match on the SDK-side error subclasses:
25
+ *
26
+ * try {
27
+ * await cv.security.pentestRun({...});
28
+ * } catch (err) {
29
+ * if (err instanceof TargetUnreachableError) { ... }
30
+ * if (err instanceof InvalidTargetHostError) { ... }
31
+ * if (err instanceof SandboxMissingError) { ... }
32
+ * if (err instanceof OwnershipUnconfirmedError) { ... }
33
+ * if (err instanceof LlmQuotaError) { ... }
34
+ * if (err instanceof PentestTimeoutError) { ... }
35
+ * if (err instanceof StrixCrashedError) { ... }
36
+ * }
37
+ */
38
+ import { ClawvardError } from "./errors.js";
39
+ import { SecurityNamespace } from "./generated.js";
40
+ export const PENTEST_ERROR_CODES = [
41
+ "target_unreachable",
42
+ "invalid_target_host",
43
+ "sandbox_missing",
44
+ "ownership_unconfirmed",
45
+ "llm_quota",
46
+ "timeout",
47
+ "strix_crashed",
48
+ ];
49
+ /** Base class for any error surfaced by `cv.security.pentestRun`. */
50
+ export class PentestError extends ClawvardError {
51
+ constructor(code, message) {
52
+ super(message, code);
53
+ this.name = "PentestError";
54
+ }
55
+ }
56
+ /** `HEAD <targetUrl>` failed before Strix could be spawned. Usually
57
+ * means the user forgot to `docker run` the target, or bound it to a
58
+ * port other than the one they wrote in the prompt. */
59
+ export class TargetUnreachableError extends PentestError {
60
+ constructor(message = "Target URL could not be reached — start the target (e.g. `docker run --rm -p 3000:3000 bkimminich/juice-shop`) and retry.") {
61
+ super("target_unreachable", message);
62
+ this.name = "TargetUnreachableError";
63
+ }
64
+ }
65
+ /** Either the input `targetUrl` isn't in `allowedHosts`, or Strix
66
+ * tried to reach a host outside the whitelist mid-run. The SDK kills
67
+ * the run instead of letting a coerced prompt escape the sandbox. */
68
+ export class InvalidTargetHostError extends PentestError {
69
+ constructor(message = "Target host is not in `allowedHosts`. Add the exact host:port shown in `targetUrl` and retry.") {
70
+ super("invalid_target_host", message);
71
+ this.name = "InvalidTargetHostError";
72
+ }
73
+ }
74
+ /** Local Docker daemon is missing or unreachable, `strix` is not on
75
+ * PATH, or the environment cannot spawn subprocesses (browser). */
76
+ export class SandboxMissingError extends PentestError {
77
+ constructor(message = "Local sandbox is not ready — install strix-agent (`pipx install strix-agent`), start Docker, and retry.") {
78
+ super("sandbox_missing", message);
79
+ this.name = "SandboxMissingError";
80
+ }
81
+ }
82
+ /** `ownership.confirmed` was missing or `false`. The service will not
83
+ * attack a target the caller has not declared they own or are
84
+ * authorised to test. */
85
+ export class OwnershipUnconfirmedError extends PentestError {
86
+ constructor(message = "Set `ownership.confirmed = true` and a truthful `ownership.statement` to run against your own target.") {
87
+ super("ownership_unconfirmed", message);
88
+ this.name = "OwnershipUnconfirmedError";
89
+ }
90
+ }
91
+ /** The caller's Clawvard credits balance is below the per-run budget
92
+ * the SDK reserved from `security.pentest-run`. Top up at
93
+ * https://clawvard.school and retry. */
94
+ export class LlmQuotaError extends PentestError {
95
+ constructor(message = "Not enough Clawvard credits reserved for this run — top up at https://clawvard.school and retry.") {
96
+ super("llm_quota", message);
97
+ this.name = "LlmQuotaError";
98
+ }
99
+ }
100
+ /** Wall-clock timeout hit before Strix marked the run complete. The
101
+ * scoped LLM credential is revoked at this point so the run cannot
102
+ * keep grinding credits in the background. */
103
+ export class PentestTimeoutError extends PentestError {
104
+ constructor(message = "Pentest run exceeded its wall-clock budget. Split by iteration cap or retry with a smaller target.") {
105
+ super("timeout", message);
106
+ this.name = "PentestTimeoutError";
107
+ }
108
+ }
109
+ /** Strix subprocess exited non-zero. Message carries the tail of
110
+ * Strix's stderr so the caller can see what actually broke — usually
111
+ * a docker-in-docker permissions issue or an interrupted run. */
112
+ export class StrixCrashedError extends PentestError {
113
+ constructor(message) {
114
+ super("strix_crashed", message);
115
+ this.name = "StrixCrashedError";
116
+ }
117
+ }
118
+ /** Map a backend error envelope (`{ error: code, message }`) to the
119
+ * matching SDK class. Called when the credential-mint step or the
120
+ * server-side preflight fails before Strix is spawned. */
121
+ export function mapPentestError(code, message) {
122
+ switch (code) {
123
+ case "target_unreachable":
124
+ return new TargetUnreachableError(message);
125
+ case "invalid_target_host":
126
+ return new InvalidTargetHostError(message);
127
+ case "sandbox_missing":
128
+ return new SandboxMissingError(message);
129
+ case "ownership_unconfirmed":
130
+ return new OwnershipUnconfirmedError(message);
131
+ case "llm_quota":
132
+ return new LlmQuotaError(message);
133
+ case "timeout":
134
+ return new PentestTimeoutError(message);
135
+ case "strix_crashed":
136
+ return new StrixCrashedError(message);
137
+ default:
138
+ return new PentestError(code, message);
139
+ }
140
+ }
141
+ /** Attach the hand-written `pentestRun` to the SecurityNamespace
142
+ * prototype. Called from the Clawvard constructor so browsers still
143
+ * see the method (even if calling it throws SandboxMissingError). */
144
+ export function installPentestRun(_client) {
145
+ if (Object.prototype.hasOwnProperty.call(SecurityNamespace.prototype, "pentestRun")) {
146
+ return;
147
+ }
148
+ async function pentestRunImpl(input) {
149
+ validateOwnership(input.ownership);
150
+ validateAllowedHosts(input.targetUrl, input.allowedHosts);
151
+ const nodeApis = await loadNodeApis();
152
+ if (!nodeApis) {
153
+ throw new SandboxMissingError("cv.security.pentestRun requires Node.js — it spawns the local `strix` CLI. Browser environments are not supported.");
154
+ }
155
+ await preflightTarget(input.targetUrl);
156
+ const outputDir = await resolveOutputDir(input, nodeApis);
157
+ const credential = await rethrowAsPentest(this.mintPentestCredential(input));
158
+ return runStrix(input, credential, outputDir, nodeApis);
159
+ }
160
+ Object.defineProperty(SecurityNamespace.prototype, "pentestRun", {
161
+ value: pentestRunImpl,
162
+ writable: true,
163
+ configurable: true,
164
+ });
165
+ }
166
+ async function loadNodeApis() {
167
+ try {
168
+ const [cp, fs, path, os] = await Promise.all([
169
+ import("node:child_process"),
170
+ import("node:fs/promises"),
171
+ import("node:path"),
172
+ import("node:os"),
173
+ ]);
174
+ return { spawn: cp.spawn, fs, path, os };
175
+ }
176
+ catch {
177
+ return null;
178
+ }
179
+ }
180
+ /** Throw `OwnershipUnconfirmedError` before hitting the server if the
181
+ * caller has not confirmed they own the target. */
182
+ function validateOwnership(ownership) {
183
+ if (!ownership || ownership.confirmed !== true) {
184
+ throw new OwnershipUnconfirmedError();
185
+ }
186
+ const statement = ownership.statement?.trim();
187
+ if (!statement || statement.length < 4) {
188
+ throw new OwnershipUnconfirmedError("Set a truthful `ownership.statement` describing why you are authorised to test this target.");
189
+ }
190
+ }
191
+ /** Throw `InvalidTargetHostError` when `targetUrl` isn't covered by
192
+ * `allowedHosts`. Matches on host+port literals — this is not a
193
+ * wildcard matcher; the whitelist has to name the exact origin the
194
+ * caller wrote into `targetUrl`. */
195
+ function validateAllowedHosts(targetUrl, allowedHosts) {
196
+ if (!Array.isArray(allowedHosts) || allowedHosts.length === 0) {
197
+ throw new InvalidTargetHostError("Provide at least one entry in `allowedHosts` — the SDK will not run against a target without a scoped whitelist.");
198
+ }
199
+ let parsed;
200
+ try {
201
+ parsed = new URL(targetUrl);
202
+ }
203
+ catch {
204
+ throw new InvalidTargetHostError("targetUrl is not a parseable URL. Use `http://<host>:<port>` or `https://<host>`.");
205
+ }
206
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
207
+ throw new InvalidTargetHostError("Only http and https schemes are accepted for `targetUrl`.");
208
+ }
209
+ const originShape = parsed.port
210
+ ? `${parsed.hostname}:${parsed.port}`
211
+ : parsed.hostname;
212
+ if (!allowedHosts.includes(originShape) && !allowedHosts.includes(parsed.hostname)) {
213
+ throw new InvalidTargetHostError(`targetUrl origin \`${originShape}\` is not in allowedHosts. Include it verbatim and retry.`);
214
+ }
215
+ }
216
+ /** `HEAD` the target so we fail fast before spending credits on a
217
+ * Strix startup that will just crash. 3s hard budget. */
218
+ async function preflightTarget(targetUrl) {
219
+ const ctrl = new AbortController();
220
+ const timer = setTimeout(() => ctrl.abort(), 3000);
221
+ try {
222
+ const res = await fetch(targetUrl, { method: "HEAD", signal: ctrl.signal, redirect: "follow" });
223
+ if (!res.ok && res.status >= 500) {
224
+ throw new TargetUnreachableError(`Target responded with ${res.status}. Check the app is up and try again.`);
225
+ }
226
+ }
227
+ catch (err) {
228
+ if (err instanceof TargetUnreachableError)
229
+ throw err;
230
+ throw new TargetUnreachableError(`Could not reach ${targetUrl}. Start the target and retry (docker run bkimminich/juice-shop for the demo).`);
231
+ }
232
+ finally {
233
+ clearTimeout(timer);
234
+ }
235
+ }
236
+ /** Resolve the working directory for `strix_runs/<name>/` output.
237
+ * Defaults to `./strix_runs/` under the caller's CWD when
238
+ * `outputDir` is unset. */
239
+ async function resolveOutputDir(input, nodeApis) {
240
+ const dir = input.outputDir ?? nodeApis.path.join(process.cwd(), "strix_runs");
241
+ await nodeApis.fs.mkdir(dir, { recursive: true });
242
+ return dir;
243
+ }
244
+ /** Spawn the `strix` CLI, pipe stdio into log files under
245
+ * `outputDir/<runId>/`, and resolve to the typed run envelope on
246
+ * clean exit. Enforces `maxIterations`-derived wall-clock timeout
247
+ * (2 min per iteration). */
248
+ async function runStrix(input, cred, outputDir, nodeApis) {
249
+ const runDir = nodeApis.path.join(outputDir, cred.runId);
250
+ await nodeApis.fs.mkdir(runDir, { recursive: true });
251
+ const stdoutPath = nodeApis.path.join(runDir, "strix.stdout.log");
252
+ const stderrPath = nodeApis.path.join(runDir, "strix.stderr.log");
253
+ const env = {
254
+ ...process.env,
255
+ LLM_API_KEY: cred.scopedApiKey,
256
+ STRIX_LLM: `${cred.provider}/${cred.model}`,
257
+ ...(cred.scopedApiBase ? { LLM_API_BASE: cred.scopedApiBase } : {}),
258
+ STRIX_RUN_NAME: cred.runId,
259
+ STRIX_OUTPUT_DIR: runDir,
260
+ };
261
+ const args = [
262
+ "--target",
263
+ input.targetUrl,
264
+ "--scan-mode",
265
+ "standard",
266
+ "--non-interactive",
267
+ ];
268
+ const maxIterations = input.maxIterations ?? 40;
269
+ const timeoutMs = Math.min(maxIterations * 120_000, 4 * 60 * 60 * 1000);
270
+ return new Promise((resolve, reject) => {
271
+ let killed = false;
272
+ const child = nodeApis.spawn("strix", args, {
273
+ env,
274
+ cwd: outputDir,
275
+ stdio: ["ignore", "pipe", "pipe"],
276
+ });
277
+ // Pipe strix stdio into on-disk logs so the user can inspect them
278
+ // after the fact; we tail stderr into the crash message.
279
+ let stderrTail = "";
280
+ child.stdout?.on("data", async (chunk) => {
281
+ try {
282
+ await nodeApis.fs.appendFile(stdoutPath, chunk);
283
+ }
284
+ catch { /* best effort */ }
285
+ });
286
+ child.stderr?.on("data", async (chunk) => {
287
+ try {
288
+ await nodeApis.fs.appendFile(stderrPath, chunk);
289
+ }
290
+ catch { /* best effort */ }
291
+ stderrTail = (stderrTail + chunk.toString()).slice(-2048);
292
+ });
293
+ const timer = setTimeout(() => {
294
+ killed = true;
295
+ child.kill("SIGKILL");
296
+ }, timeoutMs);
297
+ child.on("error", (err) => {
298
+ clearTimeout(timer);
299
+ if (err.code === "ENOENT") {
300
+ reject(new SandboxMissingError("The `strix` CLI is not on PATH. Install with `pipx install strix-agent` and retry."));
301
+ return;
302
+ }
303
+ reject(new StrixCrashedError(err.message));
304
+ });
305
+ child.on("exit", async (code) => {
306
+ clearTimeout(timer);
307
+ if (killed) {
308
+ reject(new PentestTimeoutError());
309
+ return;
310
+ }
311
+ if (code !== 0) {
312
+ reject(new StrixCrashedError(`strix exited with code ${code}. Stderr tail:\n${stderrTail || "(empty)"}`));
313
+ return;
314
+ }
315
+ try {
316
+ const out = await hydrateOutput(cred, input, runDir, nodeApis);
317
+ resolve(out);
318
+ }
319
+ catch (err) {
320
+ reject(new StrixCrashedError(`strix finished but its output could not be parsed: ${err.message}`));
321
+ }
322
+ });
323
+ });
324
+ }
325
+ /** Read `<runDir>/report.json` (findings/pocs/patch) plus the
326
+ * self-contained `report.html` and pack them into the typed run
327
+ * envelope. Falls back to reading `findings.json` for older Strix
328
+ * versions that write per-artefact files. */
329
+ async function hydrateOutput(cred, input, runDir, nodeApis) {
330
+ const reportJson = await readJsonSafely(nodeApis.path.join(runDir, "report.json"), nodeApis);
331
+ const findings = reportJson?.findings ?? [];
332
+ const pocs = reportJson?.pocs ?? [];
333
+ const patch = reportJson?.patch ?? {
334
+ diff: "",
335
+ branchSuggestion: `pentest/${cred.runId}`,
336
+ };
337
+ const reportHtmlPath = nodeApis.path.join(runDir, "report.html");
338
+ if (!(await pathExists(reportHtmlPath, nodeApis))) {
339
+ // Compose a minimal HTML report from the JSON when Strix didn't
340
+ // emit one — deterministic, no-network fallback.
341
+ await nodeApis.fs.writeFile(reportHtmlPath, renderPentestReportHtml({
342
+ runId: cred.runId,
343
+ target: input.targetUrl,
344
+ findings,
345
+ pocs,
346
+ patch,
347
+ reportHtmlPath: "",
348
+ costCredits: cred.budgetCredits,
349
+ }));
350
+ }
351
+ return {
352
+ runId: cred.runId,
353
+ target: input.targetUrl,
354
+ findings,
355
+ pocs,
356
+ patch,
357
+ reportHtmlPath,
358
+ costCredits: cred.budgetCredits,
359
+ };
360
+ }
361
+ async function readJsonSafely(filePath, nodeApis) {
362
+ try {
363
+ const text = await nodeApis.fs.readFile(filePath, "utf-8");
364
+ return JSON.parse(text);
365
+ }
366
+ catch {
367
+ return null;
368
+ }
369
+ }
370
+ async function pathExists(filePath, nodeApis) {
371
+ try {
372
+ await nodeApis.fs.stat(filePath);
373
+ return true;
374
+ }
375
+ catch {
376
+ return false;
377
+ }
378
+ }
379
+ /** Backend errors land as `ClawvardError` from the HTTP client; we
380
+ * rewrap the ones whose `code` matches a `PentestErrorCode` into the
381
+ * matching subclass. Non-matching errors bubble up unchanged. */
382
+ async function rethrowAsPentest(p) {
383
+ try {
384
+ return await p;
385
+ }
386
+ catch (err) {
387
+ if (err instanceof PentestError)
388
+ throw err;
389
+ if (err instanceof ClawvardError) {
390
+ const code = err.code;
391
+ if (PENTEST_ERROR_CODES.includes(code)) {
392
+ throw mapPentestError(code, err.message);
393
+ }
394
+ }
395
+ if (err instanceof Error) {
396
+ const parsed = parsePentestCodeFromMessage(err.message);
397
+ if (parsed)
398
+ throw mapPentestError(parsed.code, parsed.message);
399
+ }
400
+ throw err;
401
+ }
402
+ }
403
+ /** Pull `{ code, message }` out of a `"<code>|<message>"` job-failure
404
+ * message. Mirrors the id-photo convention so a future job-runtime
405
+ * handler can surface typed failures via the same channel. */
406
+ export function parsePentestCodeFromMessage(msg) {
407
+ const pipeIdx = msg.indexOf("|");
408
+ if (pipeIdx <= 0)
409
+ return null;
410
+ const candidate = msg.slice(0, pipeIdx);
411
+ if (!PENTEST_ERROR_CODES.includes(candidate))
412
+ return null;
413
+ return {
414
+ code: candidate,
415
+ message: msg.slice(pipeIdx + 1),
416
+ };
417
+ }
418
+ /** Deterministic renderer — turns a `SecurityPentestRunOutput` into
419
+ * the three-panel HTML report the course showcase renders (findings
420
+ * card / PoC replay accordion / patch diff viewer). Exposed on the
421
+ * SDK so course pipelines don't have to re-derive the layout in user
422
+ * code. Emits a self-contained HTML document: inlined CSS, no
423
+ * external dependencies, deterministic node order, safe to
424
+ * `iframe`-embed. */
425
+ export function renderPentestReportHtml(out, options) {
426
+ const title = escapeHtml(options?.title ?? `Pen-Test Report · ${out.target}`);
427
+ const findings = out.findings.map(renderFindingCard).join("\n");
428
+ const pocs = out.pocs.map(renderPocCard).join("\n");
429
+ const patch = renderPatchCard(out.patch);
430
+ return [
431
+ `<!DOCTYPE html>`,
432
+ `<html lang="en">`,
433
+ `<head>`,
434
+ `<meta charset="utf-8"/>`,
435
+ `<meta name="viewport" content="width=device-width, initial-scale=1"/>`,
436
+ `<title>${title}</title>`,
437
+ `<style>${PENTEST_REPORT_CSS}</style>`,
438
+ `</head>`,
439
+ `<body>`,
440
+ `<main class="pt-report">`,
441
+ `<header><h1>${title}</h1><p class="meta">${out.findings.length} findings · ${out.pocs.length} PoCs · ${out.costCredits} credits</p></header>`,
442
+ `<section class="findings"><h2>Findings</h2>${findings}</section>`,
443
+ `<section class="pocs"><h2>Proof-of-concept replay</h2>${pocs}</section>`,
444
+ `<section class="patch"><h2>Remediation patch</h2>${patch}</section>`,
445
+ `</main>`,
446
+ `</body>`,
447
+ `</html>`,
448
+ ].join("\n");
449
+ }
450
+ function renderFindingCard(f) {
451
+ const badge = escapeHtml(f.cvss.severity);
452
+ const score = f.cvss.score.toFixed(1);
453
+ return [
454
+ `<article class="finding sev-${badge}">`,
455
+ `<header>`,
456
+ `<span class="badge">${badge.toUpperCase()} · CVSS ${escapeHtml(score)}</span>`,
457
+ `<h3>${escapeHtml(f.title)}</h3>`,
458
+ `<p class="cat">${escapeHtml(f.owaspCategory)} · <code>${escapeHtml(f.affectedEndpoint)}</code></p>`,
459
+ `</header>`,
460
+ `<p class="impact">${escapeHtml(f.impact)}</p>`,
461
+ `<p class="fix"><strong>Fix:</strong> ${escapeHtml(f.remediation)}</p>`,
462
+ `</article>`,
463
+ ].join("");
464
+ }
465
+ function renderPocCard(p) {
466
+ return [
467
+ `<details class="poc">`,
468
+ `<summary><code>${escapeHtml(p.findingId)}</code> · ${escapeHtml(p.kind)}</summary>`,
469
+ `<pre>${escapeHtml(p.body)}</pre>`,
470
+ `<p class="indicator"><strong>Look for:</strong> ${escapeHtml(p.expectedIndicator)}</p>`,
471
+ `</details>`,
472
+ ].join("");
473
+ }
474
+ function renderPatchCard(patch) {
475
+ const branch = escapeHtml(patch.branchSuggestion);
476
+ return [
477
+ `<p class="branch">Suggested branch: <code>${branch}</code></p>`,
478
+ `<pre class="diff">${escapeHtml(patch.diff)}</pre>`,
479
+ ].join("");
480
+ }
481
+ /** Minimal HTML escape — enough for user-supplied strings coming out
482
+ * of the pentest run. We escape `&`, `<`, `>`, `"`, `'`. */
483
+ function escapeHtml(s) {
484
+ return s
485
+ .replace(/&/g, "&amp;")
486
+ .replace(/</g, "&lt;")
487
+ .replace(/>/g, "&gt;")
488
+ .replace(/"/g, "&quot;")
489
+ .replace(/'/g, "&#39;");
490
+ }
491
+ const PENTEST_REPORT_CSS = `
492
+ :root { --fg: #0f172a; --muted: #64748b; --card: #ffffff; --edge: #e2e8f0; --crit: #b91c1c; --high: #c2410c; --med: #a16207; --low: #0369a1; }
493
+ body { margin: 0; font: 15px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif; color: var(--fg); background: #f8fafc; }
494
+ .pt-report { max-width: 960px; margin: 0 auto; padding: 32px 24px 64px; }
495
+ .pt-report > header h1 { font-size: 22px; margin: 0 0 4px; }
496
+ .pt-report .meta { color: var(--muted); margin: 0 0 24px; }
497
+ .pt-report section { margin-top: 28px; }
498
+ .pt-report section > h2 { font-size: 14px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 12px; }
499
+ .finding { background: var(--card); border: 1px solid var(--edge); border-radius: 12px; padding: 16px 18px; margin-bottom: 12px; }
500
+ .finding header { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
501
+ .finding .badge { font-size: 11px; padding: 3px 8px; border-radius: 999px; background: #f1f5f9; color: var(--fg); align-self: flex-start; font-weight: 600; }
502
+ .finding.sev-critical .badge { background: #fee2e2; color: var(--crit); }
503
+ .finding.sev-high .badge { background: #ffedd5; color: var(--high); }
504
+ .finding.sev-medium .badge { background: #fef3c7; color: var(--med); }
505
+ .finding.sev-low .badge { background: #e0f2fe; color: var(--low); }
506
+ .finding h3 { margin: 0; font-size: 16px; }
507
+ .finding .cat { margin: 0; color: var(--muted); font-size: 13px; }
508
+ .finding .cat code { background: #f1f5f9; padding: 2px 6px; border-radius: 6px; }
509
+ .finding .impact { margin: 6px 0 8px; }
510
+ .finding .fix { margin: 0; color: var(--muted); }
511
+ .poc { background: var(--card); border: 1px solid var(--edge); border-radius: 10px; padding: 10px 14px; margin-bottom: 10px; }
512
+ .poc summary { cursor: pointer; font-weight: 500; }
513
+ .poc pre { background: #0f172a; color: #e2e8f0; padding: 12px 14px; border-radius: 8px; overflow-x: auto; font: 13px/1.5 ui-monospace, SFMono-Regular, monospace; }
514
+ .poc .indicator { margin: 8px 0 0; color: var(--muted); font-size: 13px; }
515
+ .patch .branch { margin: 0 0 8px; color: var(--muted); }
516
+ .patch .branch code { background: #f1f5f9; padding: 2px 6px; border-radius: 6px; }
517
+ .patch pre.diff { background: #0f172a; color: #e2e8f0; padding: 14px 16px; border-radius: 10px; overflow-x: auto; font: 13px/1.55 ui-monospace, SFMono-Regular, monospace; }
518
+ `;
519
+ //# sourceMappingURL=pentest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pentest.js","sourceRoot":"","sources":["../src/pentest.ts"],"names":[],"mappings":"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"}