pentesting 0.4.9 → 0.5.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/{auto-update-GKUAPLBP.js → auto-update-IDSABTT4.js} +2 -2
- package/dist/{chunk-X3X45KYT.js → chunk-FHPP7RP2.js} +1 -1
- package/dist/{chunk-L4MURCOP.js → chunk-ZC53SMRU.js} +1 -1
- package/dist/index.js +389 -20
- package/dist/{update-2U2TR7HJ.js → update-OWR4FHRQ.js} +2 -2
- package/package.json +2 -2
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
readVersionCache,
|
|
9
9
|
semverTuple,
|
|
10
10
|
writeVersionCache
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-ZC53SMRU.js";
|
|
12
|
+
import "./chunk-FHPP7RP2.js";
|
|
13
13
|
import "./chunk-3RG5ZIWI.js";
|
|
14
14
|
export {
|
|
15
15
|
checkForUpdate,
|
|
@@ -132,7 +132,7 @@ var SENSITIVE_TOOLS = [
|
|
|
132
132
|
|
|
133
133
|
// src/config/constants.ts
|
|
134
134
|
var APP_NAME = "pentesting";
|
|
135
|
-
var APP_VERSION = "0.
|
|
135
|
+
var APP_VERSION = "0.5.1";
|
|
136
136
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
137
137
|
var LLM_API_KEY = process.env.PENTEST_API_KEY || process.env.ANTHROPIC_API_KEY || "";
|
|
138
138
|
var LLM_BASE_URL = process.env.PENTEST_BASE_URL || void 0;
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
PHASE_STATUS,
|
|
16
16
|
THOUGHT_TYPE,
|
|
17
17
|
TOOL_NAME
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-FHPP7RP2.js";
|
|
19
19
|
import {
|
|
20
20
|
__require
|
|
21
21
|
} from "./chunk-3RG5ZIWI.js";
|
|
@@ -1723,9 +1723,27 @@ var ApprovalManager = class extends EventEmitter3 {
|
|
|
1723
1723
|
this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
|
|
1724
1724
|
if (response.decision === "approve_always") {
|
|
1725
1725
|
this.autoApprovedTools.add(toolName);
|
|
1726
|
+
const pendingForSameTool = Array.from(this.pendingRequests.entries()).filter(([_, req]) => req.toolName === toolName);
|
|
1727
|
+
for (const [pendingId, _] of pendingForSameTool) {
|
|
1728
|
+
this.pendingRequests.delete(pendingId);
|
|
1729
|
+
this.emit(APPROVAL_EVENT.RESPONSE, {
|
|
1730
|
+
requestId: pendingId,
|
|
1731
|
+
decision: "approve",
|
|
1732
|
+
respondedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1726
1735
|
resolve("approve");
|
|
1727
1736
|
} else if (response.decision === "deny_always") {
|
|
1728
1737
|
this.autoDeniedTools.add(toolName);
|
|
1738
|
+
const pendingForSameTool = Array.from(this.pendingRequests.entries()).filter(([_, req]) => req.toolName === toolName);
|
|
1739
|
+
for (const [pendingId, _] of pendingForSameTool) {
|
|
1740
|
+
this.pendingRequests.delete(pendingId);
|
|
1741
|
+
this.emit(APPROVAL_EVENT.RESPONSE, {
|
|
1742
|
+
requestId: pendingId,
|
|
1743
|
+
decision: "deny",
|
|
1744
|
+
respondedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1729
1747
|
resolve("deny");
|
|
1730
1748
|
} else {
|
|
1731
1749
|
resolve(response.decision);
|
|
@@ -3298,6 +3316,14 @@ ${prompt}`
|
|
|
3298
3316
|
this.state.lastProgressTime = /* @__PURE__ */ new Date();
|
|
3299
3317
|
this.state.repeatedActions.clear();
|
|
3300
3318
|
}
|
|
3319
|
+
/**
|
|
3320
|
+
* Check if the main loop should stop (due to pause, completion, etc.)
|
|
3321
|
+
* Uses string comparison to avoid TypeScript narrowing issues with const enums
|
|
3322
|
+
*/
|
|
3323
|
+
shouldStopLoop() {
|
|
3324
|
+
const status = this.state.status;
|
|
3325
|
+
return status === AGENT_STATUS.PAUSED || status === AGENT_STATUS.COMPLETED || status === AGENT_STATUS.IDLE;
|
|
3326
|
+
}
|
|
3301
3327
|
trackAction(action) {
|
|
3302
3328
|
const count = this.state.repeatedActions.get(action) || 0;
|
|
3303
3329
|
this.state.repeatedActions.set(action, count + 1);
|
|
@@ -3399,7 +3425,7 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
3399
3425
|
});
|
|
3400
3426
|
let iteration = 0;
|
|
3401
3427
|
const maxIterations = this.config.maxIterations;
|
|
3402
|
-
while (iteration < maxIterations && this.
|
|
3428
|
+
while (iteration < maxIterations && !this.shouldStopLoop()) {
|
|
3403
3429
|
iteration++;
|
|
3404
3430
|
this.state.iteration = iteration;
|
|
3405
3431
|
this.getCurrentPhase().attempts++;
|
|
@@ -3422,7 +3448,15 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
3422
3448
|
continue;
|
|
3423
3449
|
}
|
|
3424
3450
|
const response = await this.executeStep();
|
|
3451
|
+
if (this.shouldStopLoop()) {
|
|
3452
|
+
this.think(THOUGHT_TYPE.OBSERVATION, "Execution paused by user");
|
|
3453
|
+
break;
|
|
3454
|
+
}
|
|
3425
3455
|
await this.analyzeResponse(response);
|
|
3456
|
+
if (this.shouldStopLoop()) {
|
|
3457
|
+
this.think(THOUGHT_TYPE.OBSERVATION, "Execution paused by user");
|
|
3458
|
+
break;
|
|
3459
|
+
}
|
|
3426
3460
|
if (this.shouldAdvancePhase()) {
|
|
3427
3461
|
if (!this.advanceToNextPhase()) {
|
|
3428
3462
|
this.think(THOUGHT_TYPE.OBSERVATION, "[done] All phases completed!");
|
|
@@ -3436,9 +3470,14 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
3436
3470
|
await this.attemptRecovery(error);
|
|
3437
3471
|
}
|
|
3438
3472
|
}
|
|
3439
|
-
this.state.status
|
|
3440
|
-
|
|
3441
|
-
|
|
3473
|
+
const finalStatus = this.state.status;
|
|
3474
|
+
if (finalStatus !== AGENT_STATUS.PAUSED && finalStatus !== AGENT_STATUS.COMPLETED) {
|
|
3475
|
+
this.state.status = AGENT_STATUS.COMPLETED;
|
|
3476
|
+
await this.generateFinalReport();
|
|
3477
|
+
this.emit(AGENT_EVENT.COMPLETE, this.getSummary());
|
|
3478
|
+
} else if (finalStatus === AGENT_STATUS.PAUSED) {
|
|
3479
|
+
this.emit(AGENT_EVENT.PAUSED);
|
|
3480
|
+
}
|
|
3442
3481
|
}
|
|
3443
3482
|
// ===== Step Execution =====
|
|
3444
3483
|
async executeStep() {
|
|
@@ -3596,6 +3635,25 @@ Use report_finding tool for important discoveries.
|
|
|
3596
3635
|
is_error: !result.success
|
|
3597
3636
|
}]
|
|
3598
3637
|
});
|
|
3638
|
+
if (!this.state.target.primary && result.success && result.output) {
|
|
3639
|
+
const ipMatches = result.output.match(/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g);
|
|
3640
|
+
if (ipMatches) {
|
|
3641
|
+
const validIPs = [...new Set(ipMatches)].filter(
|
|
3642
|
+
(ip) => !ip.startsWith("127.") && !ip.startsWith("0.") && !ip.startsWith("255.")
|
|
3643
|
+
);
|
|
3644
|
+
if (validIPs.length === 1) {
|
|
3645
|
+
this.setTarget(validIPs[0]);
|
|
3646
|
+
this.emit(AGENT_EVENT.RESPONSE, `
|
|
3647
|
+
[Target auto-set: ${validIPs[0]}]
|
|
3648
|
+
`);
|
|
3649
|
+
} else if (validIPs.length > 1) {
|
|
3650
|
+
this.emit(AGENT_EVENT.RESPONSE, `
|
|
3651
|
+
[Multiple IPs found: ${validIPs.join(", ")}]
|
|
3652
|
+
[Use /target <ip> to select one]
|
|
3653
|
+
`);
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3599
3657
|
if (response.stop_reason === "tool_use") {
|
|
3600
3658
|
return this.executeStep();
|
|
3601
3659
|
}
|
|
@@ -4917,6 +4975,235 @@ var FindingDisplay = ({ block }) => {
|
|
|
4917
4975
|
// src/cli/app.tsx
|
|
4918
4976
|
import { homedir } from "os";
|
|
4919
4977
|
import { join as join6 } from "path";
|
|
4978
|
+
|
|
4979
|
+
// src/cli/utils/keyboard-listener.ts
|
|
4980
|
+
import { EventEmitter as EventEmitter7 } from "events";
|
|
4981
|
+
import * as readline2 from "readline";
|
|
4982
|
+
var KeyboardListener = class extends EventEmitter7 {
|
|
4983
|
+
isListening = false;
|
|
4984
|
+
isPaused = false;
|
|
4985
|
+
stdin = process.stdin;
|
|
4986
|
+
originalRawMode;
|
|
4987
|
+
preInputBuffer = "";
|
|
4988
|
+
constructor() {
|
|
4989
|
+
super();
|
|
4990
|
+
this.handleKeypress = this.handleKeypress.bind(this);
|
|
4991
|
+
this.handleData = this.handleData.bind(this);
|
|
4992
|
+
}
|
|
4993
|
+
/**
|
|
4994
|
+
* Start listening for keyboard input in raw mode
|
|
4995
|
+
*/
|
|
4996
|
+
start() {
|
|
4997
|
+
if (this.isListening) return;
|
|
4998
|
+
try {
|
|
4999
|
+
if (this.stdin.isTTY) {
|
|
5000
|
+
this.originalRawMode = this.stdin.isRaw;
|
|
5001
|
+
this.stdin.setRawMode(true);
|
|
5002
|
+
readline2.emitKeypressEvents(this.stdin);
|
|
5003
|
+
this.stdin.on("keypress", this.handleKeypress);
|
|
5004
|
+
this.stdin.resume();
|
|
5005
|
+
this.isListening = true;
|
|
5006
|
+
}
|
|
5007
|
+
} catch {
|
|
5008
|
+
this.stdin.on("data", this.handleData);
|
|
5009
|
+
this.isListening = true;
|
|
5010
|
+
}
|
|
5011
|
+
}
|
|
5012
|
+
/**
|
|
5013
|
+
* Stop listening and restore terminal state
|
|
5014
|
+
*/
|
|
5015
|
+
stop() {
|
|
5016
|
+
if (!this.isListening) return;
|
|
5017
|
+
try {
|
|
5018
|
+
this.stdin.off("keypress", this.handleKeypress);
|
|
5019
|
+
this.stdin.off("data", this.handleData);
|
|
5020
|
+
if (this.stdin.isTTY && this.originalRawMode !== void 0) {
|
|
5021
|
+
this.stdin.setRawMode(this.originalRawMode);
|
|
5022
|
+
}
|
|
5023
|
+
} catch {
|
|
5024
|
+
}
|
|
5025
|
+
this.isListening = false;
|
|
5026
|
+
}
|
|
5027
|
+
/**
|
|
5028
|
+
* Pause listening (for when Ink needs control)
|
|
5029
|
+
*/
|
|
5030
|
+
pause() {
|
|
5031
|
+
if (!this.isListening || this.isPaused) return;
|
|
5032
|
+
try {
|
|
5033
|
+
if (this.stdin.isTTY && this.originalRawMode !== void 0) {
|
|
5034
|
+
this.stdin.setRawMode(this.originalRawMode);
|
|
5035
|
+
}
|
|
5036
|
+
this.isPaused = true;
|
|
5037
|
+
} catch {
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
/**
|
|
5041
|
+
* Resume listening (after Ink releases control)
|
|
5042
|
+
*/
|
|
5043
|
+
resume() {
|
|
5044
|
+
if (!this.isListening || !this.isPaused) return;
|
|
5045
|
+
try {
|
|
5046
|
+
if (this.stdin.isTTY) {
|
|
5047
|
+
this.stdin.setRawMode(true);
|
|
5048
|
+
}
|
|
5049
|
+
this.isPaused = false;
|
|
5050
|
+
} catch {
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
/**
|
|
5054
|
+
* Get the current pre-input buffer
|
|
5055
|
+
*/
|
|
5056
|
+
getPreInputBuffer() {
|
|
5057
|
+
return this.preInputBuffer;
|
|
5058
|
+
}
|
|
5059
|
+
/**
|
|
5060
|
+
* Clear the pre-input buffer
|
|
5061
|
+
*/
|
|
5062
|
+
clearPreInputBuffer() {
|
|
5063
|
+
this.preInputBuffer = "";
|
|
5064
|
+
}
|
|
5065
|
+
/**
|
|
5066
|
+
* Get and clear the pre-input buffer
|
|
5067
|
+
*/
|
|
5068
|
+
consumePreInputBuffer() {
|
|
5069
|
+
const buffer = this.preInputBuffer;
|
|
5070
|
+
this.preInputBuffer = "";
|
|
5071
|
+
return buffer;
|
|
5072
|
+
}
|
|
5073
|
+
/**
|
|
5074
|
+
* Handle keypress events (readline mode)
|
|
5075
|
+
*/
|
|
5076
|
+
handleKeypress(_str, key) {
|
|
5077
|
+
if (this.isPaused) return;
|
|
5078
|
+
if (key.name === "escape") {
|
|
5079
|
+
this.emit("escape" /* ESCAPE */);
|
|
5080
|
+
return;
|
|
5081
|
+
}
|
|
5082
|
+
if (key.ctrl && key.name === "c") {
|
|
5083
|
+
this.emit("ctrl_c" /* CTRL_C */);
|
|
5084
|
+
return;
|
|
5085
|
+
}
|
|
5086
|
+
if (key.name === "return" || key.name === "enter") {
|
|
5087
|
+
if (this.preInputBuffer) {
|
|
5088
|
+
this.emit("line", this.preInputBuffer);
|
|
5089
|
+
}
|
|
5090
|
+
this.emit("enter" /* ENTER */);
|
|
5091
|
+
return;
|
|
5092
|
+
}
|
|
5093
|
+
if (key.name === "backspace") {
|
|
5094
|
+
if (this.preInputBuffer.length > 0) {
|
|
5095
|
+
this.preInputBuffer = this.preInputBuffer.slice(0, -1);
|
|
5096
|
+
}
|
|
5097
|
+
this.emit("backspace" /* BACKSPACE */);
|
|
5098
|
+
return;
|
|
5099
|
+
}
|
|
5100
|
+
if (key.name === "up") {
|
|
5101
|
+
this.emit("up" /* UP */);
|
|
5102
|
+
return;
|
|
5103
|
+
}
|
|
5104
|
+
if (key.name === "down") {
|
|
5105
|
+
this.emit("down" /* DOWN */);
|
|
5106
|
+
return;
|
|
5107
|
+
}
|
|
5108
|
+
if (key.name === "left") {
|
|
5109
|
+
this.emit("left" /* LEFT */);
|
|
5110
|
+
return;
|
|
5111
|
+
}
|
|
5112
|
+
if (key.name === "right") {
|
|
5113
|
+
this.emit("right" /* RIGHT */);
|
|
5114
|
+
return;
|
|
5115
|
+
}
|
|
5116
|
+
if (key.name === "tab") {
|
|
5117
|
+
this.emit("tab" /* TAB */);
|
|
5118
|
+
return;
|
|
5119
|
+
}
|
|
5120
|
+
if (_str && !key.ctrl && !key.meta && _str.length === 1) {
|
|
5121
|
+
const charCode = _str.charCodeAt(0);
|
|
5122
|
+
if (charCode >= 32 && charCode <= 126) {
|
|
5123
|
+
this.preInputBuffer += _str;
|
|
5124
|
+
this.emit("char", _str);
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
/**
|
|
5129
|
+
* Handle raw data events (fallback mode)
|
|
5130
|
+
*/
|
|
5131
|
+
handleData(data) {
|
|
5132
|
+
if (this.isPaused) return;
|
|
5133
|
+
const str = data.toString();
|
|
5134
|
+
for (let i = 0; i < str.length; i++) {
|
|
5135
|
+
const char = str[i];
|
|
5136
|
+
const code = char.charCodeAt(0);
|
|
5137
|
+
if (code === 27) {
|
|
5138
|
+
if (i + 1 < str.length && str[i + 1] === "[") {
|
|
5139
|
+
if (i + 2 < str.length) {
|
|
5140
|
+
const arrow = str[i + 2];
|
|
5141
|
+
switch (arrow) {
|
|
5142
|
+
case "A":
|
|
5143
|
+
this.emit("up" /* UP */);
|
|
5144
|
+
break;
|
|
5145
|
+
case "B":
|
|
5146
|
+
this.emit("down" /* DOWN */);
|
|
5147
|
+
break;
|
|
5148
|
+
case "C":
|
|
5149
|
+
this.emit("right" /* RIGHT */);
|
|
5150
|
+
break;
|
|
5151
|
+
case "D":
|
|
5152
|
+
this.emit("left" /* LEFT */);
|
|
5153
|
+
break;
|
|
5154
|
+
}
|
|
5155
|
+
i += 2;
|
|
5156
|
+
continue;
|
|
5157
|
+
}
|
|
5158
|
+
} else {
|
|
5159
|
+
this.emit("escape" /* ESCAPE */);
|
|
5160
|
+
continue;
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
if (code === 3) {
|
|
5164
|
+
this.emit("ctrl_c" /* CTRL_C */);
|
|
5165
|
+
continue;
|
|
5166
|
+
}
|
|
5167
|
+
if (code === 13 || code === 10) {
|
|
5168
|
+
if (this.preInputBuffer) {
|
|
5169
|
+
this.emit("line", this.preInputBuffer);
|
|
5170
|
+
}
|
|
5171
|
+
this.emit("enter" /* ENTER */);
|
|
5172
|
+
continue;
|
|
5173
|
+
}
|
|
5174
|
+
if (code === 127 || code === 8) {
|
|
5175
|
+
if (this.preInputBuffer.length > 0) {
|
|
5176
|
+
this.preInputBuffer = this.preInputBuffer.slice(0, -1);
|
|
5177
|
+
}
|
|
5178
|
+
this.emit("backspace" /* BACKSPACE */);
|
|
5179
|
+
continue;
|
|
5180
|
+
}
|
|
5181
|
+
if (code === 9) {
|
|
5182
|
+
this.emit("tab" /* TAB */);
|
|
5183
|
+
continue;
|
|
5184
|
+
}
|
|
5185
|
+
if (code >= 32 && code <= 126) {
|
|
5186
|
+
this.preInputBuffer += char;
|
|
5187
|
+
this.emit("char", char);
|
|
5188
|
+
}
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
/**
|
|
5192
|
+
* Check if currently listening
|
|
5193
|
+
*/
|
|
5194
|
+
isActive() {
|
|
5195
|
+
return this.isListening && !this.isPaused;
|
|
5196
|
+
}
|
|
5197
|
+
};
|
|
5198
|
+
var keyboardListenerInstance = null;
|
|
5199
|
+
function getKeyboardListener() {
|
|
5200
|
+
if (!keyboardListenerInstance) {
|
|
5201
|
+
keyboardListenerInstance = new KeyboardListener();
|
|
5202
|
+
}
|
|
5203
|
+
return keyboardListenerInstance;
|
|
5204
|
+
}
|
|
5205
|
+
|
|
5206
|
+
// src/cli/app.tsx
|
|
4920
5207
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
4921
5208
|
var App = ({ autoApprove = false, target }) => {
|
|
4922
5209
|
const { exit } = useApp();
|
|
@@ -4931,12 +5218,19 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4931
5218
|
const [showCommandHints, setShowCommandHints] = useState(false);
|
|
4932
5219
|
const [mode, setMode] = useState("agent");
|
|
4933
5220
|
const [checkpointCount, setCheckpointCount] = useState(0);
|
|
5221
|
+
const [preInputBuffer, setPreInputBuffer] = useState("");
|
|
5222
|
+
const [wasInterrupted, setWasInterrupted] = useState(false);
|
|
4934
5223
|
const [agent] = useState(() => new AutonomousHackingAgent(void 0, { autoApprove }));
|
|
4935
5224
|
const sessionManager2 = getSessionManager();
|
|
4936
5225
|
const approvalManager2 = getApprovalManager({ yoloMode: autoApprove });
|
|
4937
5226
|
const sessionDirRef = useRef(join6(homedir(), ".pentest", "sessions", `session-${Date.now()}`));
|
|
4938
5227
|
const contextManagerRef = useRef(null);
|
|
4939
5228
|
const wireLoggerRef = useRef(null);
|
|
5229
|
+
const keyboardListenerRef = useRef(getKeyboardListener());
|
|
5230
|
+
const isProcessingRef = useRef(false);
|
|
5231
|
+
useEffect(() => {
|
|
5232
|
+
isProcessingRef.current = isProcessing;
|
|
5233
|
+
}, [isProcessing]);
|
|
4940
5234
|
useEffect(() => {
|
|
4941
5235
|
const sessionId = `session-${Date.now()}`;
|
|
4942
5236
|
contextManagerRef.current = new ContextManager2(sessionDirRef.current);
|
|
@@ -4946,7 +5240,7 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4946
5240
|
setCheckpointCount(contextManagerRef.current?.getCheckpoints().length || 0);
|
|
4947
5241
|
}
|
|
4948
5242
|
});
|
|
4949
|
-
import("./auto-update-
|
|
5243
|
+
import("./auto-update-IDSABTT4.js").then(({ checkForUpdateAsync, formatUpdateNotification }) => {
|
|
4950
5244
|
checkForUpdateAsync().then((result) => {
|
|
4951
5245
|
if (result.hasUpdate) {
|
|
4952
5246
|
const notification = formatUpdateNotification(result);
|
|
@@ -4988,6 +5282,60 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
4988
5282
|
setElapsedTime(0);
|
|
4989
5283
|
return duration;
|
|
4990
5284
|
}, []);
|
|
5285
|
+
useEffect(() => {
|
|
5286
|
+
const listener = keyboardListenerRef.current;
|
|
5287
|
+
const handleEscape = () => {
|
|
5288
|
+
if (isProcessingRef.current && !pendingApproval) {
|
|
5289
|
+
agent.pause();
|
|
5290
|
+
stopTimer();
|
|
5291
|
+
setIsProcessing(false);
|
|
5292
|
+
setCurrentStatus("");
|
|
5293
|
+
setWasInterrupted(true);
|
|
5294
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "\u23F8 Interrupted by ESC - Ready for input");
|
|
5295
|
+
const buffered = listener.consumePreInputBuffer();
|
|
5296
|
+
if (buffered) {
|
|
5297
|
+
setInput(buffered);
|
|
5298
|
+
}
|
|
5299
|
+
listener.pause();
|
|
5300
|
+
}
|
|
5301
|
+
};
|
|
5302
|
+
const handleChar = () => {
|
|
5303
|
+
setPreInputBuffer(listener.getPreInputBuffer());
|
|
5304
|
+
};
|
|
5305
|
+
const handleBackspace = () => {
|
|
5306
|
+
setPreInputBuffer(listener.getPreInputBuffer());
|
|
5307
|
+
};
|
|
5308
|
+
listener.on("escape" /* ESCAPE */, handleEscape);
|
|
5309
|
+
listener.on("char", handleChar);
|
|
5310
|
+
listener.on("backspace" /* BACKSPACE */, handleBackspace);
|
|
5311
|
+
return () => {
|
|
5312
|
+
listener.off("escape" /* ESCAPE */, handleEscape);
|
|
5313
|
+
listener.off("char", handleChar);
|
|
5314
|
+
listener.off("backspace" /* BACKSPACE */, handleBackspace);
|
|
5315
|
+
};
|
|
5316
|
+
}, [agent, addMessage, stopTimer, pendingApproval]);
|
|
5317
|
+
useEffect(() => {
|
|
5318
|
+
const listener = keyboardListenerRef.current;
|
|
5319
|
+
if (isProcessing && !pendingApproval) {
|
|
5320
|
+
listener.clearPreInputBuffer();
|
|
5321
|
+
setPreInputBuffer("");
|
|
5322
|
+
listener.start();
|
|
5323
|
+
listener.resume();
|
|
5324
|
+
} else {
|
|
5325
|
+
const buffered = listener.consumePreInputBuffer();
|
|
5326
|
+
if (buffered && !wasInterrupted) {
|
|
5327
|
+
setInput((prev) => prev + buffered);
|
|
5328
|
+
}
|
|
5329
|
+
setPreInputBuffer("");
|
|
5330
|
+
setWasInterrupted(false);
|
|
5331
|
+
listener.pause();
|
|
5332
|
+
}
|
|
5333
|
+
}, [isProcessing, pendingApproval, wasInterrupted]);
|
|
5334
|
+
useEffect(() => {
|
|
5335
|
+
return () => {
|
|
5336
|
+
keyboardListenerRef.current.stop();
|
|
5337
|
+
};
|
|
5338
|
+
}, []);
|
|
4991
5339
|
useEffect(() => {
|
|
4992
5340
|
const banner = `
|
|
4993
5341
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
@@ -5166,13 +5514,20 @@ pentesting v${APP_VERSION}`
|
|
|
5166
5514
|
return;
|
|
5167
5515
|
case CLI_COMMAND.START:
|
|
5168
5516
|
case "s":
|
|
5517
|
+
let startObjective = args.join(" ");
|
|
5518
|
+
const firstArg = args[0];
|
|
5519
|
+
if (firstArg && (firstArg.includes(".") || /^\d+\.\d+\.\d+\.\d+$/.test(firstArg))) {
|
|
5520
|
+
agent.setTarget(firstArg);
|
|
5521
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `Target \u2192 ${firstArg}`);
|
|
5522
|
+
startObjective = args.slice(1).join(" ") || "Perform comprehensive penetration testing";
|
|
5523
|
+
}
|
|
5169
5524
|
if (!agent.getState().target.primary) {
|
|
5170
|
-
addMessage(MESSAGE_TYPE.ERROR, "Set target first: /target <ip>");
|
|
5525
|
+
addMessage(MESSAGE_TYPE.ERROR, "Set target first: /target <ip> or /start <domain>");
|
|
5171
5526
|
return;
|
|
5172
5527
|
}
|
|
5173
5528
|
setIsProcessing(true);
|
|
5174
5529
|
startTimer();
|
|
5175
|
-
const objective =
|
|
5530
|
+
const objective = startObjective || "Perform comprehensive penetration testing";
|
|
5176
5531
|
setCurrentStatus("Initializing...");
|
|
5177
5532
|
addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F680} Starting: ${objective}`);
|
|
5178
5533
|
try {
|
|
@@ -5421,7 +5776,7 @@ pentesting v${APP_VERSION}`
|
|
|
5421
5776
|
return;
|
|
5422
5777
|
case "update":
|
|
5423
5778
|
try {
|
|
5424
|
-
const { checkForUpdate, formatUpdateNotification, doUpdate } = await import("./update-
|
|
5779
|
+
const { checkForUpdate, formatUpdateNotification, doUpdate } = await import("./update-OWR4FHRQ.js");
|
|
5425
5780
|
const result = checkForUpdate(true);
|
|
5426
5781
|
if (result.hasUpdate) {
|
|
5427
5782
|
const notification = formatUpdateNotification(result);
|
|
@@ -5586,17 +5941,27 @@ pentesting v${APP_VERSION}`
|
|
|
5586
5941
|
] }, opt.decision)) }),
|
|
5587
5942
|
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2191\u2193 to select, Enter to confirm, or type /y /n /ya" }) })
|
|
5588
5943
|
] }),
|
|
5589
|
-
isProcessing ? /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
5590
|
-
/* @__PURE__ */
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5944
|
+
isProcessing ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
5945
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
5946
|
+
/* @__PURE__ */ jsx2(Text2, { color: THEME.status.running, children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
|
|
5947
|
+
/* @__PURE__ */ jsxs2(Text2, { color: THEME.text.muted, children: [
|
|
5948
|
+
" ",
|
|
5949
|
+
currentStatus,
|
|
5950
|
+
elapsedTime > 0 && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
5951
|
+
" (",
|
|
5952
|
+
elapsedTime,
|
|
5953
|
+
"s)"
|
|
5954
|
+
] })
|
|
5598
5955
|
] })
|
|
5599
|
-
] })
|
|
5956
|
+
] }),
|
|
5957
|
+
preInputBuffer && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
5958
|
+
/* @__PURE__ */ jsxs2(Text2, { color: THEME.text.accent, children: [
|
|
5959
|
+
"\u2728 ",
|
|
5960
|
+
preInputBuffer
|
|
5961
|
+
] }),
|
|
5962
|
+
/* @__PURE__ */ jsx2(Text2, { color: THEME.text.muted, children: "\u258C" })
|
|
5963
|
+
] }),
|
|
5964
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "ESC to interrupt \u2502 Type ahead to queue input" }) })
|
|
5600
5965
|
] }) : /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
5601
5966
|
showCommandHints && input.startsWith("/") && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: [
|
|
5602
5967
|
"/target <ip>",
|
|
@@ -5639,7 +6004,11 @@ pentesting v${APP_VERSION}`
|
|
|
5639
6004
|
state.currentPhase !== AGENT_STATUS.IDLE && ` ${state.currentPhase} \u2502`
|
|
5640
6005
|
] }),
|
|
5641
6006
|
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
5642
|
-
"
|
|
6007
|
+
"v",
|
|
6008
|
+
APP_VERSION,
|
|
6009
|
+
" \u2502 Ctrl+X mode \u2502 /help \u2502 ",
|
|
6010
|
+
isProcessing ? "ESC interrupt \u2502 " : "",
|
|
6011
|
+
"Ctrl+C ",
|
|
5643
6012
|
isProcessing ? "stop" : "exit"
|
|
5644
6013
|
] })
|
|
5645
6014
|
] })
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
readVersionCache,
|
|
9
9
|
semverTuple,
|
|
10
10
|
writeVersionCache
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-ZC53SMRU.js";
|
|
12
|
+
import "./chunk-FHPP7RP2.js";
|
|
13
13
|
import "./chunk-3RG5ZIWI.js";
|
|
14
14
|
export {
|
|
15
15
|
checkForUpdate,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pentesting",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Autonomous Penetration Testing AI Agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -78,4 +78,4 @@
|
|
|
78
78
|
"tsx": "^4.19.2",
|
|
79
79
|
"typescript": "^5.7.3"
|
|
80
80
|
}
|
|
81
|
-
}
|
|
81
|
+
}
|