pentesting 0.2.4 → 0.2.5

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.
Files changed (3) hide show
  1. package/README.md +5 -0
  2. package/dist/index.js +235 -182
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -29,6 +29,11 @@ export PENTEST_API_KEY=your_api_key
29
29
  export PENTEST_BASE_URL=https://your-api-endpoint.com/v1
30
30
  export PENTEST_MODEL=your-model-name
31
31
 
32
+ export PENTEST_API_KEY="key"
33
+ export PENTEST_BASE_URL="https://api.z.ai/api/anthropic"
34
+ export PENTEST_MODEL="glm-4.7"
35
+
36
+
32
37
  # Run
33
38
  pentesting
34
39
  ```
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import Spinner from "ink-spinner";
12
12
 
13
13
  // src/core/agent/autonomous-agent.ts
14
14
  import Anthropic from "@anthropic-ai/sdk";
15
- import { EventEmitter as EventEmitter3 } from "events";
15
+ import { EventEmitter as EventEmitter4 } from "events";
16
16
 
17
17
  // src/core/prompts/autonomous-prompt.ts
18
18
  var AUTONOMOUS_HACKING_PROMPT = `You are Hacker-Code, an elite autonomous penetration testing AI designed for CTF competitions and professional security assessments. You operate with minimal human intervention, making intelligent decisions, adapting to obstacles, and persistently pursuing objectives until complete system compromise.
@@ -251,6 +251,8 @@ var AGENT_EVENT = {
251
251
  TOOL_CALL: "tool_call",
252
252
  TOOL_RESULT: "tool_result",
253
253
  COMMAND_EXECUTE: "command_execute",
254
+ APPROVAL_NEEDED: "approval_needed",
255
+ TOKEN_USAGE: "token_usage",
254
256
  // State changes
255
257
  TARGET_SET: "target_set",
256
258
  PHASE_CHANGE: "phase_change",
@@ -1374,7 +1376,7 @@ const { chromium } = require('playwright');
1374
1376
  }
1375
1377
 
1376
1378
  // src/config/constants.ts
1377
- var APP_VERSION = "0.2.4";
1379
+ var APP_VERSION = "0.2.5";
1378
1380
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
1379
1381
  var LLM_API_KEY = process.env.PENTEST_API_KEY || process.env.ANTHROPIC_API_KEY || "";
1380
1382
  var LLM_BASE_URL = process.env.PENTEST_BASE_URL || void 0;
@@ -1732,6 +1734,183 @@ function getMCPManager() {
1732
1734
  return mcpManager;
1733
1735
  }
1734
1736
 
1737
+ // src/core/approval/approval-manager.ts
1738
+ import { EventEmitter as EventEmitter3 } from "events";
1739
+ var APPROVAL_EVENT = {
1740
+ REQUEST: "approval_request",
1741
+ RESPONSE: "approval_response",
1742
+ TIMEOUT: "approval_timeout"
1743
+ };
1744
+ var CRITICAL_TOOLS = [
1745
+ "execute_command",
1746
+ "write_file",
1747
+ "delete_file",
1748
+ "modify_file",
1749
+ "send_request",
1750
+ "exploit_execute"
1751
+ ];
1752
+ var HIGH_RISK_PATTERNS = [
1753
+ /rm\s+-rf/i,
1754
+ /mkfs/i,
1755
+ /dd\s+if=/i,
1756
+ /format/i,
1757
+ /shutdown/i,
1758
+ /reboot/i,
1759
+ /kill\s+-9/i,
1760
+ /pkill/i,
1761
+ /iptables/i,
1762
+ /ufw/i,
1763
+ /firewall/i,
1764
+ /passwd/i,
1765
+ /useradd/i,
1766
+ /userdel/i,
1767
+ /chmod\s+777/i,
1768
+ /chown/i,
1769
+ /sudo/i,
1770
+ /su\s+-/i,
1771
+ /nc\s+-e/i,
1772
+ /bash\s+-i/i,
1773
+ /reverse.*shell/i,
1774
+ /bind.*shell/i,
1775
+ /meterpreter/i,
1776
+ /mimikatz/i
1777
+ ];
1778
+ function assessRisk(toolName, toolInput) {
1779
+ const inputStr = JSON.stringify(toolInput).toLowerCase();
1780
+ for (const pattern of HIGH_RISK_PATTERNS) {
1781
+ if (pattern.test(inputStr)) {
1782
+ return "critical";
1783
+ }
1784
+ }
1785
+ if (CRITICAL_TOOLS.includes(toolName)) {
1786
+ return "high";
1787
+ }
1788
+ if (toolName.includes("script") || toolName.includes("exec")) {
1789
+ return "medium";
1790
+ }
1791
+ if (toolName.includes("scan") || toolName.includes("request")) {
1792
+ return "medium";
1793
+ }
1794
+ return "low";
1795
+ }
1796
+ function generateRequestId() {
1797
+ return `approval_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
1798
+ }
1799
+ var ApprovalManager = class extends EventEmitter3 {
1800
+ pendingRequests = /* @__PURE__ */ new Map();
1801
+ autoApprovedTools = /* @__PURE__ */ new Set();
1802
+ autoDeniedTools = /* @__PURE__ */ new Set();
1803
+ yoloMode = false;
1804
+ defaultTimeout = 6e4;
1805
+ // 1 minute
1806
+ constructor(options) {
1807
+ super();
1808
+ this.yoloMode = options?.yoloMode ?? false;
1809
+ this.defaultTimeout = options?.timeout ?? 6e4;
1810
+ }
1811
+ /**
1812
+ * Enable/disable YOLO mode (auto-approve everything)
1813
+ */
1814
+ setYoloMode(enabled) {
1815
+ this.yoloMode = enabled;
1816
+ this.emit("yolo_mode_changed", enabled);
1817
+ }
1818
+ /**
1819
+ * Check if approval is required for a tool call
1820
+ */
1821
+ requiresApproval(toolName, toolInput) {
1822
+ if (this.yoloMode) return false;
1823
+ if (this.autoApprovedTools.has(toolName)) return false;
1824
+ if (this.autoDeniedTools.has(toolName)) return true;
1825
+ const risk = assessRisk(toolName, toolInput);
1826
+ if (risk === "low") return false;
1827
+ return true;
1828
+ }
1829
+ /**
1830
+ * Request approval for a tool call
1831
+ */
1832
+ async requestApproval(toolName, toolInput, reason) {
1833
+ if (this.autoDeniedTools.has(toolName)) {
1834
+ return "deny";
1835
+ }
1836
+ if (this.autoApprovedTools.has(toolName)) {
1837
+ return "approve";
1838
+ }
1839
+ const risk = assessRisk(toolName, toolInput);
1840
+ const request = {
1841
+ id: generateRequestId(),
1842
+ toolName,
1843
+ toolInput,
1844
+ reason: reason || `Tool "${toolName}" requires approval (${risk} risk)`,
1845
+ riskLevel: risk,
1846
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1847
+ };
1848
+ this.pendingRequests.set(request.id, request);
1849
+ this.emit(APPROVAL_EVENT.REQUEST, request);
1850
+ return new Promise((resolve) => {
1851
+ const timeout = setTimeout(() => {
1852
+ this.pendingRequests.delete(request.id);
1853
+ this.emit(APPROVAL_EVENT.TIMEOUT, request.id);
1854
+ resolve("deny");
1855
+ }, this.defaultTimeout);
1856
+ const responseHandler = (response) => {
1857
+ if (response.requestId === request.id) {
1858
+ clearTimeout(timeout);
1859
+ this.pendingRequests.delete(request.id);
1860
+ this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
1861
+ if (response.decision === "approve_always") {
1862
+ this.autoApprovedTools.add(toolName);
1863
+ resolve("approve");
1864
+ } else if (response.decision === "deny_always") {
1865
+ this.autoDeniedTools.add(toolName);
1866
+ resolve("deny");
1867
+ } else {
1868
+ resolve(response.decision);
1869
+ }
1870
+ }
1871
+ };
1872
+ this.on(APPROVAL_EVENT.RESPONSE, responseHandler);
1873
+ });
1874
+ }
1875
+ /**
1876
+ * Respond to an approval request (called by UI)
1877
+ */
1878
+ respond(requestId, decision) {
1879
+ const response = {
1880
+ requestId,
1881
+ decision,
1882
+ respondedAt: (/* @__PURE__ */ new Date()).toISOString()
1883
+ };
1884
+ this.emit(APPROVAL_EVENT.RESPONSE, response);
1885
+ }
1886
+ /**
1887
+ * Get pending requests
1888
+ */
1889
+ getPendingRequests() {
1890
+ return Array.from(this.pendingRequests.values());
1891
+ }
1892
+ /**
1893
+ * Get auto-approved tools
1894
+ */
1895
+ getAutoApprovedTools() {
1896
+ return Array.from(this.autoApprovedTools);
1897
+ }
1898
+ /**
1899
+ * Reset all auto decisions
1900
+ */
1901
+ resetAutoDecisions() {
1902
+ this.autoApprovedTools.clear();
1903
+ this.autoDeniedTools.clear();
1904
+ }
1905
+ };
1906
+ var approvalManager = null;
1907
+ function getApprovalManager(options) {
1908
+ if (!approvalManager) {
1909
+ approvalManager = new ApprovalManager(options);
1910
+ }
1911
+ return approvalManager;
1912
+ }
1913
+
1735
1914
  // src/core/tools/web-search.ts
1736
1915
  import { spawn as spawn4 } from "child_process";
1737
1916
  async function searchDuckDuckGo(query, options = {}) {
@@ -2959,7 +3138,7 @@ var DEFAULT_PHASES = [
2959
3138
  { id: PHASE_ID.EXFIL, name: "Data Exfiltration", shortName: "Exfil", status: PHASE_STATUS.PENDING, attempts: 0 },
2960
3139
  { id: PHASE_ID.REPORT, name: "Reporting", shortName: "Report", status: PHASE_STATUS.PENDING, attempts: 0 }
2961
3140
  ];
2962
- var AutonomousHackingAgent = class extends EventEmitter3 {
3141
+ var AutonomousHackingAgent = class extends EventEmitter4 {
2963
3142
  client;
2964
3143
  state;
2965
3144
  config;
@@ -2970,6 +3149,13 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
2970
3149
  hookExecutor;
2971
3150
  mcpManager;
2972
3151
  contextManager;
3152
+ approvalManager;
3153
+ // Token usage tracking
3154
+ tokenUsage = {
3155
+ input: 0,
3156
+ output: 0,
3157
+ total: 0
3158
+ };
2973
3159
  // Rabbit hole detection settings
2974
3160
  STUCK_THRESHOLD = 5;
2975
3161
  // Same action repeat count
@@ -2988,6 +3174,7 @@ var AutonomousHackingAgent = class extends EventEmitter3 {
2988
3174
  this.hookExecutor = getHookExecutor();
2989
3175
  this.mcpManager = getMCPManager();
2990
3176
  this.contextManager = new ContextManager(this.client);
3177
+ this.approvalManager = getApprovalManager({ yoloMode: config?.autoApprove });
2991
3178
  this.state = this.createInitialState();
2992
3179
  this.initSystems();
2993
3180
  }
@@ -3399,6 +3586,12 @@ Goal: Deep penetration to obtain root/system privileges, extract internal data,
3399
3586
  }
3400
3587
  }
3401
3588
  );
3589
+ if (response.usage) {
3590
+ this.tokenUsage.input += response.usage.input_tokens;
3591
+ this.tokenUsage.output += response.usage.output_tokens;
3592
+ this.tokenUsage.total = this.tokenUsage.input + this.tokenUsage.output;
3593
+ this.emit(AGENT_EVENT.TOKEN_USAGE, this.tokenUsage);
3594
+ }
3402
3595
  return this.processResponse(response);
3403
3596
  }
3404
3597
  buildContextPrompt() {
@@ -3457,6 +3650,29 @@ Use report_finding tool for important discoveries.
3457
3650
  this.think(THOUGHT_TYPE.STUCK, `Tool blocked by hook: ${hookCheck.output}`);
3458
3651
  continue;
3459
3652
  }
3653
+ if (this.approvalManager.requiresApproval(toolName, toolInput)) {
3654
+ const risk = assessRisk(toolName, toolInput);
3655
+ this.emit(AGENT_EVENT.APPROVAL_NEEDED, {
3656
+ id: block.id,
3657
+ toolName,
3658
+ toolInput,
3659
+ riskLevel: risk
3660
+ });
3661
+ const decision = await this.approvalManager.requestApproval(
3662
+ toolName,
3663
+ toolInput,
3664
+ `Executing ${toolName} (${risk} risk)`
3665
+ );
3666
+ if (decision === "deny") {
3667
+ this.think(THOUGHT_TYPE.STUCK, `Tool denied by user: ${toolName}`);
3668
+ this.emit(AGENT_EVENT.TOOL_RESULT, {
3669
+ id: block.id,
3670
+ name: toolName,
3671
+ result: { success: false, output: "Denied by user" }
3672
+ });
3673
+ continue;
3674
+ }
3675
+ }
3460
3676
  const result = await executeToolCall(toolName, toolInput);
3461
3677
  await this.hookExecutor.runPostToolUse(toolName, result.output || "");
3462
3678
  const resultType = result.success ? "result" : "result";
@@ -3833,14 +4049,14 @@ Respond helpfully to the user's message. If they ask to perform security testing
3833
4049
  // src/core/session/session-manager.ts
3834
4050
  import * as fs3 from "fs/promises";
3835
4051
  import * as path3 from "path";
3836
- import { EventEmitter as EventEmitter4 } from "events";
4052
+ import { EventEmitter as EventEmitter5 } from "events";
3837
4053
  var SESSIONS_DIR = ".pentesting/sessions";
3838
4054
  function generateSessionId() {
3839
4055
  const timestamp = Date.now().toString(36);
3840
4056
  const random = Math.random().toString(36).substring(2, 8);
3841
4057
  return `session_${timestamp}_${random}`;
3842
4058
  }
3843
- var SessionManager = class extends EventEmitter4 {
4059
+ var SessionManager = class extends EventEmitter5 {
3844
4060
  sessionsDir;
3845
4061
  currentSession = null;
3846
4062
  constructor(baseDir) {
@@ -4015,183 +4231,6 @@ function getSessionManager() {
4015
4231
  return sessionManager;
4016
4232
  }
4017
4233
 
4018
- // src/core/approval/approval-manager.ts
4019
- import { EventEmitter as EventEmitter5 } from "events";
4020
- var APPROVAL_EVENT = {
4021
- REQUEST: "approval_request",
4022
- RESPONSE: "approval_response",
4023
- TIMEOUT: "approval_timeout"
4024
- };
4025
- var CRITICAL_TOOLS = [
4026
- "execute_command",
4027
- "write_file",
4028
- "delete_file",
4029
- "modify_file",
4030
- "send_request",
4031
- "exploit_execute"
4032
- ];
4033
- var HIGH_RISK_PATTERNS = [
4034
- /rm\s+-rf/i,
4035
- /mkfs/i,
4036
- /dd\s+if=/i,
4037
- /format/i,
4038
- /shutdown/i,
4039
- /reboot/i,
4040
- /kill\s+-9/i,
4041
- /pkill/i,
4042
- /iptables/i,
4043
- /ufw/i,
4044
- /firewall/i,
4045
- /passwd/i,
4046
- /useradd/i,
4047
- /userdel/i,
4048
- /chmod\s+777/i,
4049
- /chown/i,
4050
- /sudo/i,
4051
- /su\s+-/i,
4052
- /nc\s+-e/i,
4053
- /bash\s+-i/i,
4054
- /reverse.*shell/i,
4055
- /bind.*shell/i,
4056
- /meterpreter/i,
4057
- /mimikatz/i
4058
- ];
4059
- function assessRisk(toolName, toolInput) {
4060
- const inputStr = JSON.stringify(toolInput).toLowerCase();
4061
- for (const pattern of HIGH_RISK_PATTERNS) {
4062
- if (pattern.test(inputStr)) {
4063
- return "critical";
4064
- }
4065
- }
4066
- if (CRITICAL_TOOLS.includes(toolName)) {
4067
- return "high";
4068
- }
4069
- if (toolName.includes("script") || toolName.includes("exec")) {
4070
- return "medium";
4071
- }
4072
- if (toolName.includes("scan") || toolName.includes("request")) {
4073
- return "medium";
4074
- }
4075
- return "low";
4076
- }
4077
- function generateRequestId() {
4078
- return `approval_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
4079
- }
4080
- var ApprovalManager = class extends EventEmitter5 {
4081
- pendingRequests = /* @__PURE__ */ new Map();
4082
- autoApprovedTools = /* @__PURE__ */ new Set();
4083
- autoDeniedTools = /* @__PURE__ */ new Set();
4084
- yoloMode = false;
4085
- defaultTimeout = 6e4;
4086
- // 1 minute
4087
- constructor(options) {
4088
- super();
4089
- this.yoloMode = options?.yoloMode ?? false;
4090
- this.defaultTimeout = options?.timeout ?? 6e4;
4091
- }
4092
- /**
4093
- * Enable/disable YOLO mode (auto-approve everything)
4094
- */
4095
- setYoloMode(enabled) {
4096
- this.yoloMode = enabled;
4097
- this.emit("yolo_mode_changed", enabled);
4098
- }
4099
- /**
4100
- * Check if approval is required for a tool call
4101
- */
4102
- requiresApproval(toolName, toolInput) {
4103
- if (this.yoloMode) return false;
4104
- if (this.autoApprovedTools.has(toolName)) return false;
4105
- if (this.autoDeniedTools.has(toolName)) return true;
4106
- const risk = assessRisk(toolName, toolInput);
4107
- if (risk === "low") return false;
4108
- return true;
4109
- }
4110
- /**
4111
- * Request approval for a tool call
4112
- */
4113
- async requestApproval(toolName, toolInput, reason) {
4114
- if (this.autoDeniedTools.has(toolName)) {
4115
- return "deny";
4116
- }
4117
- if (this.autoApprovedTools.has(toolName)) {
4118
- return "approve";
4119
- }
4120
- const risk = assessRisk(toolName, toolInput);
4121
- const request = {
4122
- id: generateRequestId(),
4123
- toolName,
4124
- toolInput,
4125
- reason: reason || `Tool "${toolName}" requires approval (${risk} risk)`,
4126
- riskLevel: risk,
4127
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4128
- };
4129
- this.pendingRequests.set(request.id, request);
4130
- this.emit(APPROVAL_EVENT.REQUEST, request);
4131
- return new Promise((resolve) => {
4132
- const timeout = setTimeout(() => {
4133
- this.pendingRequests.delete(request.id);
4134
- this.emit(APPROVAL_EVENT.TIMEOUT, request.id);
4135
- resolve("deny");
4136
- }, this.defaultTimeout);
4137
- const responseHandler = (response) => {
4138
- if (response.requestId === request.id) {
4139
- clearTimeout(timeout);
4140
- this.pendingRequests.delete(request.id);
4141
- this.removeListener(APPROVAL_EVENT.RESPONSE, responseHandler);
4142
- if (response.decision === "approve_always") {
4143
- this.autoApprovedTools.add(toolName);
4144
- resolve("approve");
4145
- } else if (response.decision === "deny_always") {
4146
- this.autoDeniedTools.add(toolName);
4147
- resolve("deny");
4148
- } else {
4149
- resolve(response.decision);
4150
- }
4151
- }
4152
- };
4153
- this.on(APPROVAL_EVENT.RESPONSE, responseHandler);
4154
- });
4155
- }
4156
- /**
4157
- * Respond to an approval request (called by UI)
4158
- */
4159
- respond(requestId, decision) {
4160
- const response = {
4161
- requestId,
4162
- decision,
4163
- respondedAt: (/* @__PURE__ */ new Date()).toISOString()
4164
- };
4165
- this.emit(APPROVAL_EVENT.RESPONSE, response);
4166
- }
4167
- /**
4168
- * Get pending requests
4169
- */
4170
- getPendingRequests() {
4171
- return Array.from(this.pendingRequests.values());
4172
- }
4173
- /**
4174
- * Get auto-approved tools
4175
- */
4176
- getAutoApprovedTools() {
4177
- return Array.from(this.autoApprovedTools);
4178
- }
4179
- /**
4180
- * Reset all auto decisions
4181
- */
4182
- resetAutoDecisions() {
4183
- this.autoApprovedTools.clear();
4184
- this.autoDeniedTools.clear();
4185
- }
4186
- };
4187
- var approvalManager = null;
4188
- function getApprovalManager(options) {
4189
- if (!approvalManager) {
4190
- approvalManager = new ApprovalManager(options);
4191
- }
4192
- return approvalManager;
4193
- }
4194
-
4195
4234
  // src/config/theme.ts
4196
4235
  var THEME = {
4197
4236
  // Primary backgrounds (dark purple tones)
@@ -4287,6 +4326,7 @@ var App = ({ autoApprove = false, target }) => {
4287
4326
  const [currentStatus, setCurrentStatus] = useState("");
4288
4327
  const [elapsedTime, setElapsedTime] = useState(0);
4289
4328
  const [pendingApproval, setPendingApproval] = useState(null);
4329
+ const [tokenUsage, setTokenUsage] = useState({ input: 0, output: 0, total: 0 });
4290
4330
  const [agent] = useState(() => new AutonomousHackingAgent(void 0, { autoApprove }));
4291
4331
  const sessionManager2 = getSessionManager();
4292
4332
  const approvalManager2 = getApprovalManager({ yoloMode: autoApprove });
@@ -4350,6 +4390,18 @@ var App = ({ autoApprove = false, target }) => {
4350
4390
  agent.on(AGENT_EVENT.CONTEXT_COMPACTED, () => {
4351
4391
  addMessage(MESSAGE_TYPE.SYSTEM, "\u{1F4BE} Context compacted to save tokens");
4352
4392
  });
4393
+ agent.on(AGENT_EVENT.TOKEN_USAGE, (usage) => {
4394
+ setTokenUsage(usage);
4395
+ });
4396
+ agent.on(AGENT_EVENT.APPROVAL_NEEDED, (data) => {
4397
+ setPendingApproval({
4398
+ id: data.id,
4399
+ toolName: data.toolName,
4400
+ riskLevel: data.riskLevel
4401
+ });
4402
+ addMessage(MESSAGE_TYPE.SYSTEM, `\u26A0\uFE0F APPROVAL NEEDED: ${data.toolName} (${data.riskLevel} risk)`);
4403
+ addMessage(MESSAGE_TYPE.SYSTEM, " Type /approve or /deny");
4404
+ });
4353
4405
  agent.on(AGENT_EVENT.COMPLETE, () => {
4354
4406
  const duration = stopTimer();
4355
4407
  addMessage(MESSAGE_TYPE.SYSTEM, `\u2713 Complete (${duration}s)`);
@@ -4622,6 +4674,7 @@ var App = ({ autoApprove = false, target }) => {
4622
4674
  " findings \u2502",
4623
4675
  state.credentials.length,
4624
4676
  " creds \u2502",
4677
+ tokenUsage.total > 0 && `${(tokenUsage.total / 1e3).toFixed(1)}k tokens \u2502`,
4625
4678
  state.currentPhase !== AGENT_STATUS.IDLE && ` ${state.currentPhase} \u2502`
4626
4679
  ] }),
4627
4680
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",