pentesting 0.1.8 → 0.1.10
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/index.js +203 -116
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1840,6 +1840,93 @@ async function searchExploits(query) {
|
|
|
1840
1840
|
return searchDuckDuckGo(`${query} site:exploit-db.com OR site:github.com exploit`);
|
|
1841
1841
|
}
|
|
1842
1842
|
|
|
1843
|
+
// src/config/agent-constants.ts
|
|
1844
|
+
var AGENT_STATUS = {
|
|
1845
|
+
IDLE: "idle",
|
|
1846
|
+
RUNNING: "running",
|
|
1847
|
+
PAUSED: "paused",
|
|
1848
|
+
STUCK: "stuck",
|
|
1849
|
+
WAITING_INPUT: "waiting_input",
|
|
1850
|
+
COMPLETED: "completed"
|
|
1851
|
+
};
|
|
1852
|
+
var PHASE_ID = {
|
|
1853
|
+
RECON: "recon",
|
|
1854
|
+
SCAN: "scan",
|
|
1855
|
+
ENUM: "enum",
|
|
1856
|
+
VULN: "vuln",
|
|
1857
|
+
EXPLOIT: "exploit",
|
|
1858
|
+
PRIVESC: "privesc",
|
|
1859
|
+
PIVOT: "pivot",
|
|
1860
|
+
PERSIST: "persist",
|
|
1861
|
+
EXFIL: "exfil",
|
|
1862
|
+
REPORT: "report"
|
|
1863
|
+
};
|
|
1864
|
+
var PHASE_STATUS = {
|
|
1865
|
+
PENDING: "pending",
|
|
1866
|
+
IN_PROGRESS: "in_progress",
|
|
1867
|
+
COMPLETED: "completed",
|
|
1868
|
+
FAILED: "failed",
|
|
1869
|
+
SKIPPED: "skipped"
|
|
1870
|
+
};
|
|
1871
|
+
var THOUGHT_TYPE = {
|
|
1872
|
+
OBSERVATION: "observation",
|
|
1873
|
+
HYPOTHESIS: "hypothesis",
|
|
1874
|
+
PLAN: "plan",
|
|
1875
|
+
ACTION: "action",
|
|
1876
|
+
RESULT: "result",
|
|
1877
|
+
REFLECTION: "reflection",
|
|
1878
|
+
STUCK: "stuck",
|
|
1879
|
+
BREAKTHROUGH: "breakthrough"
|
|
1880
|
+
};
|
|
1881
|
+
var AGENT_EVENT = {
|
|
1882
|
+
// Lifecycle
|
|
1883
|
+
PLUGINS_LOADED: "plugins_loaded",
|
|
1884
|
+
HOOKS_LOADED: "hooks_loaded",
|
|
1885
|
+
COMMANDS_LOADED: "commands_loaded",
|
|
1886
|
+
MCP_SERVER_ADDED: "mcp_server_added",
|
|
1887
|
+
// Execution
|
|
1888
|
+
ITERATION: "iteration",
|
|
1889
|
+
THOUGHT: "thought",
|
|
1890
|
+
RESPONSE: "response",
|
|
1891
|
+
TOOL_CALL: "tool_call",
|
|
1892
|
+
TOOL_RESULT: "tool_result",
|
|
1893
|
+
COMMAND_EXECUTE: "command_execute",
|
|
1894
|
+
// State changes
|
|
1895
|
+
TARGET_SET: "target_set",
|
|
1896
|
+
PHASE_CHANGE: "phase_change",
|
|
1897
|
+
AGENT_SWITCH: "agent_switch",
|
|
1898
|
+
PAUSED: "paused",
|
|
1899
|
+
RESUMED: "resumed",
|
|
1900
|
+
RESET: "reset",
|
|
1901
|
+
// Discoveries
|
|
1902
|
+
FINDING: "finding",
|
|
1903
|
+
CREDENTIAL: "credential",
|
|
1904
|
+
COMPROMISED: "compromised",
|
|
1905
|
+
// Completion
|
|
1906
|
+
COMPLETE: "complete",
|
|
1907
|
+
REPORT: "report",
|
|
1908
|
+
ERROR: "error",
|
|
1909
|
+
HINT_RECEIVED: "hint_received"
|
|
1910
|
+
};
|
|
1911
|
+
var CLI_COMMAND = {
|
|
1912
|
+
HELP: "help",
|
|
1913
|
+
TARGET: "target",
|
|
1914
|
+
START: "start",
|
|
1915
|
+
STOP: "stop",
|
|
1916
|
+
FINDINGS: "findings",
|
|
1917
|
+
CLEAR: "clear",
|
|
1918
|
+
EXIT: "exit"
|
|
1919
|
+
};
|
|
1920
|
+
var MESSAGE_TYPE = {
|
|
1921
|
+
USER: "user",
|
|
1922
|
+
ASSISTANT: "assistant",
|
|
1923
|
+
TOOL: "tool",
|
|
1924
|
+
THINKING: "thinking",
|
|
1925
|
+
ERROR: "error",
|
|
1926
|
+
SYSTEM: "system",
|
|
1927
|
+
RESULT: "result"
|
|
1928
|
+
};
|
|
1929
|
+
|
|
1843
1930
|
// src/core/agent/autonomous-agent.ts
|
|
1844
1931
|
function toContentBlockParam(block) {
|
|
1845
1932
|
switch (block.type) {
|
|
@@ -1923,36 +2010,36 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
|
|
|
1923
2010
|
try {
|
|
1924
2011
|
const agentsDir = new URL("../../../../plugins/pentesting-core/agents", import.meta.url).pathname;
|
|
1925
2012
|
this.pluginAgents = await loadAllAgents(agentsDir);
|
|
1926
|
-
this.emit(
|
|
2013
|
+
this.emit(AGENT_EVENT.PLUGINS_LOADED, { agents: this.pluginAgents.length });
|
|
1927
2014
|
await this.hookExecutor.initialize();
|
|
1928
|
-
this.emit(
|
|
2015
|
+
this.emit(AGENT_EVENT.HOOKS_LOADED);
|
|
1929
2016
|
await this.commandRegistry.initialize();
|
|
1930
|
-
this.emit(
|
|
2017
|
+
this.emit(AGENT_EVENT.COMMANDS_LOADED);
|
|
1931
2018
|
} catch {
|
|
1932
2019
|
}
|
|
1933
2020
|
}
|
|
1934
2021
|
// Add MCP server at runtime
|
|
1935
2022
|
async addMCPServer(name, command, args) {
|
|
1936
2023
|
await this.mcpManager.addServer(name, { command, args });
|
|
1937
|
-
this.emit(
|
|
2024
|
+
this.emit(AGENT_EVENT.MCP_SERVER_ADDED, { name });
|
|
1938
2025
|
}
|
|
1939
2026
|
// Web search capabilities
|
|
1940
2027
|
async webSearch(query) {
|
|
1941
|
-
this.think(
|
|
2028
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Web search: ${query}`);
|
|
1942
2029
|
const results = await searchDuckDuckGo(query);
|
|
1943
|
-
this.think(
|
|
2030
|
+
this.think(THOUGHT_TYPE.RESULT, `Found ${results.length} results`);
|
|
1944
2031
|
return results;
|
|
1945
2032
|
}
|
|
1946
2033
|
async searchForCVE(query) {
|
|
1947
|
-
this.think(
|
|
2034
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `CVE search: ${query}`);
|
|
1948
2035
|
const results = await searchCVE(query);
|
|
1949
|
-
this.think(
|
|
2036
|
+
this.think(THOUGHT_TYPE.RESULT, `Found ${results.length} CVE results`);
|
|
1950
2037
|
return results;
|
|
1951
2038
|
}
|
|
1952
2039
|
async searchForExploits(query) {
|
|
1953
|
-
this.think(
|
|
2040
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Exploit search: ${query}`);
|
|
1954
2041
|
const results = await searchExploits(query);
|
|
1955
|
-
this.think(
|
|
2042
|
+
this.think(THOUGHT_TYPE.RESULT, `Found ${results.length} exploit results`);
|
|
1956
2043
|
return results;
|
|
1957
2044
|
}
|
|
1958
2045
|
// Process slash command
|
|
@@ -1964,8 +2051,8 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
|
|
|
1964
2051
|
return `Unknown command: /${parsed.command}
|
|
1965
2052
|
${await this.commandRegistry.getHelp()}`;
|
|
1966
2053
|
}
|
|
1967
|
-
this.think(
|
|
1968
|
-
this.emit(
|
|
2054
|
+
this.think(THOUGHT_TYPE.PLAN, `Executing command: /${cmd.name}`);
|
|
2055
|
+
this.emit(AGENT_EVENT.COMMAND_EXECUTE, { command: cmd.name, args: parsed.rawArgs });
|
|
1969
2056
|
return cmd.content;
|
|
1970
2057
|
}
|
|
1971
2058
|
// Switch to specialized agent
|
|
@@ -1975,8 +2062,8 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
1975
2062
|
);
|
|
1976
2063
|
if (agent) {
|
|
1977
2064
|
this.currentAgent = agent;
|
|
1978
|
-
this.think(
|
|
1979
|
-
this.emit(
|
|
2065
|
+
this.think(THOUGHT_TYPE.PLAN, `Switching to specialized agent: ${agent.name}`);
|
|
2066
|
+
this.emit(AGENT_EVENT.AGENT_SWITCH, agent);
|
|
1980
2067
|
return true;
|
|
1981
2068
|
}
|
|
1982
2069
|
return false;
|
|
@@ -1988,7 +2075,7 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
1988
2075
|
// ===== State Management =====
|
|
1989
2076
|
createInitialState() {
|
|
1990
2077
|
return {
|
|
1991
|
-
status:
|
|
2078
|
+
status: AGENT_STATUS.IDLE,
|
|
1992
2079
|
target: {
|
|
1993
2080
|
primary: "",
|
|
1994
2081
|
discovered: [],
|
|
@@ -2015,7 +2102,7 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
2015
2102
|
return { ...this.state };
|
|
2016
2103
|
}
|
|
2017
2104
|
getPhaseProgress() {
|
|
2018
|
-
const completed = this.state.phases.filter((p) => p.status ===
|
|
2105
|
+
const completed = this.state.phases.filter((p) => p.status === PHASE_STATUS.COMPLETED).length;
|
|
2019
2106
|
return {
|
|
2020
2107
|
completed,
|
|
2021
2108
|
full: this.state.phases.length,
|
|
@@ -2032,13 +2119,13 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
2032
2119
|
phase: this.state.currentPhase
|
|
2033
2120
|
};
|
|
2034
2121
|
this.state.thoughts.push(thought);
|
|
2035
|
-
this.emit(
|
|
2122
|
+
this.emit(AGENT_EVENT.THOUGHT, thought);
|
|
2036
2123
|
}
|
|
2037
2124
|
// ===== Target Setting =====
|
|
2038
2125
|
setTarget(target) {
|
|
2039
2126
|
this.state.target.primary = target;
|
|
2040
|
-
this.think(
|
|
2041
|
-
this.emit(
|
|
2127
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Target Setting: ${target}`);
|
|
2128
|
+
this.emit(AGENT_EVENT.TARGET_SET, target);
|
|
2042
2129
|
}
|
|
2043
2130
|
// ===== Phase Management =====
|
|
2044
2131
|
getCurrentPhase() {
|
|
@@ -2051,21 +2138,21 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
2051
2138
|
phase.status = status;
|
|
2052
2139
|
if (status === "in_progress" && !phase.startTime) {
|
|
2053
2140
|
phase.startTime = /* @__PURE__ */ new Date();
|
|
2054
|
-
} else if ((status ===
|
|
2141
|
+
} else if ((status === PHASE_STATUS.COMPLETED || status === PHASE_STATUS.FAILED) && !phase.endTime) {
|
|
2055
2142
|
phase.endTime = /* @__PURE__ */ new Date();
|
|
2056
2143
|
}
|
|
2057
|
-
this.emit(
|
|
2058
|
-
this.think(
|
|
2144
|
+
this.emit(AGENT_EVENT.PHASE_CHANGE, { phaseId, oldStatus, newStatus: status });
|
|
2145
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Phase status changed: ${phase.shortName} (${oldStatus} \u2192 ${status})`);
|
|
2059
2146
|
}
|
|
2060
2147
|
}
|
|
2061
2148
|
advanceToNextPhase() {
|
|
2062
2149
|
const currentIndex = this.state.phases.findIndex((p) => p.id === this.state.currentPhase);
|
|
2063
2150
|
if (currentIndex < this.state.phases.length - 1) {
|
|
2064
2151
|
const nextPhase = this.state.phases[currentIndex + 1];
|
|
2065
|
-
this.setPhaseStatus(this.state.currentPhase,
|
|
2152
|
+
this.setPhaseStatus(this.state.currentPhase, PHASE_STATUS.COMPLETED);
|
|
2066
2153
|
this.state.currentPhase = nextPhase.id;
|
|
2067
2154
|
this.setPhaseStatus(nextPhase.id, "in_progress");
|
|
2068
|
-
this.think(
|
|
2155
|
+
this.think(THOUGHT_TYPE.PLAN, `Advancing to next phase: ${nextPhase.shortName}`);
|
|
2069
2156
|
this.resetStuckCounter();
|
|
2070
2157
|
return true;
|
|
2071
2158
|
}
|
|
@@ -2075,16 +2162,16 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
2075
2162
|
checkIfStuck() {
|
|
2076
2163
|
const currentPhase = this.getCurrentPhase();
|
|
2077
2164
|
if (currentPhase.attempts > this.MAX_PHASE_ATTEMPTS) {
|
|
2078
|
-
this.think(
|
|
2165
|
+
this.think(THOUGHT_TYPE.STUCK, `[!] Rabbit hole detected: ${currentPhase.attempts} attempts in ${currentPhase.shortName} phase`);
|
|
2079
2166
|
return true;
|
|
2080
2167
|
}
|
|
2081
2168
|
const timeSinceProgress = Date.now() - this.state.lastProgressTime.getTime();
|
|
2082
2169
|
if (timeSinceProgress > this.STUCK_TIME_THRESHOLD) {
|
|
2083
|
-
this.think(
|
|
2170
|
+
this.think(THOUGHT_TYPE.STUCK, `[!] Rabbit hole detected: No progress for ${Math.round(timeSinceProgress / 6e4)} minutes`);
|
|
2084
2171
|
return true;
|
|
2085
2172
|
}
|
|
2086
2173
|
if (this.state.stuckCounter > this.STUCK_THRESHOLD) {
|
|
2087
|
-
this.think(
|
|
2174
|
+
this.think(THOUGHT_TYPE.STUCK, `[!] Rabbit hole detected: Same pattern ${this.state.stuckCounter} times repeated`);
|
|
2088
2175
|
return true;
|
|
2089
2176
|
}
|
|
2090
2177
|
return false;
|
|
@@ -2103,7 +2190,7 @@ ${await this.commandRegistry.getHelp()}`;
|
|
|
2103
2190
|
}
|
|
2104
2191
|
// ===== Self Reflection =====
|
|
2105
2192
|
async performSelfReflection() {
|
|
2106
|
-
this.think(
|
|
2193
|
+
this.think(THOUGHT_TYPE.REFLECTION, "[reflect] Starting self-reflection...");
|
|
2107
2194
|
const reflectionPrompt = `
|
|
2108
2195
|
${SELF_REFLECTION_PROMPT}
|
|
2109
2196
|
|
|
@@ -2124,7 +2211,7 @@ What went wrong and what different approach should be tried?
|
|
|
2124
2211
|
messages: [{ role: "user", content: reflectionPrompt }]
|
|
2125
2212
|
});
|
|
2126
2213
|
const reflection = response.content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
|
|
2127
|
-
this.think(
|
|
2214
|
+
this.think(THOUGHT_TYPE.REFLECTION, reflection);
|
|
2128
2215
|
return reflection;
|
|
2129
2216
|
}
|
|
2130
2217
|
// ===== Progress Detection =====
|
|
@@ -2133,16 +2220,16 @@ What went wrong and what different approach should be tried?
|
|
|
2133
2220
|
this.state.lastProgressTime = /* @__PURE__ */ new Date();
|
|
2134
2221
|
switch (type) {
|
|
2135
2222
|
case "discovery":
|
|
2136
|
-
this.think(
|
|
2223
|
+
this.think(THOUGHT_TYPE.BREAKTHROUGH, "[target] New target discovered!");
|
|
2137
2224
|
break;
|
|
2138
2225
|
case "credential":
|
|
2139
|
-
this.think(
|
|
2226
|
+
this.think(THOUGHT_TYPE.BREAKTHROUGH, "[cred] Credential obtained!");
|
|
2140
2227
|
break;
|
|
2141
2228
|
case "access":
|
|
2142
|
-
this.think(
|
|
2229
|
+
this.think(THOUGHT_TYPE.BREAKTHROUGH, "[access] Access obtained!");
|
|
2143
2230
|
break;
|
|
2144
2231
|
case "exploit":
|
|
2145
|
-
this.think(
|
|
2232
|
+
this.think(THOUGHT_TYPE.BREAKTHROUGH, "[exploit] Exploit successful!");
|
|
2146
2233
|
this.state.successfulExploits++;
|
|
2147
2234
|
break;
|
|
2148
2235
|
}
|
|
@@ -2156,7 +2243,7 @@ What went wrong and what different approach should be tried?
|
|
|
2156
2243
|
};
|
|
2157
2244
|
this.state.findings.push(newFinding);
|
|
2158
2245
|
this.getCurrentPhase().findings.push(newFinding);
|
|
2159
|
-
this.emit(
|
|
2246
|
+
this.emit(AGENT_EVENT.FINDING, newFinding);
|
|
2160
2247
|
if (finding.severity === "critical" || finding.severity === "high") {
|
|
2161
2248
|
this.recordProgress("discovery");
|
|
2162
2249
|
}
|
|
@@ -2164,55 +2251,55 @@ What went wrong and what different approach should be tried?
|
|
|
2164
2251
|
addCredential(cred) {
|
|
2165
2252
|
this.state.target.credentials.push(cred);
|
|
2166
2253
|
this.recordProgress("credential");
|
|
2167
|
-
this.emit(
|
|
2168
|
-
this.think(
|
|
2254
|
+
this.emit(AGENT_EVENT.CREDENTIAL, cred);
|
|
2255
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Credential obtained: ${cred.type} - ${cred.username || "unknown"}@${cred.source}`);
|
|
2169
2256
|
}
|
|
2170
2257
|
addCompromisedHost(host) {
|
|
2171
2258
|
if (!this.state.target.compromised.includes(host)) {
|
|
2172
2259
|
this.state.target.compromised.push(host);
|
|
2173
2260
|
this.recordProgress("access");
|
|
2174
|
-
this.emit(
|
|
2175
|
-
this.think(
|
|
2261
|
+
this.emit(AGENT_EVENT.COMPROMISED, host);
|
|
2262
|
+
this.think(THOUGHT_TYPE.BREAKTHROUGH, `Host compromised: ${host}`);
|
|
2176
2263
|
}
|
|
2177
2264
|
}
|
|
2178
2265
|
// ===== Main Autonomous Execution Loop =====
|
|
2179
2266
|
async runAutonomous(objective) {
|
|
2180
2267
|
if (!this.state.target.primary) {
|
|
2181
|
-
this.emit(
|
|
2268
|
+
this.emit(AGENT_EVENT.ERROR, new Error("Target not set"));
|
|
2182
2269
|
return;
|
|
2183
2270
|
}
|
|
2184
|
-
this.state.status =
|
|
2271
|
+
this.state.status = AGENT_STATUS.RUNNING;
|
|
2185
2272
|
this.setPhaseStatus("recon", "in_progress");
|
|
2186
2273
|
const mainObjective = objective || `
|
|
2187
2274
|
Target ${this.state.target.primary} - performing full penetration test.
|
|
2188
2275
|
Goal: Deep penetration to obtain root/system privileges, extract internal data, map entire network.
|
|
2189
2276
|
`;
|
|
2190
|
-
this.think(
|
|
2277
|
+
this.think(THOUGHT_TYPE.PLAN, `Autonomous hacking started: ${mainObjective}`);
|
|
2191
2278
|
this.state.history.push({
|
|
2192
2279
|
role: "user",
|
|
2193
2280
|
content: mainObjective
|
|
2194
2281
|
});
|
|
2195
2282
|
let iteration = 0;
|
|
2196
2283
|
const maxIterations = this.config.maxIterations;
|
|
2197
|
-
while (iteration < maxIterations && this.state.status ===
|
|
2284
|
+
while (iteration < maxIterations && this.state.status === AGENT_STATUS.RUNNING) {
|
|
2198
2285
|
iteration++;
|
|
2199
2286
|
this.state.iteration = iteration;
|
|
2200
2287
|
this.getCurrentPhase().attempts++;
|
|
2201
2288
|
this.state.fullAttempts++;
|
|
2202
|
-
this.emit(
|
|
2289
|
+
this.emit(AGENT_EVENT.ITERATION, { current: iteration, max: maxIterations, phase: this.state.currentPhase });
|
|
2203
2290
|
try {
|
|
2204
2291
|
if (this.checkIfStuck()) {
|
|
2205
|
-
this.state.status =
|
|
2292
|
+
this.state.status = AGENT_STATUS.STUCK;
|
|
2206
2293
|
const reflection = await this.performSelfReflection();
|
|
2207
2294
|
const shouldSkip = await this.decideNextAction(reflection);
|
|
2208
2295
|
if (shouldSkip) {
|
|
2209
2296
|
this.setPhaseStatus(this.state.currentPhase, "skipped");
|
|
2210
2297
|
if (!this.advanceToNextPhase()) {
|
|
2211
|
-
this.think(
|
|
2298
|
+
this.think(THOUGHT_TYPE.OBSERVATION, "All phases completed or skipped");
|
|
2212
2299
|
break;
|
|
2213
2300
|
}
|
|
2214
2301
|
}
|
|
2215
|
-
this.state.status =
|
|
2302
|
+
this.state.status = AGENT_STATUS.RUNNING;
|
|
2216
2303
|
this.resetStuckCounter();
|
|
2217
2304
|
continue;
|
|
2218
2305
|
}
|
|
@@ -2220,25 +2307,25 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
2220
2307
|
await this.analyzeResponse(response);
|
|
2221
2308
|
if (this.shouldAdvancePhase()) {
|
|
2222
2309
|
if (!this.advanceToNextPhase()) {
|
|
2223
|
-
this.think(
|
|
2310
|
+
this.think(THOUGHT_TYPE.OBSERVATION, "[done] All phases completed!");
|
|
2224
2311
|
break;
|
|
2225
2312
|
}
|
|
2226
2313
|
}
|
|
2227
2314
|
} catch (error) {
|
|
2228
2315
|
this.state.failedAttempts++;
|
|
2229
|
-
this.think(
|
|
2230
|
-
this.emit(
|
|
2316
|
+
this.think(THOUGHT_TYPE.RESULT, `[-] Error: ${error.message}`);
|
|
2317
|
+
this.emit(AGENT_EVENT.ERROR, error);
|
|
2231
2318
|
await this.attemptRecovery(error);
|
|
2232
2319
|
}
|
|
2233
2320
|
}
|
|
2234
|
-
this.state.status =
|
|
2321
|
+
this.state.status = AGENT_STATUS.COMPLETED;
|
|
2235
2322
|
await this.generateFinalReport();
|
|
2236
|
-
this.emit(
|
|
2323
|
+
this.emit(AGENT_EVENT.COMPLETE, this.getSummary());
|
|
2237
2324
|
}
|
|
2238
2325
|
// ===== Step Execution =====
|
|
2239
2326
|
async executeStep() {
|
|
2240
2327
|
const contextPrompt = this.buildContextPrompt();
|
|
2241
|
-
this.think(
|
|
2328
|
+
this.think(THOUGHT_TYPE.PLAN, "Deciding next action...");
|
|
2242
2329
|
const historyMessages = this.state.history.map(toMessageParam);
|
|
2243
2330
|
const messages = [
|
|
2244
2331
|
...historyMessages,
|
|
@@ -2266,7 +2353,7 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
|
|
|
2266
2353
|
=== Current Status ===
|
|
2267
2354
|
Target: ${this.state.target.primary}
|
|
2268
2355
|
Current phase: ${phase.shortName} (${phase.name})
|
|
2269
|
-
Phase progress: ${this.state.phases.filter((p) => p.status ===
|
|
2356
|
+
Phase progress: ${this.state.phases.filter((p) => p.status === PHASE_STATUS.COMPLETED).length}/${this.state.phases.length}
|
|
2270
2357
|
Compromised hosts: ${this.state.target.compromised.join(", ") || "none"}
|
|
2271
2358
|
|
|
2272
2359
|
=== Discovered Services ===
|
|
@@ -2293,8 +2380,8 @@ Use report_finding tool for important discoveries.
|
|
|
2293
2380
|
if (block.type === "text") {
|
|
2294
2381
|
textResponse += block.text;
|
|
2295
2382
|
contentBlocks.push({ type: "text", text: block.text });
|
|
2296
|
-
this.think(
|
|
2297
|
-
this.emit(
|
|
2383
|
+
this.think(THOUGHT_TYPE.OBSERVATION, block.text.slice(0, 500));
|
|
2384
|
+
this.emit(AGENT_EVENT.RESPONSE, block.text);
|
|
2298
2385
|
} else if (block.type === "tool_use") {
|
|
2299
2386
|
const toolName = block.name;
|
|
2300
2387
|
const toolInput = block.input;
|
|
@@ -2306,15 +2393,15 @@ Use report_finding tool for important discoveries.
|
|
|
2306
2393
|
});
|
|
2307
2394
|
const actionKey = `${toolName}:${JSON.stringify(toolInput).slice(0, 100)}`;
|
|
2308
2395
|
this.trackAction(actionKey);
|
|
2309
|
-
this.think(
|
|
2310
|
-
this.emit(
|
|
2396
|
+
this.think(THOUGHT_TYPE.ACTION, `[tool] Tool execution: ${toolName}`);
|
|
2397
|
+
this.emit(AGENT_EVENT.TOOL_CALL, { id: block.id, name: toolName, input: toolInput });
|
|
2311
2398
|
const result = await executeToolCall(toolName, toolInput);
|
|
2312
2399
|
const resultType = result.success ? "result" : "result";
|
|
2313
2400
|
this.think(
|
|
2314
2401
|
resultType,
|
|
2315
2402
|
result.success ? `[+] ${toolName} Success: ${result.output.slice(0, 200)}...` : `[-] ${toolName} Failed: ${result.error}`
|
|
2316
2403
|
);
|
|
2317
|
-
this.emit(
|
|
2404
|
+
this.emit(AGENT_EVENT.TOOL_RESULT, { id: block.id, name: toolName, result });
|
|
2318
2405
|
this.extractIntelligence(toolName, result);
|
|
2319
2406
|
this.state.history.push({
|
|
2320
2407
|
role: "assistant",
|
|
@@ -2378,14 +2465,14 @@ Use report_finding tool for important discoveries.
|
|
|
2378
2465
|
passwordPatterns.forEach((pattern) => {
|
|
2379
2466
|
const matches = result.output.match(pattern);
|
|
2380
2467
|
if (matches) {
|
|
2381
|
-
this.think(
|
|
2468
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `Potential credentials found: ${matches.slice(0, 3).join(", ")}`);
|
|
2382
2469
|
}
|
|
2383
2470
|
});
|
|
2384
2471
|
}
|
|
2385
2472
|
const cveMatches = result.output.match(/CVE-\d{4}-\d+/gi);
|
|
2386
2473
|
if (cveMatches) {
|
|
2387
2474
|
cveMatches.forEach((cve) => {
|
|
2388
|
-
this.think(
|
|
2475
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `CVE found: ${cve}`);
|
|
2389
2476
|
});
|
|
2390
2477
|
}
|
|
2391
2478
|
if (output.includes("meterpreter") || output.includes("shell session") || output.includes("www-data") || output.includes("uid=")) {
|
|
@@ -2431,11 +2518,11 @@ Use report_finding tool for important discoveries.
|
|
|
2431
2518
|
}
|
|
2432
2519
|
// ===== Recovery Attempt =====
|
|
2433
2520
|
async attemptRecovery(error) {
|
|
2434
|
-
this.think(
|
|
2521
|
+
this.think(THOUGHT_TYPE.REFLECTION, `Attempting recovery: ${error.message}`);
|
|
2435
2522
|
if (error.message.includes("timeout")) {
|
|
2436
|
-
this.think(
|
|
2523
|
+
this.think(THOUGHT_TYPE.PLAN, "Timeout - retrying with shorter command");
|
|
2437
2524
|
} else if (error.message.includes("permission")) {
|
|
2438
|
-
this.think(
|
|
2525
|
+
this.think(THOUGHT_TYPE.PLAN, "Permission error - trying different approach");
|
|
2439
2526
|
}
|
|
2440
2527
|
}
|
|
2441
2528
|
// ===== Final Report Generation =====
|
|
@@ -2480,8 +2567,8 @@ ${this.state.phases.map((p) => `- **${p.shortName}**: ${p.status} (${p.attempts}
|
|
|
2480
2567
|
Based on the findings, the following remediation steps are recommended:
|
|
2481
2568
|
${this.state.findings.filter((f) => f.severity !== "info").map((f) => `- Address: ${f.title}`).join("\n")}
|
|
2482
2569
|
`;
|
|
2483
|
-
this.setPhaseStatus(
|
|
2484
|
-
this.emit(
|
|
2570
|
+
this.setPhaseStatus(PHASE_ID.REPORT, PHASE_STATUS.COMPLETED);
|
|
2571
|
+
this.emit(AGENT_EVENT.REPORT, report);
|
|
2485
2572
|
return report;
|
|
2486
2573
|
}
|
|
2487
2574
|
// ===== Summary =====
|
|
@@ -2499,29 +2586,29 @@ ${this.state.findings.filter((f) => f.severity !== "info").map((f) => `- Address
|
|
|
2499
2586
|
}
|
|
2500
2587
|
// ===== User Hint Processing =====
|
|
2501
2588
|
async processUserHint(hint) {
|
|
2502
|
-
this.think(
|
|
2589
|
+
this.think(THOUGHT_TYPE.OBSERVATION, `User hint: ${hint}`);
|
|
2503
2590
|
this.state.history.push({
|
|
2504
2591
|
role: "user",
|
|
2505
2592
|
content: `[User hint] ${hint}`
|
|
2506
2593
|
});
|
|
2507
2594
|
this.resetStuckCounter();
|
|
2508
|
-
this.emit(
|
|
2595
|
+
this.emit(AGENT_EVENT.HINT_RECEIVED, hint);
|
|
2509
2596
|
}
|
|
2510
2597
|
// ===== Pause/Resume =====
|
|
2511
2598
|
pause() {
|
|
2512
|
-
this.state.status =
|
|
2513
|
-
this.emit(
|
|
2599
|
+
this.state.status = AGENT_STATUS.PAUSED;
|
|
2600
|
+
this.emit(AGENT_EVENT.PAUSED);
|
|
2514
2601
|
}
|
|
2515
2602
|
resume() {
|
|
2516
|
-
if (this.state.status ===
|
|
2517
|
-
this.state.status =
|
|
2518
|
-
this.emit(
|
|
2603
|
+
if (this.state.status === AGENT_STATUS.PAUSED) {
|
|
2604
|
+
this.state.status = AGENT_STATUS.RUNNING;
|
|
2605
|
+
this.emit(AGENT_EVENT.RESUMED);
|
|
2519
2606
|
}
|
|
2520
2607
|
}
|
|
2521
2608
|
// ===== Reset =====
|
|
2522
2609
|
reset() {
|
|
2523
2610
|
this.state = this.createInitialState();
|
|
2524
|
-
this.emit(
|
|
2611
|
+
this.emit(AGENT_EVENT.RESET);
|
|
2525
2612
|
}
|
|
2526
2613
|
};
|
|
2527
2614
|
|
|
@@ -2647,39 +2734,39 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2647
2734
|
return duration;
|
|
2648
2735
|
}, []);
|
|
2649
2736
|
useEffect(() => {
|
|
2650
|
-
addMessage(
|
|
2737
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "Pentesting Agent initialized. Type /help for commands.");
|
|
2651
2738
|
if (target) {
|
|
2652
2739
|
agent.setTarget(target);
|
|
2653
|
-
addMessage(
|
|
2740
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `Target: ${target}`);
|
|
2654
2741
|
}
|
|
2655
|
-
agent.on(
|
|
2656
|
-
setCurrentStatus(content.slice(0, 60));
|
|
2742
|
+
agent.on(AGENT_EVENT.THOUGHT, (thought) => {
|
|
2743
|
+
setCurrentStatus(thought.content.slice(0, 60));
|
|
2657
2744
|
});
|
|
2658
|
-
agent.on(
|
|
2745
|
+
agent.on(AGENT_EVENT.TOOL_CALL, (data) => {
|
|
2659
2746
|
const args = Object.entries(data.input).slice(0, 2).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 30) : "..."}`).join(" ");
|
|
2660
2747
|
setCurrentStatus(`Running ${data.name}...`);
|
|
2661
|
-
addMessage(
|
|
2748
|
+
addMessage(MESSAGE_TYPE.TOOL, `\u25B6 ${data.name} ${args}`);
|
|
2662
2749
|
});
|
|
2663
|
-
agent.on(
|
|
2750
|
+
agent.on(AGENT_EVENT.TOOL_RESULT, (data) => {
|
|
2664
2751
|
const icon = data.result.success ? "\u2713" : "\u2717";
|
|
2665
2752
|
const preview = data.result.output?.slice(0, 100).replace(/\n/g, " ") || "";
|
|
2666
|
-
addMessage(
|
|
2753
|
+
addMessage(MESSAGE_TYPE.RESULT, `${icon} ${preview}`);
|
|
2667
2754
|
});
|
|
2668
|
-
agent.on(
|
|
2669
|
-
setCurrentStatus(`Phase: ${data.phase} (iteration ${data.
|
|
2755
|
+
agent.on(AGENT_EVENT.ITERATION, (data) => {
|
|
2756
|
+
setCurrentStatus(`Phase: ${data.phase} (iteration ${data.current})`);
|
|
2670
2757
|
});
|
|
2671
|
-
agent.on(
|
|
2672
|
-
addMessage(
|
|
2758
|
+
agent.on(AGENT_EVENT.FINDING, (finding) => {
|
|
2759
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} [${finding.severity.toUpperCase()}] ${finding.title}`);
|
|
2673
2760
|
});
|
|
2674
|
-
agent.on(
|
|
2761
|
+
agent.on(AGENT_EVENT.COMPLETE, () => {
|
|
2675
2762
|
const duration = stopTimer();
|
|
2676
|
-
addMessage(
|
|
2763
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `\u2713 Complete (${duration}s)`);
|
|
2677
2764
|
setIsProcessing(false);
|
|
2678
2765
|
setCurrentStatus("");
|
|
2679
2766
|
});
|
|
2680
|
-
agent.on(
|
|
2767
|
+
agent.on(AGENT_EVENT.ERROR, (error) => {
|
|
2681
2768
|
stopTimer();
|
|
2682
|
-
addMessage(
|
|
2769
|
+
addMessage(MESSAGE_TYPE.ERROR, error.message);
|
|
2683
2770
|
setIsProcessing(false);
|
|
2684
2771
|
});
|
|
2685
2772
|
return () => {
|
|
@@ -2690,14 +2777,14 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2690
2777
|
const trimmed = value.trim();
|
|
2691
2778
|
if (!trimmed || isProcessing) return;
|
|
2692
2779
|
setInput("");
|
|
2693
|
-
addMessage(
|
|
2780
|
+
addMessage(MESSAGE_TYPE.USER, trimmed);
|
|
2694
2781
|
if (trimmed.startsWith("/")) {
|
|
2695
2782
|
const [cmd, ...args] = trimmed.slice(1).split(" ");
|
|
2696
2783
|
switch (cmd) {
|
|
2697
|
-
case
|
|
2784
|
+
case CLI_COMMAND.HELP:
|
|
2698
2785
|
case "h":
|
|
2699
2786
|
addMessage(
|
|
2700
|
-
|
|
2787
|
+
MESSAGE_TYPE.SYSTEM,
|
|
2701
2788
|
`/target <ip> Set target
|
|
2702
2789
|
/start [goal] Start pentest
|
|
2703
2790
|
/stop Stop operation
|
|
@@ -2706,16 +2793,16 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2706
2793
|
/exit Exit`
|
|
2707
2794
|
);
|
|
2708
2795
|
return;
|
|
2709
|
-
case
|
|
2796
|
+
case CLI_COMMAND.TARGET:
|
|
2710
2797
|
case "t":
|
|
2711
2798
|
if (args[0]) {
|
|
2712
2799
|
agent.setTarget(args[0]);
|
|
2713
|
-
addMessage(
|
|
2800
|
+
addMessage(MESSAGE_TYPE.SYSTEM, `Target \u2192 ${args[0]}`);
|
|
2714
2801
|
} else {
|
|
2715
|
-
addMessage(
|
|
2802
|
+
addMessage(MESSAGE_TYPE.ERROR, "Usage: /target <ip>");
|
|
2716
2803
|
}
|
|
2717
2804
|
return;
|
|
2718
|
-
case
|
|
2805
|
+
case CLI_COMMAND.START:
|
|
2719
2806
|
case "s":
|
|
2720
2807
|
setIsProcessing(true);
|
|
2721
2808
|
startTimer();
|
|
@@ -2724,39 +2811,39 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2724
2811
|
try {
|
|
2725
2812
|
await agent.runAutonomous(objective);
|
|
2726
2813
|
} catch (e) {
|
|
2727
|
-
addMessage(
|
|
2814
|
+
addMessage(MESSAGE_TYPE.ERROR, e instanceof Error ? e.message : String(e));
|
|
2728
2815
|
}
|
|
2729
2816
|
stopTimer();
|
|
2730
2817
|
setIsProcessing(false);
|
|
2731
2818
|
setCurrentStatus("");
|
|
2732
2819
|
return;
|
|
2733
|
-
case
|
|
2820
|
+
case CLI_COMMAND.STOP:
|
|
2734
2821
|
agent.pause();
|
|
2735
2822
|
stopTimer();
|
|
2736
|
-
addMessage(
|
|
2823
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "Stopped.");
|
|
2737
2824
|
setIsProcessing(false);
|
|
2738
2825
|
setCurrentStatus("");
|
|
2739
2826
|
return;
|
|
2740
|
-
case
|
|
2827
|
+
case CLI_COMMAND.FINDINGS:
|
|
2741
2828
|
case "f":
|
|
2742
2829
|
const findings = agent.getState().findings;
|
|
2743
2830
|
if (findings.length === 0) {
|
|
2744
|
-
addMessage(
|
|
2831
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "No findings.");
|
|
2745
2832
|
} else {
|
|
2746
|
-
findings.forEach((f) => addMessage(
|
|
2833
|
+
findings.forEach((f) => addMessage(MESSAGE_TYPE.SYSTEM, `[${f.severity}] ${f.title}`));
|
|
2747
2834
|
}
|
|
2748
2835
|
return;
|
|
2749
|
-
case
|
|
2836
|
+
case CLI_COMMAND.CLEAR:
|
|
2750
2837
|
case "c":
|
|
2751
2838
|
setMessages([]);
|
|
2752
2839
|
return;
|
|
2753
|
-
case
|
|
2840
|
+
case CLI_COMMAND.EXIT:
|
|
2754
2841
|
case "quit":
|
|
2755
2842
|
case "q":
|
|
2756
2843
|
exit();
|
|
2757
2844
|
return;
|
|
2758
2845
|
default:
|
|
2759
|
-
addMessage(
|
|
2846
|
+
addMessage(MESSAGE_TYPE.ERROR, `Unknown: ${cmd}`);
|
|
2760
2847
|
return;
|
|
2761
2848
|
}
|
|
2762
2849
|
}
|
|
@@ -2765,9 +2852,9 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2765
2852
|
setCurrentStatus("Thinking...");
|
|
2766
2853
|
try {
|
|
2767
2854
|
await agent.processUserHint(trimmed);
|
|
2768
|
-
addMessage(
|
|
2855
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "Hint received.");
|
|
2769
2856
|
} catch (e) {
|
|
2770
|
-
addMessage(
|
|
2857
|
+
addMessage(MESSAGE_TYPE.ERROR, e instanceof Error ? e.message : String(e));
|
|
2771
2858
|
}
|
|
2772
2859
|
stopTimer();
|
|
2773
2860
|
setIsProcessing(false);
|
|
@@ -2780,7 +2867,7 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2780
2867
|
stopTimer();
|
|
2781
2868
|
setIsProcessing(false);
|
|
2782
2869
|
setCurrentStatus("");
|
|
2783
|
-
addMessage(
|
|
2870
|
+
addMessage(MESSAGE_TYPE.SYSTEM, "Interrupted.");
|
|
2784
2871
|
} else {
|
|
2785
2872
|
exit();
|
|
2786
2873
|
}
|
|
@@ -2788,15 +2875,15 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
2788
2875
|
});
|
|
2789
2876
|
const getStyle = (type) => {
|
|
2790
2877
|
const styles = {
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2878
|
+
[MESSAGE_TYPE.USER]: { color: THEME.text.accent, prefix: "\u276F" },
|
|
2879
|
+
[MESSAGE_TYPE.ASSISTANT]: { color: THEME.text.primary, prefix: "\u25C8" },
|
|
2880
|
+
[MESSAGE_TYPE.TOOL]: { color: THEME.text.muted, prefix: " ", dim: true },
|
|
2881
|
+
[MESSAGE_TYPE.RESULT]: { color: THEME.text.muted, prefix: " ", dim: true },
|
|
2882
|
+
[MESSAGE_TYPE.THINKING]: { color: THEME.status.running, prefix: "\u25CB" },
|
|
2883
|
+
[MESSAGE_TYPE.ERROR]: { color: THEME.status.error, prefix: "\u2717" },
|
|
2884
|
+
[MESSAGE_TYPE.SYSTEM]: { color: THEME.text.muted, prefix: "\u2022" }
|
|
2798
2885
|
};
|
|
2799
|
-
return styles[type] || styles.
|
|
2886
|
+
return styles[type] || styles[MESSAGE_TYPE.SYSTEM];
|
|
2800
2887
|
};
|
|
2801
2888
|
const state = agent.getState();
|
|
2802
2889
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, children: [
|