pentesting 0.40.3 → 0.40.6
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 +78 -10
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -306,7 +306,7 @@ var ORPHAN_PROCESS_NAMES = [
|
|
|
306
306
|
|
|
307
307
|
// src/shared/constants/agent.ts
|
|
308
308
|
var APP_NAME = "Pentest AI";
|
|
309
|
-
var APP_VERSION = "0.40.
|
|
309
|
+
var APP_VERSION = "0.40.6";
|
|
310
310
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
311
311
|
var LLM_ROLES = {
|
|
312
312
|
SYSTEM: "system",
|
|
@@ -444,6 +444,7 @@ var TOOL_NAMES = {
|
|
|
444
444
|
ADD_FINDING: "add_finding",
|
|
445
445
|
UPDATE_MISSION: "update_mission",
|
|
446
446
|
UPDATE_TODO: "update_todo",
|
|
447
|
+
UPDATE_PHASE: "update_phase",
|
|
447
448
|
HASH_CRACK: "hash_crack",
|
|
448
449
|
ADD_LOOT: "add_loot",
|
|
449
450
|
GET_STATE: "get_state",
|
|
@@ -4189,7 +4190,7 @@ All ports freed. All children killed.`
|
|
|
4189
4190
|
];
|
|
4190
4191
|
|
|
4191
4192
|
// src/engine/tools/pentest-state-tools.ts
|
|
4192
|
-
var createStateTools = (state) => [
|
|
4193
|
+
var createStateTools = (state, events) => [
|
|
4193
4194
|
{
|
|
4194
4195
|
name: TOOL_NAMES.UPDATE_MISSION,
|
|
4195
4196
|
description: `Update the mission summary and checklist.
|
|
@@ -4240,6 +4241,58 @@ Checklist Items: ${state.getMissionChecklist().length}`
|
|
|
4240
4241
|
description: "Get current engagement state summary",
|
|
4241
4242
|
parameters: {},
|
|
4242
4243
|
execute: async () => ({ success: true, output: state.toPrompt() })
|
|
4244
|
+
},
|
|
4245
|
+
{
|
|
4246
|
+
name: TOOL_NAMES.UPDATE_PHASE,
|
|
4247
|
+
description: `Update the current penetration testing phase.
|
|
4248
|
+
Use this to signal progress through the engagement lifecycle.
|
|
4249
|
+
Valid phases: ${Object.values(PHASES).join(", ")}
|
|
4250
|
+
Phase transitions should reflect actual progress, not just time passed.
|
|
4251
|
+
Examples:
|
|
4252
|
+
- recon \u2192 vulnerability_analysis: After port scanning and service enumeration
|
|
4253
|
+
- vulnerability_analysis \u2192 exploit: After finding exploitable vulnerabilities
|
|
4254
|
+
- exploit \u2192 post_exploitation: After gaining initial access
|
|
4255
|
+
- post_exploitation \u2192 privilege_escalation: When seeking higher privileges
|
|
4256
|
+
- privilege_escalation \u2192 lateral_movement: When pivoting to other hosts`,
|
|
4257
|
+
parameters: {
|
|
4258
|
+
phase: {
|
|
4259
|
+
type: "string",
|
|
4260
|
+
description: "The new phase to transition to",
|
|
4261
|
+
enum: Object.values(PHASES)
|
|
4262
|
+
},
|
|
4263
|
+
reason: {
|
|
4264
|
+
type: "string",
|
|
4265
|
+
description: "Brief explanation for the phase change"
|
|
4266
|
+
}
|
|
4267
|
+
},
|
|
4268
|
+
required: ["phase"],
|
|
4269
|
+
execute: async (p) => {
|
|
4270
|
+
const newPhase = p.phase;
|
|
4271
|
+
const reason = p.reason || "Phase transition";
|
|
4272
|
+
const oldPhase = state.getPhase();
|
|
4273
|
+
const validPhases = Object.values(PHASES);
|
|
4274
|
+
if (!validPhases.includes(newPhase)) {
|
|
4275
|
+
return {
|
|
4276
|
+
success: false,
|
|
4277
|
+
output: `Invalid phase. Valid phases: ${validPhases.join(", ")}`
|
|
4278
|
+
};
|
|
4279
|
+
}
|
|
4280
|
+
state.setPhase(newPhase);
|
|
4281
|
+
events.emit({
|
|
4282
|
+
type: EVENT_TYPES.PHASE_CHANGE,
|
|
4283
|
+
timestamp: Date.now(),
|
|
4284
|
+
data: {
|
|
4285
|
+
fromPhase: oldPhase,
|
|
4286
|
+
toPhase: newPhase,
|
|
4287
|
+
reason
|
|
4288
|
+
}
|
|
4289
|
+
});
|
|
4290
|
+
return {
|
|
4291
|
+
success: true,
|
|
4292
|
+
output: `Phase changed: ${oldPhase} \u2192 ${newPhase}
|
|
4293
|
+
Reason: ${reason}`
|
|
4294
|
+
};
|
|
4295
|
+
}
|
|
4243
4296
|
}
|
|
4244
4297
|
];
|
|
4245
4298
|
|
|
@@ -6277,8 +6330,8 @@ Returns: All available wordlists with their paths, sizes, and categories.`,
|
|
|
6277
6330
|
];
|
|
6278
6331
|
|
|
6279
6332
|
// src/engine/tools/pentest.ts
|
|
6280
|
-
var createPentestTools = (state) => [
|
|
6281
|
-
...createStateTools(state),
|
|
6333
|
+
var createPentestTools = (state, events) => [
|
|
6334
|
+
...createStateTools(state, events),
|
|
6282
6335
|
...createTargetTools(state),
|
|
6283
6336
|
...createIntelTools(state),
|
|
6284
6337
|
...createAttackTools(state)
|
|
@@ -7683,7 +7736,7 @@ var ToolRegistry = class {
|
|
|
7683
7736
|
initializeRegistry() {
|
|
7684
7737
|
const allTools = [
|
|
7685
7738
|
...systemTools,
|
|
7686
|
-
...createPentestTools(this.state),
|
|
7739
|
+
...createPentestTools(this.state, this.events),
|
|
7687
7740
|
...createAgentTools(),
|
|
7688
7741
|
...createNetworkAttackTools(),
|
|
7689
7742
|
...resourceTools,
|
|
@@ -10987,6 +11040,16 @@ var useAgentEvents = (agent, eventsRef, state) => {
|
|
|
10987
11040
|
const onFlagFound = (e) => {
|
|
10988
11041
|
addMessage("system", `\u{1F3F4} FLAG FOUND: ${e.data.flag} (total: ${e.data.totalFlags})`);
|
|
10989
11042
|
};
|
|
11043
|
+
const onPhaseChange = (e) => {
|
|
11044
|
+
addMessage("system", `\u{1F504} Phase: ${e.data.fromPhase} \u2192 ${e.data.toPhase} (${e.data.reason})`);
|
|
11045
|
+
const s = agent.getState();
|
|
11046
|
+
setStats({
|
|
11047
|
+
phase: e.data.toPhase,
|
|
11048
|
+
targets: s.getTargets().size,
|
|
11049
|
+
findings: s.getFindings().length,
|
|
11050
|
+
todo: s.getTodo().length
|
|
11051
|
+
});
|
|
11052
|
+
};
|
|
10990
11053
|
setInputHandler((p) => {
|
|
10991
11054
|
return new Promise((resolve) => {
|
|
10992
11055
|
const isPassword = /password|passphrase/i.test(p);
|
|
@@ -11040,6 +11103,7 @@ var useAgentEvents = (agent, eventsRef, state) => {
|
|
|
11040
11103
|
events.on(EVENT_TYPES.RETRY, onRetry);
|
|
11041
11104
|
events.on(EVENT_TYPES.USAGE_UPDATE, onUsageUpdate);
|
|
11042
11105
|
events.on(EVENT_TYPES.FLAG_FOUND, onFlagFound);
|
|
11106
|
+
events.on(EVENT_TYPES.PHASE_CHANGE, onPhaseChange);
|
|
11043
11107
|
events.on(EVENT_TYPES.STATE_CHANGE, updateStats);
|
|
11044
11108
|
events.on(EVENT_TYPES.START, updateStats);
|
|
11045
11109
|
updateStats();
|
|
@@ -11411,7 +11475,7 @@ import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
|
11411
11475
|
import { Text as Text3 } from "ink";
|
|
11412
11476
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
11413
11477
|
var FRAMES = ["\u2669", "\u266A", "\u266B", "\u266C", "\u266B", "\u266A"];
|
|
11414
|
-
var INTERVAL =
|
|
11478
|
+
var INTERVAL = 400;
|
|
11415
11479
|
var MusicSpinner = ({ color }) => {
|
|
11416
11480
|
const [index, setIndex] = useState3(0);
|
|
11417
11481
|
useEffect3(() => {
|
|
@@ -11593,6 +11657,10 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
11593
11657
|
cancelInputRequest,
|
|
11594
11658
|
addMessage
|
|
11595
11659
|
} = useAgent(autoApproveMode, target);
|
|
11660
|
+
const isProcessingRef = useRef3(isProcessing);
|
|
11661
|
+
isProcessingRef.current = isProcessing;
|
|
11662
|
+
const autoApproveModeRef = useRef3(autoApproveMode);
|
|
11663
|
+
autoApproveModeRef.current = autoApproveMode;
|
|
11596
11664
|
const inputRequestRef = useRef3(inputRequest);
|
|
11597
11665
|
inputRequestRef.current = inputRequest;
|
|
11598
11666
|
const handleExit = useCallback3(() => {
|
|
@@ -11629,7 +11697,7 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
11629
11697
|
addMessage("error", "Set target first: /target <ip>");
|
|
11630
11698
|
break;
|
|
11631
11699
|
}
|
|
11632
|
-
if (!
|
|
11700
|
+
if (!autoApproveModeRef.current) {
|
|
11633
11701
|
setAutoApproveMode(true);
|
|
11634
11702
|
agent.setAutoApprove(true);
|
|
11635
11703
|
addMessage("system", "\u{1F680} Autonomous mode enabled (auto-approve ON)");
|
|
@@ -11688,7 +11756,7 @@ ${procData.stdout || "(no output)"}
|
|
|
11688
11756
|
default:
|
|
11689
11757
|
addMessage("error", `Unknown command: /${cmd}`);
|
|
11690
11758
|
}
|
|
11691
|
-
}, [agent, addMessage, executeTask, setMessages, handleExit
|
|
11759
|
+
}, [agent, addMessage, executeTask, setMessages, handleExit]);
|
|
11692
11760
|
const handleSubmit = useCallback3(async (value) => {
|
|
11693
11761
|
const trimmed = value.trim();
|
|
11694
11762
|
if (!trimmed) return;
|
|
@@ -11714,10 +11782,10 @@ ${procData.stdout || "(no output)"}
|
|
|
11714
11782
|
useInput(useCallback3((ch, key) => {
|
|
11715
11783
|
if (key.escape) {
|
|
11716
11784
|
if (inputRequestRef.current.isActive) cancelInputRequest();
|
|
11717
|
-
else if (
|
|
11785
|
+
else if (isProcessingRef.current) abort();
|
|
11718
11786
|
}
|
|
11719
11787
|
if (key.ctrl && ch === "c") handleExit();
|
|
11720
|
-
}, [cancelInputRequest,
|
|
11788
|
+
}, [cancelInputRequest, abort, handleExit]));
|
|
11721
11789
|
useEffect4(() => {
|
|
11722
11790
|
const onSignal = () => handleExit();
|
|
11723
11791
|
process.on("SIGINT", onSignal);
|