pentesting 0.40.1 → 0.40.2

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 (2) hide show
  1. package/dist/main.js +117 -112
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -305,10 +305,8 @@ var ORPHAN_PROCESS_NAMES = [
305
305
  ];
306
306
 
307
307
  // src/shared/constants/agent.ts
308
- var ID_LENGTH = AGENT_LIMITS.ID_LENGTH;
309
- var ID_RADIX = AGENT_LIMITS.ID_RADIX;
310
308
  var APP_NAME = "Pentest AI";
311
- var APP_VERSION = "0.40.1";
309
+ var APP_VERSION = "0.40.2";
312
310
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
313
311
  var LLM_ROLES = {
314
312
  SYSTEM: "system",
@@ -591,7 +589,7 @@ var DEFAULTS = {
591
589
 
592
590
  // src/engine/process-manager.ts
593
591
  import { spawn as spawn3, execSync as execSync2 } from "child_process";
594
- import { readFileSync as readFileSync2, existsSync as existsSync3, unlinkSync, writeFileSync as writeFileSync3, appendFileSync as appendFileSync2 } from "fs";
592
+ import { readFileSync as readFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3, appendFileSync as appendFileSync2 } from "fs";
595
593
 
596
594
  // src/engine/tools-base.ts
597
595
  import { spawn as spawn2 } from "child_process";
@@ -1520,58 +1518,8 @@ function createTempFile(suffix = "") {
1520
1518
  return join2(tmpdir(), generateTempFilename(suffix));
1521
1519
  }
1522
1520
 
1523
- // src/engine/process-detector.ts
1524
- function detectProcessRole(command) {
1525
- const tags = [];
1526
- let port;
1527
- let role = PROCESS_ROLES.BACKGROUND;
1528
- let isInteractive = false;
1529
- const cmd = command.toLowerCase();
1530
- if (cmd.includes("-lvnp") || cmd.includes("-nlvp") || cmd.includes("-lp") || cmd.includes("nc") && cmd.includes("listen")) {
1531
- tags.push(PROCESS_ROLES.LISTENER);
1532
- role = PROCESS_ROLES.LISTENER;
1533
- isInteractive = true;
1534
- const portMatch = command.match(DETECTION_PATTERNS.LISTENER);
1535
- if (portMatch) port = parseInt(portMatch[1], 10);
1536
- }
1537
- if (cmd.includes("http.server") || cmd.includes("simplehttpserver") || cmd.includes("httpd") || cmd.includes("php -s")) {
1538
- tags.push(PROCESS_ROLES.SERVER);
1539
- role = PROCESS_ROLES.SERVER;
1540
- const portMatch = command.match(DETECTION_PATTERNS.HTTP_SERVER);
1541
- if (portMatch) port = parseInt(portMatch[1], 10);
1542
- if (!port) {
1543
- const genericPort = command.match(DETECTION_PATTERNS.GENERIC_PORT);
1544
- if (genericPort) port = parseInt(genericPort[1], 10);
1545
- else if (cmd.includes("http.server")) port = SYSTEM_LIMITS.WEB_PORT_RANGE.MIN;
1546
- }
1547
- }
1548
- if (cmd.includes("tcpdump") || cmd.includes("tshark")) {
1549
- tags.push(PROCESS_ROLES.SNIFFER);
1550
- role = PROCESS_ROLES.SNIFFER;
1551
- }
1552
- if (cmd.includes("arpspoof") || cmd.includes("dnsspoof") || cmd.includes("ettercap")) {
1553
- tags.push(PROCESS_ROLES.SPOOFER);
1554
- role = PROCESS_ROLES.SPOOFER;
1555
- }
1556
- if (cmd.includes("mitm") || cmd.includes("proxy") || cmd.includes("intercept")) {
1557
- tags.push(PROCESS_ROLES.PROXY);
1558
- role = PROCESS_ROLES.PROXY;
1559
- }
1560
- if (cmd.includes("callback") || cmd.includes("oob")) {
1561
- tags.push(PROCESS_ROLES.CALLBACK);
1562
- role = PROCESS_ROLES.CALLBACK;
1563
- }
1564
- if (cmd.includes("socat") && cmd.includes("listen")) {
1565
- tags.push(PROCESS_ROLES.LISTENER);
1566
- role = PROCESS_ROLES.LISTENER;
1567
- isInteractive = true;
1568
- }
1569
- if (tags.length === 0) tags.push(PROCESS_ROLES.BACKGROUND);
1570
- return { tags, port, role, isInteractive };
1571
- }
1572
- function detectConnection(stdout) {
1573
- return DETECTION_PATTERNS.CONNECTION.some((p) => p.test(stdout));
1574
- }
1521
+ // src/engine/process-cleanup.ts
1522
+ import { unlinkSync } from "fs";
1575
1523
 
1576
1524
  // src/engine/process-tree.ts
1577
1525
  import { execSync } from "child_process";
@@ -1657,9 +1605,99 @@ function killProcessTreeSync(pid, childPids) {
1657
1605
  }
1658
1606
  }
1659
1607
 
1608
+ // src/engine/process-cleanup.ts
1609
+ function syncCleanupAllProcesses(processMap) {
1610
+ for (const [, proc] of processMap) {
1611
+ if (!proc.hasExited) {
1612
+ killProcessTreeSync(proc.pid, proc.childPids);
1613
+ }
1614
+ try {
1615
+ unlinkSync(proc.stdoutFile);
1616
+ } catch {
1617
+ }
1618
+ try {
1619
+ unlinkSync(proc.stderrFile);
1620
+ } catch {
1621
+ }
1622
+ try {
1623
+ unlinkSync(proc.stdinFile);
1624
+ } catch {
1625
+ }
1626
+ }
1627
+ }
1628
+ function registerExitHandlers(processMap) {
1629
+ process.on("exit", () => {
1630
+ syncCleanupAllProcesses(processMap);
1631
+ });
1632
+ process.on("SIGINT", () => {
1633
+ syncCleanupAllProcesses(processMap);
1634
+ processMap.clear();
1635
+ process.exit(EXIT_CODES.SIGINT);
1636
+ });
1637
+ process.on("SIGTERM", () => {
1638
+ syncCleanupAllProcesses(processMap);
1639
+ processMap.clear();
1640
+ process.exit(EXIT_CODES.SIGTERM);
1641
+ });
1642
+ }
1643
+
1644
+ // src/engine/process-detector.ts
1645
+ function detectProcessRole(command) {
1646
+ const tags = [];
1647
+ let port;
1648
+ let role = PROCESS_ROLES.BACKGROUND;
1649
+ let isInteractive = false;
1650
+ const cmd = command.toLowerCase();
1651
+ if (cmd.includes("-lvnp") || cmd.includes("-nlvp") || cmd.includes("-lp") || cmd.includes("nc") && cmd.includes("listen")) {
1652
+ tags.push(PROCESS_ROLES.LISTENER);
1653
+ role = PROCESS_ROLES.LISTENER;
1654
+ isInteractive = true;
1655
+ const portMatch = command.match(DETECTION_PATTERNS.LISTENER);
1656
+ if (portMatch) port = parseInt(portMatch[1], 10);
1657
+ }
1658
+ if (cmd.includes("http.server") || cmd.includes("simplehttpserver") || cmd.includes("httpd") || cmd.includes("php -s")) {
1659
+ tags.push(PROCESS_ROLES.SERVER);
1660
+ role = PROCESS_ROLES.SERVER;
1661
+ const portMatch = command.match(DETECTION_PATTERNS.HTTP_SERVER);
1662
+ if (portMatch) port = parseInt(portMatch[1], 10);
1663
+ if (!port) {
1664
+ const genericPort = command.match(DETECTION_PATTERNS.GENERIC_PORT);
1665
+ if (genericPort) port = parseInt(genericPort[1], 10);
1666
+ else if (cmd.includes("http.server")) port = SYSTEM_LIMITS.WEB_PORT_RANGE.MIN;
1667
+ }
1668
+ }
1669
+ if (cmd.includes("tcpdump") || cmd.includes("tshark")) {
1670
+ tags.push(PROCESS_ROLES.SNIFFER);
1671
+ role = PROCESS_ROLES.SNIFFER;
1672
+ }
1673
+ if (cmd.includes("arpspoof") || cmd.includes("dnsspoof") || cmd.includes("ettercap")) {
1674
+ tags.push(PROCESS_ROLES.SPOOFER);
1675
+ role = PROCESS_ROLES.SPOOFER;
1676
+ }
1677
+ if (cmd.includes("mitm") || cmd.includes("proxy") || cmd.includes("intercept")) {
1678
+ tags.push(PROCESS_ROLES.PROXY);
1679
+ role = PROCESS_ROLES.PROXY;
1680
+ }
1681
+ if (cmd.includes("callback") || cmd.includes("oob")) {
1682
+ tags.push(PROCESS_ROLES.CALLBACK);
1683
+ role = PROCESS_ROLES.CALLBACK;
1684
+ }
1685
+ if (cmd.includes("socat") && cmd.includes("listen")) {
1686
+ tags.push(PROCESS_ROLES.LISTENER);
1687
+ role = PROCESS_ROLES.LISTENER;
1688
+ isInteractive = true;
1689
+ }
1690
+ if (tags.length === 0) tags.push(PROCESS_ROLES.BACKGROUND);
1691
+ return { tags, port, role, isInteractive };
1692
+ }
1693
+ function detectConnection(stdout) {
1694
+ return DETECTION_PATTERNS.CONNECTION.some((p) => p.test(stdout));
1695
+ }
1696
+
1660
1697
  // src/engine/process-manager.ts
1661
1698
  var backgroundProcesses = /* @__PURE__ */ new Map();
1662
1699
  var cleanupDone = false;
1700
+ registerExitHandlers(backgroundProcesses);
1663
1701
  var processEventLog = [];
1664
1702
  function logEvent(processId, event, detail) {
1665
1703
  processEventLog.push({ timestamp: Date.now(), processId, event, detail });
@@ -1833,15 +1871,15 @@ async function stopBackgroundProcess(processId) {
1833
1871
  await killProcessTree(proc.pid, proc.childPids);
1834
1872
  }
1835
1873
  try {
1836
- unlinkSync(proc.stdoutFile);
1874
+ unlinkSync2(proc.stdoutFile);
1837
1875
  } catch {
1838
1876
  }
1839
1877
  try {
1840
- unlinkSync(proc.stderrFile);
1878
+ unlinkSync2(proc.stderrFile);
1841
1879
  } catch {
1842
1880
  }
1843
1881
  try {
1844
- unlinkSync(proc.stdinFile);
1882
+ unlinkSync2(proc.stdinFile);
1845
1883
  } catch {
1846
1884
  }
1847
1885
  logEvent(processId, PROCESS_EVENTS.STOPPED, `Stopped ${proc.role} (PID:${proc.pid}, children:${proc.childPids.length})`);
@@ -1939,15 +1977,15 @@ async function cleanupAllProcesses() {
1939
1977
  }
1940
1978
  for (const [, proc] of backgroundProcesses) {
1941
1979
  try {
1942
- unlinkSync(proc.stdoutFile);
1980
+ unlinkSync2(proc.stdoutFile);
1943
1981
  } catch {
1944
1982
  }
1945
1983
  try {
1946
- unlinkSync(proc.stderrFile);
1984
+ unlinkSync2(proc.stderrFile);
1947
1985
  } catch {
1948
1986
  }
1949
1987
  try {
1950
- unlinkSync(proc.stdinFile);
1988
+ unlinkSync2(proc.stdinFile);
1951
1989
  } catch {
1952
1990
  }
1953
1991
  }
@@ -2033,39 +2071,6 @@ Ports In Use: ${ports.join(", ")}`);
2033
2071
  }
2034
2072
  return lines.join("\n");
2035
2073
  }
2036
- function syncCleanupAllProcesses() {
2037
- for (const [, proc] of backgroundProcesses) {
2038
- if (!proc.hasExited) {
2039
- killProcessTreeSync(proc.pid, proc.childPids);
2040
- }
2041
- try {
2042
- unlinkSync(proc.stdoutFile);
2043
- } catch {
2044
- }
2045
- try {
2046
- unlinkSync(proc.stderrFile);
2047
- } catch {
2048
- }
2049
- try {
2050
- unlinkSync(proc.stdinFile);
2051
- } catch {
2052
- }
2053
- }
2054
- }
2055
- process.on("exit", () => {
2056
- syncCleanupAllProcesses();
2057
- });
2058
- process.on("SIGINT", () => {
2059
- syncCleanupAllProcesses();
2060
- backgroundProcesses.clear();
2061
- process.exit(EXIT_CODES.SIGINT);
2062
- });
2063
- process.on("SIGTERM", () => {
2064
- syncCleanupAllProcesses();
2065
- backgroundProcesses.clear();
2066
- process.exit(EXIT_CODES.SIGTERM);
2067
- });
2068
- var stopProcess = stopBackgroundProcess;
2069
2074
 
2070
2075
  // src/engine/state-serializer.ts
2071
2076
  var StateSerializer = class {
@@ -2852,7 +2857,7 @@ var SharedState = class {
2852
2857
  }
2853
2858
  addMissionChecklistItems(items) {
2854
2859
  for (const text of items) {
2855
- const id = generateId(ID_RADIX, ID_LENGTH);
2860
+ const id = generateId(AGENT_LIMITS.ID_RADIX, AGENT_LIMITS.ID_LENGTH);
2856
2861
  this.data.missionChecklist.push({ id, text, isCompleted: false });
2857
2862
  }
2858
2863
  }
@@ -2872,7 +2877,7 @@ var SharedState = class {
2872
2877
  this.data.engagement.scope = scope;
2873
2878
  } else {
2874
2879
  this.data.engagement = {
2875
- id: generateId(ID_RADIX, ID_LENGTH),
2880
+ id: generateId(AGENT_LIMITS.ID_RADIX, AGENT_LIMITS.ID_LENGTH),
2876
2881
  name: DEFAULTS.ENGAGEMENT_NAME,
2877
2882
  client: DEFAULTS.ENGAGEMENT_CLIENT,
2878
2883
  scope,
@@ -2932,7 +2937,7 @@ var SharedState = class {
2932
2937
  }
2933
2938
  // --- TODO Management ---
2934
2939
  addTodo(content, priority = PRIORITIES.MEDIUM) {
2935
- const id = generateId(ID_RADIX, ID_LENGTH);
2940
+ const id = generateId(AGENT_LIMITS.ID_RADIX, AGENT_LIMITS.ID_LENGTH);
2936
2941
  const item = { id, content, status: TODO_STATUSES.PENDING, priority };
2937
2942
  this.data.todo.push(item);
2938
2943
  return id;
@@ -2950,7 +2955,7 @@ var SharedState = class {
2950
2955
  // --- Logs & Phase ---
2951
2956
  logAction(action) {
2952
2957
  this.data.actionLog.push({
2953
- id: generateId(ID_RADIX, ID_LENGTH),
2958
+ id: generateId(AGENT_LIMITS.ID_RADIX, AGENT_LIMITS.ID_LENGTH),
2954
2959
  timestamp: Date.now(),
2955
2960
  ...action
2956
2961
  });
@@ -4130,7 +4135,7 @@ Next steps:
4130
4135
  }
4131
4136
  case "stop": {
4132
4137
  if (!processId) return { success: false, output: "", error: "Missing process_id" };
4133
- return stopProcess(processId);
4138
+ return stopBackgroundProcess(processId);
4134
4139
  }
4135
4140
  case "stop_all": {
4136
4141
  const procs = listBackgroundProcesses();
@@ -4464,7 +4469,7 @@ Detail: ${detail}
4464
4469
  const affected = p.affected || [];
4465
4470
  const validation = validateFinding(evidence, severity);
4466
4471
  state.addFinding({
4467
- id: generateId(ID_RADIX, ID_LENGTH),
4472
+ id: generateId(AGENT_LIMITS.ID_RADIX, AGENT_LIMITS.ID_LENGTH),
4468
4473
  title,
4469
4474
  severity,
4470
4475
  affected,
@@ -4659,7 +4664,7 @@ async function installPlaywright() {
4659
4664
 
4660
4665
  // src/engine/tools/web-browser-script.ts
4661
4666
  import { spawn as spawn5 } from "child_process";
4662
- import { writeFileSync as writeFileSync5, unlinkSync as unlinkSync2 } from "fs";
4667
+ import { writeFileSync as writeFileSync5, unlinkSync as unlinkSync3 } from "fs";
4663
4668
  import { join as join5 } from "path";
4664
4669
  import { tmpdir as tmpdir2 } from "os";
4665
4670
  function safeJsString(str) {
@@ -4695,7 +4700,7 @@ function runPlaywrightScript(script, timeout, scriptPrefix) {
4695
4700
  child.stderr.on("data", (data) => stderr += data);
4696
4701
  child.on("close", (code) => {
4697
4702
  try {
4698
- unlinkSync2(scriptPath);
4703
+ unlinkSync3(scriptPath);
4699
4704
  } catch {
4700
4705
  }
4701
4706
  if (code !== 0) {
@@ -4722,7 +4727,7 @@ function runPlaywrightScript(script, timeout, scriptPrefix) {
4722
4727
  });
4723
4728
  child.on("error", (err) => {
4724
4729
  try {
4725
- unlinkSync2(scriptPath);
4730
+ unlinkSync3(scriptPath);
4726
4731
  } catch {
4727
4732
  }
4728
4733
  resolve({
@@ -6469,7 +6474,7 @@ Combine with packet_sniff to capture intercepted traffic.`,
6469
6474
  });
6470
6475
  await new Promise((r) => setTimeout(r, (duration + NETWORK_CONFIG.WAIT_BUFFER_SECONDS) * 1e3));
6471
6476
  const output = getProcessOutput(proc.id);
6472
- await stopProcess(proc.id);
6477
+ await stopBackgroundProcess(proc.id);
6473
6478
  await runCommand(NETWORK_COMMANDS.IP_FORWARD_DISABLE);
6474
6479
  return {
6475
6480
  success: true,
@@ -6523,7 +6528,7 @@ Requires root/sudo privileges.`,
6523
6528
  });
6524
6529
  await new Promise((r) => setTimeout(r, (duration + NETWORK_CONFIG.WAIT_BUFFER_SECONDS) * 1e3));
6525
6530
  const captureOutput = getProcessOutput(proc.id);
6526
- await stopProcess(proc.id);
6531
+ await stopBackgroundProcess(proc.id);
6527
6532
  let output = `Packet Capture Results:
6528
6533
  Interface: ${iface}
6529
6534
  Filter: ${filter || "none"}
@@ -6610,7 +6615,7 @@ ${spoofIp} *.${domain}
6610
6615
  });
6611
6616
  await new Promise((r) => setTimeout(r, (duration + NETWORK_CONFIG.WAIT_BUFFER_SECONDS) * 1e3));
6612
6617
  const output = getProcessOutput(proc.id);
6613
- await stopProcess(proc.id);
6618
+ await stopBackgroundProcess(proc.id);
6614
6619
  return {
6615
6620
  success: true,
6616
6621
  output: `DNS Spoofing Results:
@@ -6662,7 +6667,7 @@ Combine with arp_spoof for transparent proxying.`,
6662
6667
  });
6663
6668
  await new Promise((r) => setTimeout(r, (duration + NETWORK_CONFIG.WAIT_BUFFER_SECONDS) * 1e3));
6664
6669
  const procOutput = getProcessOutput(proc.id);
6665
- await stopProcess(proc.id);
6670
+ await stopBackgroundProcess(proc.id);
6666
6671
  let flowSummary = "";
6667
6672
  const readFlows = await runCommand(`mitmdump -r ${outputFile} -n 2>&1 | head -50`);
6668
6673
  if (readFlows.success && readFlows.output) {
@@ -6731,7 +6736,7 @@ This is a high-level tool that combines tcpdump capture with protocol analysis.`
6731
6736
  description: `Traffic intercept on ${target}`
6732
6737
  });
6733
6738
  await new Promise((r) => setTimeout(r, (duration + NETWORK_CONFIG.WAIT_BUFFER_SECONDS) * 1e3));
6734
- await stopProcess(proc.id);
6739
+ await stopBackgroundProcess(proc.id);
6735
6740
  let output = `Traffic Interception Report
6736
6741
  ${"=".repeat(50)}
6737
6742
  Target: ${target}
@@ -7063,7 +7068,7 @@ If killOrphans is true, also cleans up child processes whose parent has died.`,
7063
7068
  async execute(params) {
7064
7069
  const results = [];
7065
7070
  if (params.processId) {
7066
- const procResult = await stopProcess(params.processId);
7071
+ const procResult = await stopBackgroundProcess(params.processId);
7067
7072
  results.push(`Stopped ${params.processId}: ${procResult.success ? "success" : "failed"}`);
7068
7073
  if (procResult.output) {
7069
7074
  results.push(procResult.output.slice(0, PROCESS_OUTPUT_TRUNCATION_LIMIT));
@@ -7971,7 +7976,7 @@ var __filename2 = fileURLToPath3(import.meta.url);
7971
7976
  var __dirname3 = dirname4(__filename2);
7972
7977
 
7973
7978
  // src/engine/state-persistence.ts
7974
- import { writeFileSync as writeFileSync6, readFileSync as readFileSync4, existsSync as existsSync6, readdirSync, statSync, unlinkSync as unlinkSync3 } from "fs";
7979
+ import { writeFileSync as writeFileSync6, readFileSync as readFileSync4, existsSync as existsSync6, readdirSync, statSync, unlinkSync as unlinkSync4 } from "fs";
7975
7980
  import { join as join9 } from "path";
7976
7981
  function saveState(state) {
7977
7982
  const sessionsDir = WORKSPACE.SESSIONS;
@@ -8006,7 +8011,7 @@ function pruneOldSessions(sessionsDir) {
8006
8011
  })).sort((a, b) => b.mtime - a.mtime);
8007
8012
  const toDelete = sessionFiles.slice(AGENT_LIMITS.MAX_SESSION_FILES);
8008
8013
  for (const file of toDelete) {
8009
- unlinkSync3(file.path);
8014
+ unlinkSync4(file.path);
8010
8015
  }
8011
8016
  } catch {
8012
8017
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.40.1",
3
+ "version": "0.40.2",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",