pentesting 0.52.1 → 0.53.0

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/main.js CHANGED
@@ -349,7 +349,7 @@ var ORPHAN_PROCESS_NAMES = [
349
349
 
350
350
  // src/shared/constants/agent.ts
351
351
  var APP_NAME = "Pentest AI";
352
- var APP_VERSION = "0.52.1";
352
+ var APP_VERSION = "0.53.0";
353
353
  var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
354
354
  var LLM_ROLES = {
355
355
  SYSTEM: "system",
@@ -931,7 +931,6 @@ var DEFAULT_DIRECTIVE_FOCUS = PHASES.RECON;
931
931
  var ALLOWED_BINARIES = /* @__PURE__ */ new Set([
932
932
  // Network scanning
933
933
  "nmap",
934
- "masscan",
935
934
  "rustscan",
936
935
  // Web scanning
937
936
  "ffuf",
@@ -1557,7 +1556,6 @@ function extractBinary(command) {
1557
1556
  import { spawn } from "child_process";
1558
1557
  var TOOL_PACKAGE_MAP = {
1559
1558
  "nmap": { apt: "nmap", brew: "nmap" },
1560
- "masscan": { apt: "masscan", brew: "masscan" },
1561
1559
  "rustscan": { apt: "rustscan", brew: "rustscan" },
1562
1560
  "ffuf": { apt: "ffuf", brew: "ffuf" },
1563
1561
  "gobuster": { apt: "gobuster", brew: "gobuster" },
@@ -1732,6 +1730,91 @@ async function installTool(toolName, eventEmitter, inputHandler) {
1732
1730
  });
1733
1731
  }
1734
1732
 
1733
+ // src/shared/utils/config.ts
1734
+ var ENV_KEYS = {
1735
+ API_KEY: "PENTEST_API_KEY",
1736
+ BASE_URL: "PENTEST_BASE_URL",
1737
+ MODEL: "PENTEST_MODEL",
1738
+ SEARCH_API_KEY: "SEARCH_API_KEY",
1739
+ SEARCH_API_URL: "SEARCH_API_URL",
1740
+ THINKING: "PENTEST_THINKING",
1741
+ THINKING_BUDGET: "PENTEST_THINKING_BUDGET",
1742
+ TOR: "PENTEST_TOR"
1743
+ };
1744
+ var DEFAULT_SEARCH_API_URL = "https://api.search.brave.com/res/v1/web/search";
1745
+ var DEFAULT_MODEL = "glm-4.7";
1746
+ function getApiKey() {
1747
+ return process.env[ENV_KEYS.API_KEY] || "";
1748
+ }
1749
+ function getBaseUrl() {
1750
+ return process.env[ENV_KEYS.BASE_URL] || void 0;
1751
+ }
1752
+ function getModel() {
1753
+ return process.env[ENV_KEYS.MODEL] || "";
1754
+ }
1755
+ function getSearchApiKey() {
1756
+ if (process.env[ENV_KEYS.SEARCH_API_KEY]) {
1757
+ return process.env[ENV_KEYS.SEARCH_API_KEY];
1758
+ }
1759
+ return process.env[ENV_KEYS.API_KEY];
1760
+ }
1761
+ function getSearchApiUrl() {
1762
+ return process.env[ENV_KEYS.SEARCH_API_URL] || DEFAULT_SEARCH_API_URL;
1763
+ }
1764
+ function isZaiProvider() {
1765
+ const baseUrl = getBaseUrl() || "";
1766
+ return baseUrl.includes("z.ai");
1767
+ }
1768
+ function isThinkingEnabled() {
1769
+ return process.env[ENV_KEYS.THINKING] === "true";
1770
+ }
1771
+ function getThinkingBudget() {
1772
+ const val = parseInt(process.env[ENV_KEYS.THINKING_BUDGET] || "", 10);
1773
+ return isNaN(val) ? 8e3 : Math.max(1024, val);
1774
+ }
1775
+ var TOR_PROXY = {
1776
+ /** SOCKS5 proxy host (Tor daemon listens here) */
1777
+ SOCKS_HOST: "127.0.0.1",
1778
+ /** SOCKS5 proxy port */
1779
+ SOCKS_PORT: 9050,
1780
+ /** Shell wrapper command for proxying CLI tools */
1781
+ WRAPPER_CMD: "proxychains4",
1782
+ /** Flags for the wrapper command (-q = quiet, no banners) */
1783
+ WRAPPER_FLAGS: "-q"
1784
+ };
1785
+ function isTorEnabled() {
1786
+ return process.env[ENV_KEYS.TOR] === "true";
1787
+ }
1788
+ function wrapCommandForTor(command) {
1789
+ if (!isTorEnabled()) return command;
1790
+ return `${TOR_PROXY.WRAPPER_CMD} ${TOR_PROXY.WRAPPER_FLAGS} ${command}`;
1791
+ }
1792
+ function getTorBrowserArgs() {
1793
+ if (!isTorEnabled()) return [];
1794
+ return [`--proxy-server=socks5://${TOR_PROXY.SOCKS_HOST}:${TOR_PROXY.SOCKS_PORT}`];
1795
+ }
1796
+ function validateRequiredConfig() {
1797
+ const errors = [];
1798
+ if (!getApiKey()) {
1799
+ errors.push(
1800
+ `[config] PENTEST_API_KEY is required.
1801
+ Export it before running:
1802
+ export PENTEST_API_KEY=your_api_key
1803
+ For z.ai: get your key at https://api.z.ai`
1804
+ );
1805
+ }
1806
+ const budgetRaw = process.env[ENV_KEYS.THINKING_BUDGET];
1807
+ if (budgetRaw !== void 0 && budgetRaw !== "") {
1808
+ const parsed = parseInt(budgetRaw, 10);
1809
+ if (isNaN(parsed) || parsed < 1024) {
1810
+ errors.push(
1811
+ `[config] PENTEST_THINKING_BUDGET must be an integer \u2265 1024 (got: "${budgetRaw}")`
1812
+ );
1813
+ }
1814
+ }
1815
+ return errors;
1816
+ }
1817
+
1735
1818
  // src/engine/tools-base.ts
1736
1819
  var globalEventEmitter = null;
1737
1820
  function setCommandEventEmitter(emitter) {
@@ -1801,7 +1884,8 @@ async function executeCommandOnce(command, options = {}) {
1801
1884
  type: COMMAND_EVENT_TYPES.COMMAND_START,
1802
1885
  message: `Executing: ${command.slice(0, DISPLAY_LIMITS.COMMAND_PREVIEW)}${command.length > DISPLAY_LIMITS.COMMAND_PREVIEW ? "..." : ""}`
1803
1886
  });
1804
- const child = spawn2("sh", ["-c", command], {
1887
+ const execCommand = wrapCommandForTor(command);
1888
+ const child = spawn2("sh", ["-c", execCommand], {
1805
1889
  timeout,
1806
1890
  env: { ...process.env, ...options.env },
1807
1891
  cwd: options.cwd
@@ -2118,12 +2202,13 @@ function startBackgroundProcess(command, options = {}) {
2118
2202
  const stderrFile = createTempFile(FILE_EXTENSIONS.STDERR);
2119
2203
  const stdinFile = createTempFile(FILE_EXTENSIONS.STDIN);
2120
2204
  const { tags, port, role, isInteractive } = detectProcessRole(command);
2205
+ const torCommand = wrapCommandForTor(command);
2121
2206
  let wrappedCmd;
2122
2207
  if (isInteractive) {
2123
2208
  writeFileSync3(stdinFile, "", "utf-8");
2124
- wrappedCmd = `tail -f ${stdinFile} | ${command} > ${stdoutFile} 2> ${stderrFile}`;
2209
+ wrappedCmd = `tail -f ${stdinFile} | ${torCommand} > ${stdoutFile} 2> ${stderrFile}`;
2125
2210
  } else {
2126
- wrappedCmd = `${command} > ${stdoutFile} 2> ${stderrFile}`;
2211
+ wrappedCmd = `${torCommand} > ${stdoutFile} 2> ${stderrFile}`;
2127
2212
  }
2128
2213
  const child = spawn3("sh", ["-c", wrappedCmd], {
2129
2214
  detached: true,
@@ -4288,7 +4373,6 @@ var NOISE_CLASSIFICATION = {
4288
4373
  "dns_spoof",
4289
4374
  "traffic_intercept",
4290
4375
  "nmap",
4291
- "masscan",
4292
4376
  "nuclei",
4293
4377
  "nikto"
4294
4378
  ],
@@ -5594,69 +5678,6 @@ ${formatValidation(validation)}${rawOverride !== void 0 ? ` [confidence overridd
5594
5678
  // src/engine/tools/intel-utils.ts
5595
5679
  import { execFileSync } from "child_process";
5596
5680
 
5597
- // src/shared/utils/config.ts
5598
- var ENV_KEYS = {
5599
- API_KEY: "PENTEST_API_KEY",
5600
- BASE_URL: "PENTEST_BASE_URL",
5601
- MODEL: "PENTEST_MODEL",
5602
- SEARCH_API_KEY: "SEARCH_API_KEY",
5603
- SEARCH_API_URL: "SEARCH_API_URL",
5604
- THINKING: "PENTEST_THINKING",
5605
- THINKING_BUDGET: "PENTEST_THINKING_BUDGET"
5606
- };
5607
- var DEFAULT_SEARCH_API_URL = "https://api.search.brave.com/res/v1/web/search";
5608
- var DEFAULT_MODEL = "glm-4.7";
5609
- function getApiKey() {
5610
- return process.env[ENV_KEYS.API_KEY] || "";
5611
- }
5612
- function getBaseUrl() {
5613
- return process.env[ENV_KEYS.BASE_URL] || void 0;
5614
- }
5615
- function getModel() {
5616
- return process.env[ENV_KEYS.MODEL] || "";
5617
- }
5618
- function getSearchApiKey() {
5619
- if (process.env[ENV_KEYS.SEARCH_API_KEY]) {
5620
- return process.env[ENV_KEYS.SEARCH_API_KEY];
5621
- }
5622
- return process.env[ENV_KEYS.API_KEY];
5623
- }
5624
- function getSearchApiUrl() {
5625
- return process.env[ENV_KEYS.SEARCH_API_URL] || DEFAULT_SEARCH_API_URL;
5626
- }
5627
- function isZaiProvider() {
5628
- const baseUrl = getBaseUrl() || "";
5629
- return baseUrl.includes("z.ai");
5630
- }
5631
- function isThinkingEnabled() {
5632
- return process.env[ENV_KEYS.THINKING] === "true";
5633
- }
5634
- function getThinkingBudget() {
5635
- const val = parseInt(process.env[ENV_KEYS.THINKING_BUDGET] || "", 10);
5636
- return isNaN(val) ? 8e3 : Math.max(1024, val);
5637
- }
5638
- function validateRequiredConfig() {
5639
- const errors = [];
5640
- if (!getApiKey()) {
5641
- errors.push(
5642
- `[config] PENTEST_API_KEY is required.
5643
- Export it before running:
5644
- export PENTEST_API_KEY=your_api_key
5645
- For z.ai: get your key at https://api.z.ai`
5646
- );
5647
- }
5648
- const budgetRaw = process.env[ENV_KEYS.THINKING_BUDGET];
5649
- if (budgetRaw !== void 0 && budgetRaw !== "") {
5650
- const parsed = parseInt(budgetRaw, 10);
5651
- if (isNaN(parsed) || parsed < 1024) {
5652
- errors.push(
5653
- `[config] PENTEST_THINKING_BUDGET must be an integer \u2265 1024 (got: "${budgetRaw}")`
5654
- );
5655
- }
5656
- }
5657
- return errors;
5658
- }
5659
-
5660
5681
  // src/shared/constants/search-api.const.ts
5661
5682
  var SEARCH_URL_PATTERN = {
5662
5683
  GLM: "bigmodel.cn",
@@ -5880,7 +5901,7 @@ const { chromium } = require(${safePlaywrightPath});
5880
5901
  (async () => {
5881
5902
  const browser = await chromium.launch({
5882
5903
  headless: true,
5883
- args: ['${PLAYWRIGHT_ARG.NO_SANDBOX}', '${PLAYWRIGHT_ARG.DISABLE_SETUID_SANDBOX}']
5904
+ args: ['${PLAYWRIGHT_ARG.NO_SANDBOX}', '${PLAYWRIGHT_ARG.DISABLE_SETUID_SANDBOX}', ${JSON.stringify(getTorBrowserArgs()).slice(1, -1)}].filter(Boolean)
5884
5905
  });
5885
5906
 
5886
5907
  const context = await browser.newContext({
@@ -6066,7 +6087,10 @@ async function fillAndSubmitForm(url, formData, options = {}) {
6066
6087
  const { chromium } = require(${safePlaywrightPath});
6067
6088
 
6068
6089
  (async () => {
6069
- const browser = await chromium.launch({ headless: true });
6090
+ const browser = await chromium.launch({
6091
+ headless: true,
6092
+ args: ['--no-sandbox', '--disable-setuid-sandbox', ${JSON.stringify(getTorBrowserArgs()).slice(1, -1)}].filter(Boolean)
6093
+ });
6070
6094
  const page = await browser.newPage();
6071
6095
 
6072
6096
  try {
@@ -23,10 +23,10 @@ nmap -Pn -p<ports> -sV -sC -O <target>
23
23
  # 5. UDP Key Services
24
24
  nmap -Pn -sU --top-ports 30 --min-rate=100 <target>
25
25
 
26
- # 6. High-Speed Subnet Scan
27
- masscan <CIDR> -p1-65535 --rate=1000 -oJ .pentesting/workspace/masscan.json
26
+ # 6. Full TCP Connect Scan (Tor-compatible)
27
+ nmap -Pn -sT -p- -T4 --min-rate=1000 <target>
28
28
 
29
- # 7. Stealth SYN Scan
29
+ # 7. Stealth SYN Scan (local network only, not Tor-compatible)
30
30
  nmap -Pn -sS -T2 --max-retries=1 <target>
31
31
  ```
32
32
 
@@ -135,7 +135,7 @@ XSS:
135
135
  ├── WAF blocks web → try API endpoints (often less protected)
136
136
  ├── Web filter blocks → try WebSocket upgrade
137
137
  ├── Frontend validates → send request directly (bypass JS validation)
138
- ├── IDS detects nmap → use alternative scanning (masscan, manual /dev/tcp)
138
+ ├── IDS detects nmap → use alternative scanning (rustscan, manual /dev/tcp)
139
139
  ├── AV detects payload → encode, obfuscate, or use fileless techniques
140
140
  ├── Container boundary → escape via kernel vuln, misconfigured mount
141
141
  └── Network filter → tunnel through allowed protocols (DNS, HTTPS, ICMP)
@@ -250,7 +250,7 @@ After confirming service version, immediately:
250
250
 
251
251
  ## Error Handling
252
252
  - When [TOOL ERROR ANALYSIS] message appears, **read and follow the instructions**
253
- - nmap fails → try masscan or other scanning methods
253
+ - nmap fails → try rustscan or other scanning methods
254
254
  - Tool not installed → attempt auto-install → on failure, search for alternatives with `web_search`
255
255
  - Timeout → reduce port range and retry
256
256
  - **Never repeat the same failure 3 times** → must switch to a different approach
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pentesting",
3
- "version": "0.52.1",
3
+ "version": "0.53.0",
4
4
  "description": "Autonomous Penetration Testing AI Agent",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -19,16 +19,17 @@
19
19
  "dev:tsx": "tsx src/platform/tui/main.tsx",
20
20
  "build": "tsup",
21
21
  "start": "node dist/main.js",
22
- "test": "mkdir -p .pentesting && TMPDIR=.pentesting vitest run",
22
+ "test": "mkdir -p .vitest && TMPDIR=.vitest vitest run && rm -rf .vitest .pentesting",
23
23
  "test:watch": "vitest",
24
24
  "lint": "tsc --noEmit",
25
25
  "prepublishOnly": "npm run build",
26
+ "docker:build": "docker buildx build -f Dockerfile.base --platform linux/amd64,linux/arm64 -t agnusdei1207/pentesting-base:latest --push .",
26
27
  "release": "npm run release:patch && npm run release:docker",
27
28
  "publish:token": "npm publish --access public",
28
29
  "release:patch": "npm version patch && npm run build && npm run publish:token",
29
30
  "release:minor": "npm version minor && npm run build && npm run publish:token",
30
31
  "release:major": "npm version major && npm run build && npm run publish:token",
31
- "release:docker": "docker buildx build --platform linux/amd64,linux/arm64 -t agnusdei1207/pentesting:latest --push . && docker system prune -af",
32
+ "release:docker": "docker buildx build -f Dockerfile --platform linux/amd64,linux/arm64 -t agnusdei1207/pentesting:latest --push .",
32
33
  "check": "npm run test && npm run build && npm run release:docker && bash test.sh"
33
34
  },
34
35
  "repository": {