@pensar/apex 1.8.0 → 1.8.2-canary.fb75c486
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.
- package/README.md +11 -0
- package/build/agent-6dj1qm50.js +221 -0
- package/build/agent-6xr8vpgm.js +28 -0
- package/build/agent-x1htbpe3.js +22 -0
- package/build/apps-t0gmwc7z.js +446 -0
- package/build/{auth-dxjgy41e.js → auth-p4r1m7xq.js} +50 -13
- package/build/authentication-je2b0c3w.js +22 -0
- package/build/blackboxAgent-a4jnt0y5.js +22 -0
- package/build/{blackboxPentest-8ps4yvbk.js → blackboxPentest-b5741n3h.js} +19 -17
- package/build/{cli-y61d9433.js → cli-0tnv1vkp.js} +138 -38
- package/build/{cli-jg7r7y5n.js → cli-4xb21y6g.js} +30 -2
- package/build/{cli-k0tckznm.js → cli-6p7d2k55.js} +39701 -31695
- package/build/cli-87zakjb2.js +17 -0
- package/build/{authentication-e30mfzbe.js → cli-8frjr68r.js} +11 -18
- package/build/cli-8xknm7d9.js +204 -0
- package/build/cli-9egg9azd.js +22 -0
- package/build/cli-9fsre5pt.js +0 -0
- package/build/cli-abbka8n3.js +501 -0
- package/build/{cli-3y0dgy56.js → cli-c8131c4q.js} +2 -2
- package/build/cli-e08r86zk.js +24 -0
- package/build/{cli-0ghkg3w6.js → cli-e6rgwtpb.js} +19950 -18556
- package/build/cli-g5h24ny8.js +197 -0
- package/build/{cli-nr1cjfr9.js → cli-gtcd5c3f.js} +26 -7
- package/build/cli-k0730f59.js +52 -0
- package/build/{cli-tp1tqn3k.js → cli-mswm4k81.js} +1 -1
- package/build/{cli-m788e4f3.js → cli-q8dfq25x.js} +584 -33
- package/build/cli-rhry8mat.js +7213 -0
- package/build/{cli-g8t710ew.js → cli-ryy39d77.js} +253 -250
- package/build/cli-s1nckt4k.js +20 -0
- package/build/{cli-k4hrygff.js → cli-v9ds4jb8.js} +9 -5
- package/build/{cli-dqt80sw3.js → cli-w5990vr6.js} +199 -68
- package/build/{cli-3w2syxpv.js → cli-wfmdch3r.js} +102695 -104816
- package/build/cli.js +351 -280
- package/build/config-3bvtf3j8.js +188 -0
- package/build/{doctor-8tva8j99.js → doctor-2bkpddws.js} +1 -1
- package/build/{fixes-q5bhgxhc.js → fixes-60k3ts71.js} +23 -4
- package/build/{index-pfee23kv.js → index-0gp3x2r8.js} +19306 -18954
- package/build/index-861hkebg.js +12 -0
- package/build/{index-y5xpp21a.js → index-acc00eq4.js} +77 -108
- package/build/index-acdgrqa0.js +36 -0
- package/build/{index-e898mdyh.js → index-cfberehw.js} +4 -2
- package/build/{index-wfeb2gcc.js → index-hxn4rk8f.js} +9 -11
- package/build/{index-dw1xbhfn.js → index-vc29b21w.js} +161 -26
- package/build/index-vwt27stc.js +184 -0
- package/build/{issues-qbmdneej.js → issues-1bynat5q.js} +33 -9
- package/build/{logs-xm5vbymy.js → logs-e78vx2dy.js} +23 -4
- package/build/{main-3d7dfdvs.js → main-3zneyg7p.js} +93 -17
- package/build/{offesecAgent-re6kt2ff.js → offesecAgent-w9m0svwk.js} +14 -11
- package/build/parse-15kqmy2v.js +207 -0
- package/build/pentest-gpvqpvmd.js +31 -0
- package/build/{pentests-e3rj5845.js → pentests-nq7wa8yb.js} +36 -17
- package/build/{targetedPentest-fs0v570s.js → targetedPentest-fjxqn089.js} +15 -12
- package/build/threatModel-9yqx7d7x.js +29 -0
- package/build/{uninstall-qb2xbh2t.js → uninstall-9zbf4cwc.js} +6 -4
- package/build/{utils-jf52rmrb.js → utils-dh1t2r1e.js} +13 -10
- package/package.json +86 -88
- package/build/agent-4d8j2jsw.js +0 -278
- package/build/agent-z2s6h7n2.js +0 -19
- package/build/blackboxAgent-j9pczwym.js +0 -19
- package/build/cli-03z6pswp.js +0 -1423
- package/build/cli-0fy9j5dw.js +0 -61
- package/build/cli-asyas1xb.js +0 -110
- package/build/cli-dj1dgw2n.js +0 -190
- package/build/cli-q7r2sth7.js +0 -103
- package/build/cli-vkwch0bc.js +0 -1207
- package/build/cli-wr7g9qcr.js +0 -645
- package/build/index-bz6f8jry.js +0 -32
- package/build/pentest-mfm4hake.js +0 -29
- package/build/projects-qk22qcbt.js +0 -35
- package/build/threatModel-xfvc6cch.js +0 -67
package/build/cli-wr7g9qcr.js
DELETED
|
@@ -1,645 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CweEntrySchema,
|
|
3
|
-
ValidatedCweEntrySchema,
|
|
4
|
-
hasCanonicalName
|
|
5
|
-
} from "./cli-3w2syxpv.js";
|
|
6
|
-
import {
|
|
7
|
-
exports_external1 as exports_external,
|
|
8
|
-
init_zod
|
|
9
|
-
} from "./cli-0ghkg3w6.js";
|
|
10
|
-
|
|
11
|
-
// src/core/report/schemas.ts
|
|
12
|
-
init_zod();
|
|
13
|
-
|
|
14
|
-
// src/lib/evidence/types.ts
|
|
15
|
-
init_zod();
|
|
16
|
-
var EvidenceFileEntrySchema = exports_external.object({
|
|
17
|
-
path: exports_external.string(),
|
|
18
|
-
type: exports_external.enum(["http-response", "screenshot", "poc-output", "raw-evidence"]),
|
|
19
|
-
description: exports_external.string()
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// src/core/report/schemas.ts
|
|
23
|
-
var PentestReportFindingSchema = exports_external.object({
|
|
24
|
-
title: exports_external.string(),
|
|
25
|
-
severity: exports_external.enum(["CRITICAL", "HIGH", "MEDIUM", "LOW"]),
|
|
26
|
-
description: exports_external.string(),
|
|
27
|
-
impact: exports_external.string(),
|
|
28
|
-
evidence: exports_external.string(),
|
|
29
|
-
endpoint: exports_external.string(),
|
|
30
|
-
pocPath: exports_external.string(),
|
|
31
|
-
remediation: exports_external.string(),
|
|
32
|
-
references: exports_external.string().optional(),
|
|
33
|
-
cwes: exports_external.array(ValidatedCweEntrySchema.or(CweEntrySchema)).optional(),
|
|
34
|
-
rootCauseGroup: exports_external.string().optional(),
|
|
35
|
-
relatedFindings: exports_external.array(exports_external.string()).optional(),
|
|
36
|
-
evidenceFiles: exports_external.array(EvidenceFileEntrySchema).optional()
|
|
37
|
-
});
|
|
38
|
-
var PentestReportSchema = exports_external.object({
|
|
39
|
-
version: exports_external.string().regex(/^1\.\d+$/),
|
|
40
|
-
metadata: exports_external.object({
|
|
41
|
-
target: exports_external.string(),
|
|
42
|
-
model: exports_external.string(),
|
|
43
|
-
timestamp: exports_external.string(),
|
|
44
|
-
sessionId: exports_external.string(),
|
|
45
|
-
mode: exports_external.enum(["blackbox", "whitebox", "targeted"])
|
|
46
|
-
}),
|
|
47
|
-
summary: exports_external.object({
|
|
48
|
-
totalFindings: exports_external.number(),
|
|
49
|
-
bySeverity: exports_external.object({
|
|
50
|
-
CRITICAL: exports_external.number(),
|
|
51
|
-
HIGH: exports_external.number(),
|
|
52
|
-
MEDIUM: exports_external.number(),
|
|
53
|
-
LOW: exports_external.number()
|
|
54
|
-
})
|
|
55
|
-
}),
|
|
56
|
-
findings: exports_external.array(PentestReportFindingSchema)
|
|
57
|
-
});
|
|
58
|
-
var REPORT_VERSION = "1.0";
|
|
59
|
-
|
|
60
|
-
// src/core/report/builder.ts
|
|
61
|
-
var SEVERITY_ORDER = ["CRITICAL", "HIGH", "MEDIUM", "LOW"];
|
|
62
|
-
function buildPentestReport(findings, context) {
|
|
63
|
-
const sorted = [...findings].sort((a, b) => SEVERITY_ORDER.indexOf(a.severity) - SEVERITY_ORDER.indexOf(b.severity));
|
|
64
|
-
const bySeverity = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
|
|
65
|
-
for (const f of findings) {
|
|
66
|
-
bySeverity[f.severity]++;
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
version: REPORT_VERSION,
|
|
70
|
-
metadata: {
|
|
71
|
-
target: context.target,
|
|
72
|
-
model: context.model,
|
|
73
|
-
timestamp: new Date().toISOString(),
|
|
74
|
-
sessionId: context.sessionId,
|
|
75
|
-
mode: context.mode
|
|
76
|
-
},
|
|
77
|
-
summary: {
|
|
78
|
-
totalFindings: findings.length,
|
|
79
|
-
bySeverity
|
|
80
|
-
},
|
|
81
|
-
findings: sorted.map((f) => ({
|
|
82
|
-
title: f.title,
|
|
83
|
-
severity: f.severity,
|
|
84
|
-
description: f.description,
|
|
85
|
-
impact: f.impact,
|
|
86
|
-
evidence: f.evidence,
|
|
87
|
-
endpoint: f.endpoint,
|
|
88
|
-
pocPath: f.pocPath,
|
|
89
|
-
remediation: f.remediation,
|
|
90
|
-
references: f.references,
|
|
91
|
-
cwes: f.cwes,
|
|
92
|
-
rootCauseGroup: f.rootCauseGroup,
|
|
93
|
-
relatedFindings: f.relatedFindings,
|
|
94
|
-
evidenceFiles: f.evidenceFiles
|
|
95
|
-
}))
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// src/core/report/renderers/markdown.ts
|
|
100
|
-
function renderMarkdown(report) {
|
|
101
|
-
const { metadata, findings, summary } = report;
|
|
102
|
-
const header = [
|
|
103
|
-
`# Pentest Report — ${metadata.target}`,
|
|
104
|
-
"",
|
|
105
|
-
`**Date:** ${metadata.timestamp} `,
|
|
106
|
-
`**Session:** ${metadata.sessionId} `,
|
|
107
|
-
`**Model:** ${metadata.model} `,
|
|
108
|
-
`**Mode:** ${metadata.mode}`,
|
|
109
|
-
"",
|
|
110
|
-
`**Findings:** ${summary.totalFindings}`,
|
|
111
|
-
""
|
|
112
|
-
];
|
|
113
|
-
if (findings.length === 0) {
|
|
114
|
-
return [
|
|
115
|
-
...header,
|
|
116
|
-
"No findings were identified during this assessment.",
|
|
117
|
-
""
|
|
118
|
-
].join(`
|
|
119
|
-
`);
|
|
120
|
-
}
|
|
121
|
-
const body = findings.map((finding) => renderFinding(finding, metadata)).join(`
|
|
122
|
-
`);
|
|
123
|
-
return [...header, body].join(`
|
|
124
|
-
`);
|
|
125
|
-
}
|
|
126
|
-
function renderFinding(finding, metadata) {
|
|
127
|
-
const lines = [
|
|
128
|
-
`# ${finding.title}`,
|
|
129
|
-
"",
|
|
130
|
-
`**Severity:** ${finding.severity} `,
|
|
131
|
-
`**Target:** ${metadata.target} `,
|
|
132
|
-
`**Endpoint:** ${finding.endpoint} `,
|
|
133
|
-
`**Date:** ${metadata.timestamp} `,
|
|
134
|
-
`**Session:** ${metadata.sessionId}`,
|
|
135
|
-
"",
|
|
136
|
-
"## Description",
|
|
137
|
-
"",
|
|
138
|
-
finding.description,
|
|
139
|
-
"",
|
|
140
|
-
"## Impact",
|
|
141
|
-
"",
|
|
142
|
-
finding.impact,
|
|
143
|
-
"",
|
|
144
|
-
"## Evidence",
|
|
145
|
-
"",
|
|
146
|
-
"```",
|
|
147
|
-
finding.evidence,
|
|
148
|
-
"```",
|
|
149
|
-
"",
|
|
150
|
-
...finding.evidenceFiles?.length ? [
|
|
151
|
-
"## Evidence Files",
|
|
152
|
-
"",
|
|
153
|
-
...finding.evidenceFiles.map((ef) => `- **[${ef.type}]** \`${ef.path}\` — ${ef.description}`),
|
|
154
|
-
""
|
|
155
|
-
] : [],
|
|
156
|
-
...finding.cwes?.length ? [
|
|
157
|
-
"## CWE Classification",
|
|
158
|
-
"",
|
|
159
|
-
...finding.cwes.map((cwe) => `- **${cwe.id}**${hasCanonicalName(cwe) ? `: ${cwe.name}` : ""} — ${cwe.reasoning}`),
|
|
160
|
-
""
|
|
161
|
-
] : [],
|
|
162
|
-
...finding.rootCauseGroup ? [
|
|
163
|
-
"## Root Cause Group",
|
|
164
|
-
"",
|
|
165
|
-
`**Group:** \`${finding.rootCauseGroup}\``,
|
|
166
|
-
...finding.relatedFindings?.length ? [
|
|
167
|
-
"",
|
|
168
|
-
"**Related Findings:**",
|
|
169
|
-
...finding.relatedFindings.map((rf) => `- ${rf}`)
|
|
170
|
-
] : [],
|
|
171
|
-
""
|
|
172
|
-
] : [],
|
|
173
|
-
"## POC",
|
|
174
|
-
"",
|
|
175
|
-
`Path: \`${finding.pocPath}\``,
|
|
176
|
-
"",
|
|
177
|
-
"## Remediation",
|
|
178
|
-
"",
|
|
179
|
-
finding.remediation,
|
|
180
|
-
...finding.references ? ["", `## References`, "", finding.references] : [],
|
|
181
|
-
"",
|
|
182
|
-
"---",
|
|
183
|
-
"",
|
|
184
|
-
"*This finding was automatically documented by the Pensar penetration testing agent.*",
|
|
185
|
-
""
|
|
186
|
-
];
|
|
187
|
-
return lines.join(`
|
|
188
|
-
`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// src/core/report/renderers/json.ts
|
|
192
|
-
function renderJson(report) {
|
|
193
|
-
return JSON.stringify(report, null, 2);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// src/core/report/index.ts
|
|
197
|
-
var REPORT_FILENAME_MD = "pentest-report.md";
|
|
198
|
-
var REPORT_FILENAME_JSON = "pentest-report.json";
|
|
199
|
-
|
|
200
|
-
// src/core/session/persistence.ts
|
|
201
|
-
import {
|
|
202
|
-
existsSync,
|
|
203
|
-
mkdirSync,
|
|
204
|
-
writeFileSync,
|
|
205
|
-
readFileSync,
|
|
206
|
-
readdirSync,
|
|
207
|
-
statSync
|
|
208
|
-
} from "fs";
|
|
209
|
-
import { join } from "path";
|
|
210
|
-
var SUBAGENTS_DIR = "subagents";
|
|
211
|
-
var MANIFEST_FILE = "agent-manifest.json";
|
|
212
|
-
function loadSubagentMessages(session, agentName) {
|
|
213
|
-
const stepPath = join(session.rootPath, SUBAGENTS_DIR, agentName, "messages.json");
|
|
214
|
-
if (existsSync(stepPath)) {
|
|
215
|
-
try {
|
|
216
|
-
return JSON.parse(readFileSync(stepPath, "utf-8"));
|
|
217
|
-
} catch {}
|
|
218
|
-
}
|
|
219
|
-
const snapshotPath = join(session.rootPath, SUBAGENTS_DIR, `${agentName}.json`);
|
|
220
|
-
if (!existsSync(snapshotPath))
|
|
221
|
-
return [];
|
|
222
|
-
try {
|
|
223
|
-
const data = JSON.parse(readFileSync(snapshotPath, "utf-8"));
|
|
224
|
-
return data.messages ?? [];
|
|
225
|
-
} catch {
|
|
226
|
-
return [];
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function saveSubagentData(session, data) {
|
|
230
|
-
const subagentsDir = join(session.rootPath, SUBAGENTS_DIR);
|
|
231
|
-
mkdirSync(subagentsDir, { recursive: true });
|
|
232
|
-
let toolCallCount = 0;
|
|
233
|
-
let stepCount = 0;
|
|
234
|
-
for (const msg of data.messages) {
|
|
235
|
-
if (msg.role === "assistant") {
|
|
236
|
-
stepCount++;
|
|
237
|
-
if (Array.isArray(msg.content)) {
|
|
238
|
-
for (const part of msg.content) {
|
|
239
|
-
if (part.type === "tool-call")
|
|
240
|
-
toolCallCount++;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const savedData = {
|
|
246
|
-
agentName: data.agentName,
|
|
247
|
-
timestamp: new Date().toISOString(),
|
|
248
|
-
target: data.target,
|
|
249
|
-
objective: data.objective,
|
|
250
|
-
vulnerabilityClass: data.vulnerabilityClass,
|
|
251
|
-
toolCallCount,
|
|
252
|
-
stepCount,
|
|
253
|
-
findingsCount: data.findingsCount ?? 0,
|
|
254
|
-
status: data.status,
|
|
255
|
-
error: data.error,
|
|
256
|
-
messages: data.messages,
|
|
257
|
-
systemPrompt: data.systemPrompt,
|
|
258
|
-
userPrompt: data.userPrompt
|
|
259
|
-
};
|
|
260
|
-
writeFileSync(join(subagentsDir, `${data.agentName}.json`), JSON.stringify(savedData, null, 2));
|
|
261
|
-
}
|
|
262
|
-
function writeAgentManifest(session, entries) {
|
|
263
|
-
const manifestPath = join(session.rootPath, MANIFEST_FILE);
|
|
264
|
-
writeFileSync(manifestPath, JSON.stringify(entries, null, 2));
|
|
265
|
-
}
|
|
266
|
-
function readAgentManifest(session) {
|
|
267
|
-
const manifestPath = join(session.rootPath, MANIFEST_FILE);
|
|
268
|
-
if (!existsSync(manifestPath))
|
|
269
|
-
return [];
|
|
270
|
-
try {
|
|
271
|
-
return JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
272
|
-
} catch {
|
|
273
|
-
return [];
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function buildManifestEntries(targets) {
|
|
277
|
-
return targets.map((t, i) => ({
|
|
278
|
-
id: `pentest-agent-${i + 1}`,
|
|
279
|
-
name: `Pentest Agent ${i + 1}`,
|
|
280
|
-
target: t.target,
|
|
281
|
-
vulnerabilityClass: t.objectives[0] || "general",
|
|
282
|
-
objective: t.objectives.join("; "),
|
|
283
|
-
status: "running",
|
|
284
|
-
spawnedAt: new Date().toISOString()
|
|
285
|
-
}));
|
|
286
|
-
}
|
|
287
|
-
function finalizeManifest(session, entries, results) {
|
|
288
|
-
const finalManifest = entries.map((entry, i) => {
|
|
289
|
-
if (entry.status === "completed")
|
|
290
|
-
return entry;
|
|
291
|
-
return {
|
|
292
|
-
...entry,
|
|
293
|
-
status: results[i] != null ? "completed" : "failed",
|
|
294
|
-
completedAt: new Date().toISOString()
|
|
295
|
-
};
|
|
296
|
-
});
|
|
297
|
-
writeAgentManifest(session, finalManifest);
|
|
298
|
-
}
|
|
299
|
-
function updateManifestEntryStatus(session, agentId, status) {
|
|
300
|
-
const manifest = readAgentManifest(session);
|
|
301
|
-
const updated = manifest.map((e) => e.id === agentId ? { ...e, status, completedAt: new Date().toISOString() } : e);
|
|
302
|
-
writeAgentManifest(session, updated);
|
|
303
|
-
}
|
|
304
|
-
function getCompletedAgentIds(session) {
|
|
305
|
-
const manifest = readAgentManifest(session);
|
|
306
|
-
return new Set(manifest.filter((e) => e.id.startsWith("pentest-agent-") && e.status === "completed").map((e) => e.id));
|
|
307
|
-
}
|
|
308
|
-
function parseSubagentFilename(filename) {
|
|
309
|
-
if (filename.startsWith("attack-surface-agent")) {
|
|
310
|
-
return { agentType: "attack-surface", name: "Attack Surface Discovery" };
|
|
311
|
-
}
|
|
312
|
-
if (filename === "whitebox-apps-discovery") {
|
|
313
|
-
return { agentType: "pentest", name: "Whitebox Apps Discovery" };
|
|
314
|
-
}
|
|
315
|
-
if (filename === "whitebox-incremental") {
|
|
316
|
-
return { agentType: "pentest", name: "Incremental Recon" };
|
|
317
|
-
}
|
|
318
|
-
if (filename.startsWith("pages-")) {
|
|
319
|
-
const appName = filename.replace("pages-", "");
|
|
320
|
-
return { agentType: "pentest", name: `Pages: ${appName}` };
|
|
321
|
-
}
|
|
322
|
-
if (filename.startsWith("apiEndpoints-")) {
|
|
323
|
-
const appName = filename.replace("apiEndpoints-", "");
|
|
324
|
-
return { agentType: "pentest", name: `API Endpoints: ${appName}` };
|
|
325
|
-
}
|
|
326
|
-
if (filename.startsWith("cloudResourceEndpoints-")) {
|
|
327
|
-
const appName = filename.replace("cloudResourceEndpoints-", "");
|
|
328
|
-
return { agentType: "pentest", name: `Cloud Resources: ${appName}` };
|
|
329
|
-
}
|
|
330
|
-
if (filename.startsWith("threat-model-")) {
|
|
331
|
-
const rest = filename.replace("threat-model-", "");
|
|
332
|
-
return { agentType: "pentest", name: `Threat Model: ${rest}` };
|
|
333
|
-
}
|
|
334
|
-
const pentestMatch = filename.match(/^pentest-agent-(\d+)/);
|
|
335
|
-
if (pentestMatch) {
|
|
336
|
-
return {
|
|
337
|
-
agentType: "pentest",
|
|
338
|
-
name: `Pentest Agent ${pentestMatch[1]}`
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
const codingMatch = filename.match(/^coding-agent-(\d+)/);
|
|
342
|
-
if (codingMatch) {
|
|
343
|
-
return {
|
|
344
|
-
agentType: "pentest",
|
|
345
|
-
name: `Coding Agent ${codingMatch[1]}`
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
if (filename === "auth-agent") {
|
|
349
|
-
return { agentType: "pentest", name: "Auth Agent" };
|
|
350
|
-
}
|
|
351
|
-
if (filename.startsWith("vuln-test-")) {
|
|
352
|
-
const parts = filename.replace("vuln-test-", "").split("-");
|
|
353
|
-
const vulnClass = parts[0] || "generic";
|
|
354
|
-
const vulnClassFormatted = vulnClass.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
355
|
-
return {
|
|
356
|
-
agentType: "pentest",
|
|
357
|
-
name: `${vulnClassFormatted} Test`
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
if (filename.startsWith("orchestrator-")) {
|
|
361
|
-
return { agentType: "pentest", name: "Orchestrator Summary" };
|
|
362
|
-
}
|
|
363
|
-
return { agentType: "pentest", name: filename.split("-")[0] || "Unknown" };
|
|
364
|
-
}
|
|
365
|
-
function unwrapAiSdkToolOutput(output) {
|
|
366
|
-
if (output === null || typeof output !== "object")
|
|
367
|
-
return output;
|
|
368
|
-
const o = output;
|
|
369
|
-
switch (o.type) {
|
|
370
|
-
case "json":
|
|
371
|
-
case "error-json":
|
|
372
|
-
if ("value" in o)
|
|
373
|
-
return o.value;
|
|
374
|
-
break;
|
|
375
|
-
case "text":
|
|
376
|
-
case "error-text":
|
|
377
|
-
if (typeof o.value === "string")
|
|
378
|
-
return o.value;
|
|
379
|
-
break;
|
|
380
|
-
case "execution-denied":
|
|
381
|
-
return o.reason ?? "Tool execution denied";
|
|
382
|
-
}
|
|
383
|
-
return output;
|
|
384
|
-
}
|
|
385
|
-
function convertMessagesToUI(messages, baseTime) {
|
|
386
|
-
const uiMessages = [];
|
|
387
|
-
let messageIndex = 0;
|
|
388
|
-
const toolResults = new Map;
|
|
389
|
-
for (const msg of messages) {
|
|
390
|
-
if (Array.isArray(msg.content)) {
|
|
391
|
-
for (const part of msg.content) {
|
|
392
|
-
if (part.type === "tool-result" && part.toolCallId) {
|
|
393
|
-
toolResults.set(part.toolCallId, unwrapAiSdkToolOutput(part.output));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
for (const msg of messages) {
|
|
399
|
-
const createdAt = new Date(baseTime.getTime() + messageIndex * 1000);
|
|
400
|
-
messageIndex++;
|
|
401
|
-
if (typeof msg.content === "string") {
|
|
402
|
-
uiMessages.push({
|
|
403
|
-
role: msg.role,
|
|
404
|
-
content: msg.content,
|
|
405
|
-
createdAt
|
|
406
|
-
});
|
|
407
|
-
} else if (Array.isArray(msg.content)) {
|
|
408
|
-
for (const part of msg.content) {
|
|
409
|
-
if (part.type === "text" && part.text) {
|
|
410
|
-
uiMessages.push({
|
|
411
|
-
role: "assistant",
|
|
412
|
-
content: part.text,
|
|
413
|
-
createdAt
|
|
414
|
-
});
|
|
415
|
-
} else if (part.type === "tool-call") {
|
|
416
|
-
const input = part.input;
|
|
417
|
-
const toolDescription = typeof input?.toolCallDescription === "string" ? input.toolCallDescription : part.toolName || "tool";
|
|
418
|
-
const hasResult = part.toolCallId ? toolResults.has(part.toolCallId) : false;
|
|
419
|
-
const result = part.toolCallId ? toolResults.get(part.toolCallId) : undefined;
|
|
420
|
-
const resultText = typeof result === "string" ? result : result != null && typeof result === "object" && ("value" in result) && typeof result.value === "string" ? result.value : undefined;
|
|
421
|
-
const cancelled = typeof resultText === "string" && resultText.toLowerCase().includes("cancelled");
|
|
422
|
-
const interrupted = !hasResult;
|
|
423
|
-
uiMessages.push({
|
|
424
|
-
role: "tool",
|
|
425
|
-
content: toolDescription,
|
|
426
|
-
createdAt,
|
|
427
|
-
toolCallId: part.toolCallId,
|
|
428
|
-
toolName: part.toolName,
|
|
429
|
-
args: input,
|
|
430
|
-
result: interrupted ? "Interrupted" : result,
|
|
431
|
-
status: cancelled || interrupted ? "error" : "completed"
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
return uiMessages;
|
|
438
|
-
}
|
|
439
|
-
function convertModelMessagesToUI(messages) {
|
|
440
|
-
return convertMessagesToUI(messages, new Date);
|
|
441
|
-
}
|
|
442
|
-
function loadSubagents(rootPath) {
|
|
443
|
-
const subagentsPath = join(rootPath, SUBAGENTS_DIR);
|
|
444
|
-
const subagents = [];
|
|
445
|
-
const agentNameIndex = new Map;
|
|
446
|
-
if (existsSync(subagentsPath)) {
|
|
447
|
-
const files = readdirSync(subagentsPath).filter((f) => f.endsWith(".json"));
|
|
448
|
-
files.sort();
|
|
449
|
-
for (const file of files) {
|
|
450
|
-
if (file.startsWith("orchestrator-"))
|
|
451
|
-
continue;
|
|
452
|
-
try {
|
|
453
|
-
const filePath = join(subagentsPath, file);
|
|
454
|
-
const data = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
455
|
-
const { agentType, name } = parseSubagentFilename(file);
|
|
456
|
-
const timestamp = new Date(data.timestamp);
|
|
457
|
-
const agentName = data.agentName;
|
|
458
|
-
const stepPath = join(subagentsPath, agentName, "messages.json");
|
|
459
|
-
let messages;
|
|
460
|
-
if (existsSync(stepPath)) {
|
|
461
|
-
try {
|
|
462
|
-
const raw = JSON.parse(readFileSync(stepPath, "utf-8"));
|
|
463
|
-
messages = convertMessagesToUI(raw, timestamp);
|
|
464
|
-
} catch {
|
|
465
|
-
messages = convertMessagesToUI(data.messages ?? [], timestamp);
|
|
466
|
-
}
|
|
467
|
-
} else {
|
|
468
|
-
messages = convertMessagesToUI(data.messages ?? [], timestamp);
|
|
469
|
-
}
|
|
470
|
-
let status = "completed";
|
|
471
|
-
switch (data.status) {
|
|
472
|
-
case "canceled":
|
|
473
|
-
case "failed":
|
|
474
|
-
case "completed":
|
|
475
|
-
case "pending":
|
|
476
|
-
status = data.status;
|
|
477
|
-
break;
|
|
478
|
-
default:
|
|
479
|
-
if (typeof data.findingsCount === "number" && data.findingsCount < 0) {
|
|
480
|
-
status = "failed";
|
|
481
|
-
}
|
|
482
|
-
break;
|
|
483
|
-
}
|
|
484
|
-
agentNameIndex.set(data.agentName, subagents.length);
|
|
485
|
-
subagents.push({
|
|
486
|
-
id: data.agentName,
|
|
487
|
-
name: data.agentName === "attack-surface-agent" ? "Attack Surface Discovery" : name,
|
|
488
|
-
type: agentType,
|
|
489
|
-
target: data.target || "Unknown",
|
|
490
|
-
messages,
|
|
491
|
-
createdAt: timestamp,
|
|
492
|
-
status
|
|
493
|
-
});
|
|
494
|
-
} catch (e) {
|
|
495
|
-
console.error(`Failed to load subagent file ${file}:`, e);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
const entries = readdirSync(subagentsPath, { withFileTypes: true });
|
|
499
|
-
for (const dirent of entries) {
|
|
500
|
-
if (!dirent.isDirectory())
|
|
501
|
-
continue;
|
|
502
|
-
const entry = dirent.name;
|
|
503
|
-
if (agentNameIndex.has(entry))
|
|
504
|
-
continue;
|
|
505
|
-
if (entry.endsWith("-tasks") || entry.endsWith("-plan"))
|
|
506
|
-
continue;
|
|
507
|
-
const messagesPath = join(subagentsPath, entry, "messages.json");
|
|
508
|
-
try {
|
|
509
|
-
const raw = JSON.parse(readFileSync(messagesPath, "utf-8"));
|
|
510
|
-
if (!Array.isArray(raw) || raw.length === 0)
|
|
511
|
-
continue;
|
|
512
|
-
const { agentType, name } = parseSubagentFilename(entry);
|
|
513
|
-
const timestamp = statSync(messagesPath).mtime;
|
|
514
|
-
const messages = convertMessagesToUI(raw, timestamp);
|
|
515
|
-
agentNameIndex.set(entry, subagents.length);
|
|
516
|
-
subagents.push({
|
|
517
|
-
id: entry,
|
|
518
|
-
name,
|
|
519
|
-
type: agentType,
|
|
520
|
-
target: "Unknown",
|
|
521
|
-
messages,
|
|
522
|
-
createdAt: timestamp,
|
|
523
|
-
status: "completed"
|
|
524
|
-
});
|
|
525
|
-
} catch {}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
const manifestPath = join(rootPath, MANIFEST_FILE);
|
|
529
|
-
if (existsSync(manifestPath)) {
|
|
530
|
-
try {
|
|
531
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
532
|
-
for (const entry of manifest) {
|
|
533
|
-
if (entry.status !== "running")
|
|
534
|
-
continue;
|
|
535
|
-
const resumeInfo = {
|
|
536
|
-
target: entry.target,
|
|
537
|
-
objective: entry.objective,
|
|
538
|
-
vulnerabilityClass: entry.vulnerabilityClass,
|
|
539
|
-
authenticationInfo: entry.authInfo
|
|
540
|
-
};
|
|
541
|
-
const existingIndex = agentNameIndex.get(entry.id);
|
|
542
|
-
if (existingIndex !== undefined) {
|
|
543
|
-
subagents[existingIndex] = {
|
|
544
|
-
...subagents[existingIndex],
|
|
545
|
-
status: "paused",
|
|
546
|
-
resumeInfo
|
|
547
|
-
};
|
|
548
|
-
} else {
|
|
549
|
-
subagents.push({
|
|
550
|
-
id: entry.id,
|
|
551
|
-
name: entry.name,
|
|
552
|
-
type: "pentest",
|
|
553
|
-
target: entry.target,
|
|
554
|
-
messages: [],
|
|
555
|
-
createdAt: new Date(entry.spawnedAt),
|
|
556
|
-
status: "paused",
|
|
557
|
-
resumeInfo
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
} catch (e) {
|
|
562
|
-
console.error("Failed to load agent manifest:", e);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
return subagents;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// src/core/session/execution-metrics.ts
|
|
569
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
570
|
-
import { join as join2 } from "path";
|
|
571
|
-
var EXECUTION_METRICS_FILENAME = "execution-metrics.json";
|
|
572
|
-
function toNonNegativeInteger(value) {
|
|
573
|
-
const n = Number(value);
|
|
574
|
-
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
|
575
|
-
}
|
|
576
|
-
function normalizeTokenUsage(value) {
|
|
577
|
-
const inputTokens = toNonNegativeInteger(value?.inputTokens);
|
|
578
|
-
const outputTokens = toNonNegativeInteger(value?.outputTokens);
|
|
579
|
-
const derivedTotal = inputTokens + outputTokens;
|
|
580
|
-
const explicitTotal = toNonNegativeInteger(value?.totalTokens);
|
|
581
|
-
return {
|
|
582
|
-
inputTokens,
|
|
583
|
-
outputTokens,
|
|
584
|
-
totalTokens: explicitTotal > 0 ? explicitTotal : derivedTotal
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
function metricsPath(sessionRootPath) {
|
|
588
|
-
return join2(sessionRootPath, EXECUTION_METRICS_FILENAME);
|
|
589
|
-
}
|
|
590
|
-
function sessionJsonPath(sessionRootPath) {
|
|
591
|
-
return join2(sessionRootPath, "session.json");
|
|
592
|
-
}
|
|
593
|
-
function readExecutionMetrics(sessionRootPath) {
|
|
594
|
-
const path = metricsPath(sessionRootPath);
|
|
595
|
-
if (!existsSync2(path))
|
|
596
|
-
return null;
|
|
597
|
-
try {
|
|
598
|
-
const parsed = JSON.parse(readFileSync2(path, "utf-8"));
|
|
599
|
-
return {
|
|
600
|
-
tokenUsage: normalizeTokenUsage(parsed.tokenUsage),
|
|
601
|
-
runtime: typeof parsed.runtime === "string" ? parsed.runtime : undefined,
|
|
602
|
-
elapsedSeconds: toNonNegativeInteger(parsed.elapsedSeconds) || undefined,
|
|
603
|
-
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date().toISOString()
|
|
604
|
-
};
|
|
605
|
-
} catch {
|
|
606
|
-
return null;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
function writeSessionJsonTokenTotals(sessionRootPath, tokenUsage) {
|
|
610
|
-
const path = sessionJsonPath(sessionRootPath);
|
|
611
|
-
if (!existsSync2(path))
|
|
612
|
-
return;
|
|
613
|
-
try {
|
|
614
|
-
const parsed = JSON.parse(readFileSync2(path, "utf-8"));
|
|
615
|
-
parsed.tokensIn = tokenUsage.inputTokens;
|
|
616
|
-
parsed.tokensOut = tokenUsage.outputTokens;
|
|
617
|
-
writeFileSync2(path, JSON.stringify(parsed, null, 2));
|
|
618
|
-
} catch {}
|
|
619
|
-
}
|
|
620
|
-
function writeExecutionMetrics(input) {
|
|
621
|
-
const existing = readExecutionMetrics(input.sessionRootPath);
|
|
622
|
-
const nextTokenUsage = input.tokenUsage ? normalizeTokenUsage(input.tokenUsage) : existing?.tokenUsage ?? {
|
|
623
|
-
inputTokens: 0,
|
|
624
|
-
outputTokens: 0,
|
|
625
|
-
totalTokens: 0
|
|
626
|
-
};
|
|
627
|
-
const next = {
|
|
628
|
-
tokenUsage: nextTokenUsage,
|
|
629
|
-
runtime: input.runtime ?? existing?.runtime,
|
|
630
|
-
elapsedSeconds: input.elapsedSeconds ?? existing?.elapsedSeconds,
|
|
631
|
-
updatedAt: new Date().toISOString()
|
|
632
|
-
};
|
|
633
|
-
writeFileSync2(metricsPath(input.sessionRootPath), JSON.stringify(next, null, 2), "utf-8");
|
|
634
|
-
writeSessionJsonTokenTotals(input.sessionRootPath, next.tokenUsage);
|
|
635
|
-
return next;
|
|
636
|
-
}
|
|
637
|
-
function formatDurationHmsFromMs(durationMs) {
|
|
638
|
-
const totalSeconds = Math.max(0, Math.floor(durationMs / 1000));
|
|
639
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
640
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
641
|
-
const seconds = totalSeconds % 60;
|
|
642
|
-
return `${hours}h${minutes}m${seconds}s`;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
export { buildPentestReport, renderMarkdown, renderJson, REPORT_FILENAME_MD, REPORT_FILENAME_JSON, loadSubagentMessages, saveSubagentData, writeAgentManifest, readAgentManifest, buildManifestEntries, finalizeManifest, updateManifestEntryStatus, getCompletedAgentIds, convertModelMessagesToUI, loadSubagents, readExecutionMetrics, writeExecutionMetrics, formatDurationHmsFromMs };
|
package/build/index-bz6f8jry.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ALL_TOOL_NAMES,
|
|
3
|
-
ASK_USER_QUESTIONS_TOOL_NAME,
|
|
4
|
-
AgentEventBus,
|
|
5
|
-
OffensiveSecurityAgent,
|
|
6
|
-
PLAN_MODE_TOOL_NAMES,
|
|
7
|
-
SKILL_TOOL_NAMES,
|
|
8
|
-
StepTraceWriter,
|
|
9
|
-
createAllTools
|
|
10
|
-
} from "./cli-3w2syxpv.js";
|
|
11
|
-
import"./cli-tp1tqn3k.js";
|
|
12
|
-
import"./cli-g8t710ew.js";
|
|
13
|
-
import"./cli-3y0dgy56.js";
|
|
14
|
-
import"./cli-k0tckznm.js";
|
|
15
|
-
import"./cli-0ghkg3w6.js";
|
|
16
|
-
import"./cli-dqt80sw3.js";
|
|
17
|
-
import"./cli-asyas1xb.js";
|
|
18
|
-
import"./cli-gpnb45ck.js";
|
|
19
|
-
import"./cli-nr1cjfr9.js";
|
|
20
|
-
import"./cli-dj1dgw2n.js";
|
|
21
|
-
import"./cli-03z6pswp.js";
|
|
22
|
-
import"./cli-8rxa073f.js";
|
|
23
|
-
export {
|
|
24
|
-
createAllTools,
|
|
25
|
-
StepTraceWriter,
|
|
26
|
-
SKILL_TOOL_NAMES,
|
|
27
|
-
PLAN_MODE_TOOL_NAMES,
|
|
28
|
-
OffensiveSecurityAgent,
|
|
29
|
-
AgentEventBus,
|
|
30
|
-
ASK_USER_QUESTIONS_TOOL_NAME,
|
|
31
|
-
ALL_TOOL_NAMES
|
|
32
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_CONCURRENCY,
|
|
3
|
-
runPentestSwarm,
|
|
4
|
-
runPentestWorkflow
|
|
5
|
-
} from "./cli-vkwch0bc.js";
|
|
6
|
-
import"./cli-wr7g9qcr.js";
|
|
7
|
-
import"./cli-y61d9433.js";
|
|
8
|
-
import"./cli-0fy9j5dw.js";
|
|
9
|
-
import"./cli-k4hrygff.js";
|
|
10
|
-
import"./cli-fw5r7pfj.js";
|
|
11
|
-
import"./cli-jg7r7y5n.js";
|
|
12
|
-
import"./cli-3w2syxpv.js";
|
|
13
|
-
import"./cli-tp1tqn3k.js";
|
|
14
|
-
import"./cli-g8t710ew.js";
|
|
15
|
-
import"./cli-3y0dgy56.js";
|
|
16
|
-
import"./cli-k0tckznm.js";
|
|
17
|
-
import"./cli-0ghkg3w6.js";
|
|
18
|
-
import"./cli-dqt80sw3.js";
|
|
19
|
-
import"./cli-asyas1xb.js";
|
|
20
|
-
import"./cli-gpnb45ck.js";
|
|
21
|
-
import"./cli-nr1cjfr9.js";
|
|
22
|
-
import"./cli-dj1dgw2n.js";
|
|
23
|
-
import"./cli-03z6pswp.js";
|
|
24
|
-
import"./cli-8rxa073f.js";
|
|
25
|
-
export {
|
|
26
|
-
runPentestWorkflow,
|
|
27
|
-
runPentestSwarm,
|
|
28
|
-
DEFAULT_CONCURRENCY
|
|
29
|
-
};
|