pentesting 0.7.12 → 0.7.15

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 +31 -17
  2. package/dist/index.js +71 -37
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -222,29 +222,43 @@ agent.abort(); // Complete stop
222
222
 
223
223
  ---
224
224
 
225
- ## 🐳 Docker Environment
225
+ ## 🐳 Docker Toolkit (Auto-Managed)
226
+
227
+ Pentesting automatically manages a Docker container with 50+ pre-installed tools.
228
+
229
+ ### Automatic Setup
230
+
231
+ **No manual Docker setup required!** When you run a command that needs tools like `nmap` or `rustscan`:
232
+
233
+ 1. Pentesting checks if tool exists locally
234
+ 2. If not, it automatically pulls `agnusdei1207/pentesting-tools:latest`
235
+ 3. Starts container `pentesting-tools` with host network
236
+ 4. Executes command via `docker exec`
237
+
238
+ ### Manual Docker Control
226
239
 
227
240
  ```bash
228
- # Pull pre-built toolkit (50+ tools)
229
- docker pull agnusdei1207/pentesting-tools:latest
241
+ # Force all commands through Docker
242
+ export PENTESTING_DOCKER=1
230
243
 
231
- # Run with host network (required for target access)
232
- docker run -d --name pentesting-tools --network host \
233
- -v $(pwd)/workspace:/pentest \
234
- agnusdei1207/pentesting-tools:latest
244
+ # Use custom container name
245
+ export PENTESTING_CONTAINER=my-pentest-container
235
246
 
236
- # Execute tools
237
- docker exec -it pentesting-tools nmap -sCV 10.0.0.1
247
+ # Manual pull (optional - auto-pulled on first use)
248
+ docker pull agnusdei1207/pentesting-tools:latest
238
249
  ```
239
250
 
240
- ### Included Tools
241
- - **Network**: nmap, rustscan, masscan, netcat
242
- - **Web**: ffuf, nikto, sqlmap, httpx
243
- - **Discovery**: subfinder, amass, nuclei
244
- - **Service**: snmpwalk, nbtscan, hydra, smbclient
245
- - **AD/Windows**: impacket, crackmapexec
246
- - **Database**: mysql-client, postgresql-client, redis-tools
247
- - **Utilities**: curl, wget, jq, python3
251
+ ### Included Tools (50+)
252
+
253
+ | Category | Tools |
254
+ |----------|-------|
255
+ | **Network** | nmap, rustscan, masscan, netcat, tcpdump |
256
+ | **Web** | ffuf, nikto, sqlmap, httpx, whatweb |
257
+ | **Discovery** | subfinder, amass, nuclei, dnsrecon |
258
+ | **Bruteforce** | hydra, hashcat, john |
259
+ | **AD/Windows** | impacket, crackmapexec, smbclient |
260
+ | **Database** | mysql-client, postgresql-client, redis-tools |
261
+ | **Utilities** | curl, wget, jq, python3, go |
248
262
 
249
263
  ---
250
264
 
package/dist/index.js CHANGED
@@ -1317,8 +1317,10 @@ import { promisify } from "util";
1317
1317
  import * as fs from "fs/promises";
1318
1318
  import * as path from "path";
1319
1319
  var execAsync = promisify(exec);
1320
+ var DOCKER_IMAGE = "agnusdei1207/pentesting-tools:latest";
1320
1321
  var DOCKER_CONTAINER = process.env.PENTESTING_CONTAINER || "pentesting-tools";
1321
1322
  var FORCE_DOCKER = process.env.PENTESTING_DOCKER === "1";
1323
+ var dockerStarted = false;
1322
1324
  var DOCKER_TOOLS = [
1323
1325
  // Network scanning
1324
1326
  TOOL_NAME.RUSTSCAN,
@@ -1392,14 +1394,37 @@ var DOCKER_TOOLS = [
1392
1394
  TOOL_NAME.CHECK_SUDO,
1393
1395
  TOOL_NAME.FIND_SUID
1394
1396
  ];
1395
- async function isDockerAvailable() {
1397
+ async function ensureDockerContainer() {
1398
+ if (dockerStarted) return true;
1396
1399
  try {
1397
- await execAsync(`docker inspect ${DOCKER_CONTAINER} --format='{{.State.Running}}'`);
1400
+ const { stdout } = await execAsync(`docker inspect ${DOCKER_CONTAINER} --format='{{.State.Running}}'`);
1401
+ if (stdout.trim() === "true") {
1402
+ dockerStarted = true;
1403
+ return true;
1404
+ }
1405
+ await execAsync(`docker start ${DOCKER_CONTAINER}`);
1406
+ dockerStarted = true;
1407
+ console.log(`[Docker] Started container: ${DOCKER_CONTAINER}`);
1398
1408
  return true;
1399
1409
  } catch {
1400
- return false;
1410
+ try {
1411
+ console.log(`[Docker] Pulling and starting ${DOCKER_IMAGE}...`);
1412
+ await execAsync(`docker run -d --name ${DOCKER_CONTAINER} --network host ${DOCKER_IMAGE}`, {
1413
+ timeout: 12e4
1414
+ // 2 min timeout for pull
1415
+ });
1416
+ dockerStarted = true;
1417
+ console.log(`[Docker] Container ready: ${DOCKER_CONTAINER}`);
1418
+ return true;
1419
+ } catch (err) {
1420
+ console.error(`[Docker] Failed to start container: ${err}`);
1421
+ return false;
1422
+ }
1401
1423
  }
1402
1424
  }
1425
+ async function isDockerAvailable() {
1426
+ return await ensureDockerContainer();
1427
+ }
1403
1428
  async function commandExists(cmd) {
1404
1429
  try {
1405
1430
  await execAsync(`which ${cmd}`);
@@ -4885,11 +4910,20 @@ Use report_finding tool for important discoveries.
4885
4910
  toolInput,
4886
4911
  riskLevel: risk
4887
4912
  });
4888
- const decision = await this.approvalManager.requestApproval(
4889
- toolName,
4890
- toolInput,
4891
- `Executing ${toolName} (${risk} risk)`
4892
- );
4913
+ const decision = await new Promise((resolve) => {
4914
+ const handler = (response2) => {
4915
+ if (response2.requestId === block.id) {
4916
+ this.approvalManager.removeListener("approval_response", handler);
4917
+ if (response2.decision === "approve_always") {
4918
+ this.approvalManager.autoApprovedTools?.add(toolName);
4919
+ resolve("approve");
4920
+ } else {
4921
+ resolve(response2.decision);
4922
+ }
4923
+ }
4924
+ };
4925
+ this.approvalManager.on("approval_response", handler);
4926
+ });
4893
4927
  if (decision === "deny") {
4894
4928
  this.think(THOUGHT_TYPE.STUCK, `Tool denied by user: ${toolName}`);
4895
4929
  this.emit(AGENT_EVENT.TOOL_RESULT, {
@@ -6512,6 +6546,7 @@ var App = ({ autoApprove = false, target }) => {
6512
6546
  const [checkpointCount, setCheckpointCount] = useState(0);
6513
6547
  const [preInputBuffer, setPreInputBuffer] = useState("");
6514
6548
  const [wasInterrupted, setWasInterrupted] = useState(false);
6549
+ const [spinnerHue, setSpinnerHue] = useState(0);
6515
6550
  const [, forceUpdate] = useState(0);
6516
6551
  const [agent] = useState(() => new AutonomousHackingAgent(void 0, { autoApprove }));
6517
6552
  const sessionManager2 = getSessionManager();
@@ -6564,6 +6599,7 @@ var App = ({ autoApprove = false, target }) => {
6564
6599
  startTimeRef.current = Date.now();
6565
6600
  timerRef.current = setInterval(() => {
6566
6601
  setElapsedTime(Math.floor((Date.now() - startTimeRef.current) / 100) / 10);
6602
+ setSpinnerHue((h) => (h + 5) % 360);
6567
6603
  }, 100);
6568
6604
  }, []);
6569
6605
  const stopTimer = useCallback(() => {
@@ -6630,19 +6666,17 @@ var App = ({ autoApprove = false, target }) => {
6630
6666
  };
6631
6667
  }, []);
6632
6668
  useEffect(() => {
6633
- addMessage(MESSAGE_TYPE.SYSTEM, `
6634
- \u{1F680} /target <ip> \u2192 /start [goal] | /help for commands
6635
- \u26A0\uFE0F For authorized penetration testing only. Unauthorized use is illegal.`);
6669
+ addMessage(MESSAGE_TYPE.SYSTEM, `/target <ip> \u2192 /start [goal] | /help for commands`);
6636
6670
  if (autoApprove) {
6637
- addMessage(MESSAGE_TYPE.SYSTEM, "\u26A0\uFE0F YOLO Mode: Auto-approving all tool executions");
6671
+ addMessage(MESSAGE_TYPE.SYSTEM, "YOLO Mode: Auto-approving all tool executions");
6638
6672
  }
6639
6673
  if (target) {
6640
6674
  agent.setTarget(target);
6641
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} Target: ${target}`);
6675
+ addMessage(MESSAGE_TYPE.SYSTEM, `Target: ${target}`);
6642
6676
  }
6643
6677
  onTargetChange((newTarget) => {
6644
6678
  agent.setTarget(newTarget);
6645
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} Target \u2192 ${newTarget}`);
6679
+ addMessage(MESSAGE_TYPE.SYSTEM, `Target \u2192 ${newTarget}`);
6646
6680
  forceUpdate((n) => n + 1);
6647
6681
  });
6648
6682
  agent.on(AGENT_EVENT.TARGET_SET, () => {
@@ -6650,6 +6684,9 @@ var App = ({ autoApprove = false, target }) => {
6650
6684
  });
6651
6685
  agent.on(AGENT_EVENT.THOUGHT, (thought) => {
6652
6686
  setCurrentStatus(thought.content.slice(0, 60));
6687
+ if (thought.type === "thinking" || thought.type === "reasoning") {
6688
+ addMessage(MESSAGE_TYPE.SYSTEM, `[${thought.type}] ${thought.content.slice(0, 200)}`);
6689
+ }
6653
6690
  wireLoggerRef.current?.contentPart(thought.content, thought.type === "thinking");
6654
6691
  });
6655
6692
  agent.on(AGENT_EVENT.TOOL_CALL, (data) => {
@@ -6670,12 +6707,12 @@ var App = ({ autoApprove = false, target }) => {
6670
6707
  wireLoggerRef.current?.stepBegin(data.current);
6671
6708
  });
6672
6709
  agent.on(AGENT_EVENT.FINDING, (finding) => {
6673
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} [${finding.severity.toUpperCase()}] ${finding.title}`);
6710
+ addMessage(MESSAGE_TYPE.SYSTEM, `[${finding.severity.toUpperCase()}] ${finding.title}`);
6674
6711
  wireLoggerRef.current?.statusUpdate({ event: "finding", ...finding });
6675
6712
  forceUpdate((n) => n + 1);
6676
6713
  });
6677
6714
  agent.on(AGENT_EVENT.PHASE_CHANGE, (data) => {
6678
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F4CD} Phase: ${data.phaseId}`);
6715
+ addMessage(MESSAGE_TYPE.SYSTEM, `Phase: ${data.phaseId}`);
6679
6716
  wireLoggerRef.current?.statusUpdate({ event: "phase_change", phase: data.phaseId });
6680
6717
  forceUpdate((n) => n + 1);
6681
6718
  });
@@ -6697,7 +6734,7 @@ var App = ({ autoApprove = false, target }) => {
6697
6734
  toolInput: data.toolInput,
6698
6735
  riskLevel: data.riskLevel
6699
6736
  });
6700
- addMessage(MESSAGE_TYPE.SYSTEM, `\u26A0\uFE0F APPROVAL NEEDED: ${data.toolName} (${data.riskLevel} risk)`);
6737
+ addMessage(MESSAGE_TYPE.SYSTEM, `APPROVAL NEEDED: ${data.toolName} (${data.riskLevel} risk)`);
6701
6738
  const inputPreview = Object.entries(data.toolInput).slice(0, 2).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 40) : JSON.stringify(v).slice(0, 40)}`).join(", ");
6702
6739
  if (inputPreview) {
6703
6740
  addMessage(MESSAGE_TYPE.SYSTEM, ` Args: ${inputPreview}`);
@@ -6722,7 +6759,7 @@ var App = ({ autoApprove = false, target }) => {
6722
6759
  toolInput: req.toolInput,
6723
6760
  riskLevel: req.riskLevel
6724
6761
  });
6725
- addMessage(MESSAGE_TYPE.SYSTEM, `\u26A0\uFE0F APPROVAL NEEDED: ${req.toolName} (${req.riskLevel} risk)`);
6762
+ addMessage(MESSAGE_TYPE.SYSTEM, `APPROVAL NEEDED: ${req.toolName} (${req.riskLevel} risk)`);
6726
6763
  addMessage(MESSAGE_TYPE.SYSTEM, ` ${req.reason}`);
6727
6764
  addMessage(MESSAGE_TYPE.SYSTEM, " /y = approve, /n = deny, /ya = always approve");
6728
6765
  });
@@ -6814,7 +6851,7 @@ pentesting v${APP_VERSION}`
6814
6851
  const allTargets = agent.getAllTargets();
6815
6852
  if (allTargets.length === 0) {
6816
6853
  addMessage(MESSAGE_TYPE.SYSTEM, `
6817
- \u{1F3AF} No targets set
6854
+ No targets set
6818
6855
 
6819
6856
  Usage:
6820
6857
  /target <domain|ip> Set primary target
@@ -6827,7 +6864,7 @@ Usage:
6827
6864
  const targetList = allTargets.map(
6828
6865
  (t) => t === primary ? ` \u2605 ${t} (primary)` : ` ${t}`
6829
6866
  ).join("\n");
6830
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} Targets:
6867
+ addMessage(MESSAGE_TYPE.SYSTEM, `Targets:
6831
6868
  ${targetList}`);
6832
6869
  }
6833
6870
  return;
@@ -6852,7 +6889,7 @@ ${targetList}`);
6852
6889
  const list = targets.map(
6853
6890
  (t, i) => t === primary ? ` ${i + 1}. \u2605 ${t}` : ` ${i + 1}. ${t}`
6854
6891
  ).join("\n");
6855
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} Targets (${targets.length}):
6892
+ addMessage(MESSAGE_TYPE.SYSTEM, `Targets (${targets.length}):
6856
6893
  ${list}`);
6857
6894
  }
6858
6895
  break;
@@ -6884,7 +6921,7 @@ ${list}`);
6884
6921
  break;
6885
6922
  default:
6886
6923
  agent.setTarget(subCmd);
6887
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F3AF} Target \u2192 ${subCmd}`);
6924
+ addMessage(MESSAGE_TYPE.SYSTEM, `Target \u2192 ${subCmd}`);
6888
6925
  }
6889
6926
  return;
6890
6927
  case CLI_COMMAND.START:
@@ -6898,7 +6935,7 @@ ${list}`);
6898
6935
  setIsProcessing(true);
6899
6936
  startTimer();
6900
6937
  const allObjective = args.slice(1).join(" ") || "Perform comprehensive penetration testing";
6901
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F680} Starting multi-target attack on ${allTargets.length} targets`);
6938
+ addMessage(MESSAGE_TYPE.SYSTEM, `Starting multi-target attack on ${allTargets.length} targets`);
6902
6939
  for (let i = 0; i < allTargets.length; i++) {
6903
6940
  const currentTarget = allTargets[i];
6904
6941
  if (agent.shouldStop()) {
@@ -6911,7 +6948,7 @@ ${list}`);
6911
6948
  forceUpdate((n) => n + 1);
6912
6949
  try {
6913
6950
  const session = await sessionManager2.createSession(allObjective, currentTarget);
6914
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F4C1} Session: ${session.id}`);
6951
+ addMessage(MESSAGE_TYPE.SYSTEM, `Session: ${session.id}`);
6915
6952
  agent.resume();
6916
6953
  await agent.runAutonomous(allObjective);
6917
6954
  } catch (e) {
@@ -6939,10 +6976,10 @@ ${list}`);
6939
6976
  startTimer();
6940
6977
  const objective = startObjective || "Perform comprehensive penetration testing";
6941
6978
  setCurrentStatus("Initializing...");
6942
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F680} Starting: ${objective}`);
6979
+ addMessage(MESSAGE_TYPE.SYSTEM, `Starting: ${objective}`);
6943
6980
  try {
6944
6981
  const session = await sessionManager2.createSession(objective, agent.getState().target.primary);
6945
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F4C1} Session: ${session.id}`);
6982
+ addMessage(MESSAGE_TYPE.SYSTEM, `Session: ${session.id}`);
6946
6983
  await agent.runAutonomous(objective);
6947
6984
  } catch (e) {
6948
6985
  addMessage(MESSAGE_TYPE.ERROR, e instanceof Error ? e.message : String(e));
@@ -7000,7 +7037,7 @@ ${list}`);
7000
7037
  case "yolo":
7001
7038
  const newYoloState = !approvalManager2.getAutoApprovedTools().length;
7002
7039
  approvalManager2.setYoloMode(newYoloState);
7003
- addMessage(MESSAGE_TYPE.SYSTEM, newYoloState ? "\u26A0\uFE0F YOLO mode ON - Auto-approving all tools" : "\u{1F512} YOLO mode OFF - Manual approval required");
7040
+ addMessage(MESSAGE_TYPE.SYSTEM, newYoloState ? "YOLO mode ON - Auto-approving all tools" : "\u{1F512} YOLO mode OFF - Manual approval required");
7004
7041
  return;
7005
7042
  case CLI_COMMAND.CLEAR:
7006
7043
  case "c":
@@ -7054,7 +7091,7 @@ ${list}`);
7054
7091
  const cp = await contextManagerRef.current.checkpoint(description);
7055
7092
  setCheckpointCount((prev) => prev + 1);
7056
7093
  wireLoggerRef.current?.statusUpdate({ action: "checkpoint", id: cp.id });
7057
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F4CD} Checkpoint #${cp.id} created${description ? `: ${description}` : ""}`);
7094
+ addMessage(MESSAGE_TYPE.SYSTEM, `Checkpoint #${cp.id} created${description ? `: ${description}` : ""}`);
7058
7095
  } else {
7059
7096
  addMessage(MESSAGE_TYPE.ERROR, "Context manager not initialized");
7060
7097
  }
@@ -7130,7 +7167,7 @@ ${list}`);
7130
7167
  if (cps.length === 0) {
7131
7168
  addMessage(MESSAGE_TYPE.SYSTEM, "No checkpoints");
7132
7169
  } else {
7133
- addMessage(MESSAGE_TYPE.SYSTEM, `\u{1F4CD} ${cps.length} Checkpoints:`);
7170
+ addMessage(MESSAGE_TYPE.SYSTEM, `${cps.length} Checkpoints:`);
7134
7171
  cps.forEach((cp) => {
7135
7172
  const time = new Date(cp.timestamp).toLocaleTimeString();
7136
7173
  addMessage(MESSAGE_TYPE.SYSTEM, ` #${cp.id} @ ${time} (${cp.messageCount} msgs)${cp.description ? ` - ${cp.description}` : ""}`);
@@ -7338,7 +7375,7 @@ ${list}`);
7338
7375
  } }) }),
7339
7376
  pendingApproval && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginBottom: 1, children: [
7340
7377
  /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
7341
- "\u26A0\uFE0F APPROVAL NEEDED: ",
7378
+ "APPROVAL NEEDED: ",
7342
7379
  pendingApproval.toolName,
7343
7380
  " (",
7344
7381
  pendingApproval.riskLevel,
@@ -7353,7 +7390,7 @@ ${list}`);
7353
7390
  ] }),
7354
7391
  isProcessing ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
7355
7392
  /* @__PURE__ */ jsxs2(Box2, { children: [
7356
- /* @__PURE__ */ jsx2(Text2, { color: THEME.status.running, children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
7393
+ /* @__PURE__ */ jsx2(Text2, { color: `hsl(${spinnerHue}, 70%, 60%)`, children: /* @__PURE__ */ jsx2(Spinner, { type: "dots" }) }),
7357
7394
  /* @__PURE__ */ jsxs2(Text2, { color: THEME.text.muted, children: [
7358
7395
  " ",
7359
7396
  currentStatus,
@@ -7365,10 +7402,7 @@ ${list}`);
7365
7402
  ] })
7366
7403
  ] }),
7367
7404
  preInputBuffer && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
7368
- /* @__PURE__ */ jsxs2(Text2, { color: THEME.text.accent, children: [
7369
- "\u2728 ",
7370
- preInputBuffer
7371
- ] }),
7405
+ /* @__PURE__ */ jsx2(Text2, { color: THEME.text.accent, children: preInputBuffer }),
7372
7406
  /* @__PURE__ */ jsx2(Text2, { color: THEME.text.muted, children: "\u258C" })
7373
7407
  ] }),
7374
7408
  /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "ESC to interrupt \u2502 Type ahead to queue input" }) })
@@ -7385,7 +7419,7 @@ ${list}`);
7385
7419
  pendingApproval ? "/y /n /ya" : ""
7386
7420
  ].filter((cmd) => cmd && cmd.toLowerCase().includes(input.toLowerCase().slice(1))).slice(0, 5).join(" \u2502 ") }) }),
7387
7421
  /* @__PURE__ */ jsxs2(Box2, { children: [
7388
- /* @__PURE__ */ jsx2(Text2, { color: mode === "agent" ? THEME.status.success : "yellow", children: mode === "agent" ? "\u2728 " : "$ " }),
7422
+ /* @__PURE__ */ jsx2(Text2, { color: mode === "agent" ? THEME.status.success : "yellow", children: mode === "agent" ? "" : "$ " }),
7389
7423
  /* @__PURE__ */ jsx2(
7390
7424
  TextInput,
7391
7425
  {
@@ -7406,7 +7440,7 @@ ${list}`);
7406
7440
  state.target.discovered.length > 1 && ` (+${state.target.discovered.length - 1})`,
7407
7441
  state.findings.length > 0 && ` \u2502 ${state.findings.length} findings`,
7408
7442
  state.credentials.length > 0 && ` \u2502 ${state.credentials.length} creds`,
7409
- tokenUsage.total > 0 && ` \u2502 ${(tokenUsage.total / 1e3).toFixed(0)}k`
7443
+ tokenUsage.total > 0 && ` \u2502 ${(tokenUsage.total / 1e3).toFixed(0)}k tok`
7410
7444
  ] }),
7411
7445
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
7412
7446
  isProcessing && currentStatus && `${currentStatus.slice(0, 40)} \u2502 `,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.7.12",
3
+ "version": "0.7.15",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",