pentesting 0.56.2 → 0.56.3
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/dist/main.js +121 -24
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -711,7 +711,7 @@ var INPUT_PROMPT_PATTERNS = [
|
|
|
711
711
|
|
|
712
712
|
// src/shared/constants/agent.ts
|
|
713
713
|
var APP_NAME = "Pentest AI";
|
|
714
|
-
var APP_VERSION = "0.56.
|
|
714
|
+
var APP_VERSION = "0.56.3";
|
|
715
715
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
716
716
|
var LLM_ROLES = {
|
|
717
717
|
SYSTEM: "system",
|
|
@@ -14929,6 +14929,15 @@ var boxLine = (content, width) => {
|
|
|
14929
14929
|
const truncated = content.length > inner ? content.slice(0, inner - 1) + "\u2026" : content;
|
|
14930
14930
|
return `\u2502 ${truncated.padEnd(inner - 1)}`;
|
|
14931
14931
|
};
|
|
14932
|
+
var formatTargetLine = (target) => {
|
|
14933
|
+
if (target.ports.length === 0) return target.ip;
|
|
14934
|
+
const portList = target.ports.map((p) => `${p.port}`).join(", ");
|
|
14935
|
+
return `${target.ip} \u2192 ${target.ip}:${portList}`;
|
|
14936
|
+
};
|
|
14937
|
+
var formatServiceLabel = (target, port) => {
|
|
14938
|
+
const svc = port.version ? `${port.service}/${port.version}` : port.service;
|
|
14939
|
+
return `${target.ip}:${port.port} (${svc})`;
|
|
14940
|
+
};
|
|
14932
14941
|
var formatFindingsWithFlags = (findings, flags) => {
|
|
14933
14942
|
const findingsOutput = formatFindings(findings);
|
|
14934
14943
|
const flagsOutput = formatFlags(flags);
|
|
@@ -14938,41 +14947,108 @@ ${flagsOutput}`;
|
|
|
14938
14947
|
}
|
|
14939
14948
|
return findingsOutput;
|
|
14940
14949
|
};
|
|
14941
|
-
var formatGraphWithSummary = (
|
|
14950
|
+
var formatGraphWithSummary = (state, findings, flags) => {
|
|
14942
14951
|
const lines = [];
|
|
14943
14952
|
const w = getBoxWidth();
|
|
14944
14953
|
const innerDash = w - 2;
|
|
14945
|
-
|
|
14946
|
-
|
|
14947
|
-
|
|
14948
|
-
|
|
14949
|
-
|
|
14954
|
+
const targets = state.getAllTargets();
|
|
14955
|
+
const graphStats = state.attackGraph.getStats();
|
|
14956
|
+
const allNodes = state.attackGraph.getAllNodes();
|
|
14957
|
+
const hostNodes = allNodes.filter((n) => n.type === NODE_TYPE.HOST);
|
|
14958
|
+
const serviceNodes = allNodes.filter((n) => n.type === NODE_TYPE.SERVICE);
|
|
14959
|
+
const vulnNodes = allNodes.filter((n) => n.type === NODE_TYPE.VULNERABILITY);
|
|
14960
|
+
const hostCount = hostNodes.length || targets.length;
|
|
14961
|
+
const serviceCount = serviceNodes.length || targets.reduce((sum, t) => sum + t.ports.length, 0);
|
|
14962
|
+
const vulnCount = findings.length;
|
|
14963
|
+
const topTitle = "\u2500\u2500\u2500 Attack Graph ";
|
|
14964
|
+
lines.push(`\u250C${topTitle}${"\u2500".repeat(Math.max(0, innerDash - topTitle.length))}\u2510`);
|
|
14965
|
+
lines.push(boxLine(`\u{1F5A5} ${hostCount} \u26A0 ${vulnCount} \u2699 ${serviceCount}`, w));
|
|
14950
14966
|
lines.push(boxLine("", w));
|
|
14951
|
-
lines.push(boxLine(`\
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
|
|
14957
|
-
|
|
14967
|
+
lines.push(boxLine(`\u{1F5A5} HOST (${hostCount})`, w));
|
|
14968
|
+
if (targets.length > 0) {
|
|
14969
|
+
for (const t of targets.slice(0, 5)) {
|
|
14970
|
+
lines.push(boxLine(` \u25CB ${formatTargetLine(t)}`, w));
|
|
14971
|
+
}
|
|
14972
|
+
if (targets.length > 5) {
|
|
14973
|
+
lines.push(boxLine(` ... and ${targets.length - 5} more hosts`, w));
|
|
14974
|
+
}
|
|
14975
|
+
} else if (hostNodes.length > 0) {
|
|
14976
|
+
for (const node of hostNodes.slice(0, 5)) {
|
|
14977
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
14978
|
+
}
|
|
14979
|
+
if (hostNodes.length > 5) {
|
|
14980
|
+
lines.push(boxLine(` ... and ${hostNodes.length - 5} more hosts`, w));
|
|
14981
|
+
}
|
|
14982
|
+
} else {
|
|
14983
|
+
lines.push(boxLine(" (no hosts discovered)", w));
|
|
14958
14984
|
}
|
|
14959
|
-
|
|
14960
|
-
|
|
14985
|
+
lines.push(boxLine("", w));
|
|
14986
|
+
lines.push(boxLine(`\u26A0 VULNERABILITY (${vulnCount})`, w));
|
|
14987
|
+
if (findings.length > 0) {
|
|
14988
|
+
const sortedFindings = [...findings].sort((a, b) => b.confidence - a.confidence).slice(0, 5);
|
|
14989
|
+
for (const f of sortedFindings) {
|
|
14990
|
+
const icon = confIcon(f.confidence);
|
|
14991
|
+
const cat = f.category ? ` \u2502 ${f.category}` : "";
|
|
14992
|
+
lines.push(boxLine(` \u25CB ${icon} ${f.title.slice(0, 60)}${f.title.length > 60 ? "..." : ""}`, w));
|
|
14993
|
+
lines.push(boxLine(` ${confLabel(f.confidence).toUpperCase()} \u2502 ${f.severity.toUpperCase()}${cat}`, w));
|
|
14994
|
+
}
|
|
14995
|
+
if (findings.length > 5) {
|
|
14996
|
+
lines.push(boxLine(` ... and ${findings.length - 5} more findings`, w));
|
|
14997
|
+
}
|
|
14998
|
+
} else if (vulnNodes.length > 0) {
|
|
14999
|
+
for (const node of vulnNodes.slice(0, 5)) {
|
|
15000
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
15001
|
+
}
|
|
15002
|
+
if (vulnNodes.length > 5) {
|
|
15003
|
+
lines.push(boxLine(` ... and ${vulnNodes.length - 5} more`, w));
|
|
15004
|
+
}
|
|
15005
|
+
} else {
|
|
15006
|
+
lines.push(boxLine(" (no vulnerabilities found)", w));
|
|
14961
15007
|
}
|
|
14962
15008
|
const cveFindings = findings.filter((f) => f.title.includes("CVE"));
|
|
14963
15009
|
if (cveFindings.length > 0) {
|
|
14964
|
-
|
|
15010
|
+
const cveList = cveFindings.slice(0, 3).map((f) => f.title.match(/CVE-\d{4}-\d+/)?.[0] ?? f.title).join(", ");
|
|
15011
|
+
const suffix = cveFindings.length > 3 ? ` (+${cveFindings.length - 3} more)` : "";
|
|
15012
|
+
lines.push(boxLine(` \u25CB CVE found: ${cveList}${suffix}`, w));
|
|
14965
15013
|
}
|
|
14966
15014
|
lines.push(boxLine("", w));
|
|
14967
|
-
lines.push(boxLine(
|
|
14968
|
-
|
|
15015
|
+
lines.push(boxLine(`\u2699 SERVICE (${serviceCount})`, w));
|
|
15016
|
+
if (targets.length > 0) {
|
|
15017
|
+
let shownServices = 0;
|
|
15018
|
+
const maxShow = 5;
|
|
15019
|
+
for (const t of targets) {
|
|
15020
|
+
for (const p of t.ports) {
|
|
15021
|
+
if (shownServices >= maxShow) break;
|
|
15022
|
+
lines.push(boxLine(` \u25CB ${formatServiceLabel(t, p)}`, w));
|
|
15023
|
+
shownServices++;
|
|
15024
|
+
}
|
|
15025
|
+
if (shownServices >= maxShow) break;
|
|
15026
|
+
}
|
|
15027
|
+
const totalServices = targets.reduce((sum, t) => sum + t.ports.length, 0);
|
|
15028
|
+
if (totalServices > maxShow) {
|
|
15029
|
+
lines.push(boxLine(` ... and ${totalServices - maxShow} more services`, w));
|
|
15030
|
+
}
|
|
15031
|
+
} else if (serviceNodes.length > 0) {
|
|
15032
|
+
for (const node of serviceNodes.slice(0, 5)) {
|
|
15033
|
+
lines.push(boxLine(` \u25CB ${node.label}`, w));
|
|
15034
|
+
}
|
|
15035
|
+
if (serviceNodes.length > 5) {
|
|
15036
|
+
lines.push(boxLine(` ... and ${serviceNodes.length - 5} more`, w));
|
|
15037
|
+
}
|
|
15038
|
+
} else {
|
|
15039
|
+
lines.push(boxLine(" (no services discovered)", w));
|
|
15040
|
+
}
|
|
14969
15041
|
if (flags.length > 0) {
|
|
14970
15042
|
lines.push(boxLine("", w));
|
|
14971
15043
|
lines.push(boxLine(`\u{1F3F4} Captured: ${flags.length}`, w));
|
|
14972
15044
|
}
|
|
14973
15045
|
lines.push(boxLine("", w));
|
|
14974
|
-
|
|
14975
|
-
lines.push(
|
|
15046
|
+
const midTitle = "\u2500\u2500\u2500 Summary ";
|
|
15047
|
+
lines.push(`\u251C${midTitle}${"\u2500".repeat(Math.max(0, innerDash - midTitle.length))}\u2524`);
|
|
15048
|
+
lines.push(boxLine(
|
|
15049
|
+
`Nodes: ${graphStats.nodes} | Edges: ${graphStats.edges} | Succeeded: ${graphStats.succeeded} | Failed: ${graphStats.failed} | Chains: ${graphStats.chains}`,
|
|
15050
|
+
w
|
|
15051
|
+
));
|
|
14976
15052
|
lines.push(`\u2514${"\u2500".repeat(innerDash)}\u2518`);
|
|
14977
15053
|
return lines.join("\n");
|
|
14978
15054
|
};
|
|
@@ -15031,7 +15107,7 @@ ${procData.stdout || "(no output)"}
|
|
|
15031
15107
|
const flags = state.getFlags();
|
|
15032
15108
|
const graphASCII = state.attackGraph.toASCII();
|
|
15033
15109
|
if (state.attackGraph.isEmpty() && (findings.length > 0 || flags.length > 0)) {
|
|
15034
|
-
ctx.showModal("graph", formatGraphWithSummary(
|
|
15110
|
+
ctx.showModal("graph", formatGraphWithSummary(state, findings, flags));
|
|
15035
15111
|
} else {
|
|
15036
15112
|
let output = graphASCII;
|
|
15037
15113
|
if (flags.length > 0) {
|
|
@@ -15046,7 +15122,7 @@ ${procData.stdout || "(no output)"}
|
|
|
15046
15122
|
const flags = state.getFlags();
|
|
15047
15123
|
const graphASCII = state.attackGraph.toASCII();
|
|
15048
15124
|
if (state.attackGraph.isEmpty() && (findings.length > 0 || flags.length > 0)) {
|
|
15049
|
-
ctx.showModal("graph", formatGraphWithSummary(
|
|
15125
|
+
ctx.showModal("graph", formatGraphWithSummary(state, findings, flags));
|
|
15050
15126
|
} else {
|
|
15051
15127
|
let output = graphASCII;
|
|
15052
15128
|
if (flags.length > 0) {
|
|
@@ -16306,6 +16382,27 @@ var ChatInput = memo10(({
|
|
|
16306
16382
|
setSelectedIdx(0);
|
|
16307
16383
|
setInputKey((k) => k + 1);
|
|
16308
16384
|
}, []);
|
|
16385
|
+
const onSubmitRef = useRef8(onSubmit);
|
|
16386
|
+
onSubmitRef.current = onSubmit;
|
|
16387
|
+
const wrappedOnSubmit = useCallback9((val) => {
|
|
16388
|
+
if (showPreviewRef.current) {
|
|
16389
|
+
const sug = suggestionsRef.current;
|
|
16390
|
+
if (!sug.length) {
|
|
16391
|
+
onSubmitRef.current(val);
|
|
16392
|
+
return;
|
|
16393
|
+
}
|
|
16394
|
+
const best = sug[Math.min(selectedIdxRef.current, sug.length - 1)];
|
|
16395
|
+
if (best.args) {
|
|
16396
|
+
completeCommand(selectedIdxRef.current);
|
|
16397
|
+
} else {
|
|
16398
|
+
const completed = `/${best.name}`;
|
|
16399
|
+
onChangeRef.current(completed);
|
|
16400
|
+
onSubmitRef.current(completed);
|
|
16401
|
+
}
|
|
16402
|
+
return;
|
|
16403
|
+
}
|
|
16404
|
+
onSubmitRef.current(val);
|
|
16405
|
+
}, [completeCommand]);
|
|
16309
16406
|
useInput3(useCallback9((_input, key) => {
|
|
16310
16407
|
if (inputRequestRef.current.status === "active") return;
|
|
16311
16408
|
const sug = suggestionsRef.current;
|
|
@@ -16349,7 +16446,7 @@ var ChatInput = memo10(({
|
|
|
16349
16446
|
inputKey,
|
|
16350
16447
|
value,
|
|
16351
16448
|
onChange,
|
|
16352
|
-
onSubmit,
|
|
16449
|
+
onSubmit: wrappedOnSubmit,
|
|
16353
16450
|
placeholder
|
|
16354
16451
|
}
|
|
16355
16452
|
)
|