pentesting 0.52.2 → 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 +96 -72
- package/dist/network/prompt.md +3 -3
- package/dist/prompts/evasion.md +1 -1
- package/dist/prompts/recon.md +1 -1
- package/package.json +3 -2
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.
|
|
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
|
|
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} | ${
|
|
2209
|
+
wrappedCmd = `tail -f ${stdinFile} | ${torCommand} > ${stdoutFile} 2> ${stderrFile}`;
|
|
2125
2210
|
} else {
|
|
2126
|
-
wrappedCmd = `${
|
|
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({
|
|
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 {
|
package/dist/network/prompt.md
CHANGED
|
@@ -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.
|
|
27
|
-
|
|
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
|
|
package/dist/prompts/evasion.md
CHANGED
|
@@ -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 (
|
|
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)
|
package/dist/prompts/recon.md
CHANGED
|
@@ -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
|
|
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.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Autonomous Penetration Testing AI Agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -23,12 +23,13 @@
|
|
|
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 .
|
|
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": {
|