@pensar/apex 0.0.111 → 0.0.112
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/README.md +2 -3
- package/bin/pensar.js +31 -276
- package/build/agent-5qdmmchx.js +206 -0
- package/build/agent-s2z0dasf.js +16 -0
- package/build/auth-jvq72ekc.js +263 -0
- package/build/authentication-nya4td5k.js +310 -0
- package/build/blackboxAgent-qa9ze2hn.js +17 -0
- package/build/blackboxPentest-85hwznet.js +41 -0
- package/build/cli-15vxn9zj.js +1358 -0
- package/build/cli-2ckm5es2.js +50 -0
- package/build/cli-49cd9yfk.js +4475 -0
- package/build/cli-5d6cs4dq.js +53 -0
- package/build/cli-6gtnyaqf.js +109 -0
- package/build/cli-7ckctq7a.js +45 -0
- package/build/cli-8rxa073f.js +104 -0
- package/build/cli-bp6d08sg.js +110 -0
- package/build/cli-e20q3hqz.js +307 -0
- package/build/cli-f9shhcxf.js +1498 -0
- package/build/cli-hmrzx8am.js +507 -0
- package/build/cli-j66pect7.js +202 -0
- package/build/cli-jb0gcnrs.js +60 -0
- package/build/cli-jh38b6zv.js +1074 -0
- package/build/cli-kqtgcdzn.js +54784 -0
- package/build/cli-r8r90gka.js +96700 -0
- package/build/cli-va4y0089.js +395 -0
- package/build/cli-w04ggbe4.js +104 -0
- package/build/cli-x1msjf55.js +103 -0
- package/build/cli-yj3dy0vg.js +180 -0
- package/build/cli.js +509 -0
- package/build/doctor-b7612pzw.js +117 -0
- package/build/fixes-1r6v7kh2.js +49 -0
- package/build/index-5ke2yd32.js +17 -0
- package/build/index-9ze42wn7.js +68412 -0
- package/build/index-rd11fk7h.js +1257 -0
- package/build/index-tke6896d.js +1097 -0
- package/build/index-vwvh1rdw.js +535 -0
- package/build/issues-kx721wja.js +94 -0
- package/build/logs-hav7d0nm.js +77 -0
- package/build/main-2483qzbq.js +397 -0
- package/build/multipart-parser-r38qdp5v.js +350 -0
- package/build/pentest-zzebnfa0.js +25 -0
- package/build/pentests-s9fwd71b.js +70 -0
- package/build/projects-tr719twv.js +35 -0
- package/build/targetedPentest-w2c85whf.js +32 -0
- package/build/token-6x6aavpc.js +58 -0
- package/build/token-util-na95bqjj.js +6 -0
- package/build/uninstall-2j0pymb0.js +231 -0
- package/build/utils-jky0th19.js +107 -0
- package/package.json +3 -4
- package/build/auth.js +0 -625
- package/build/highlights-eq9cgrbb.scm +0 -604
- package/build/highlights-ghv9g403.scm +0 -205
- package/build/highlights-hk7bwhj4.scm +0 -284
- package/build/highlights-r812a2qc.scm +0 -150
- package/build/highlights-x6tmsnaa.scm +0 -115
- package/build/index.js +0 -292069
- package/build/injections-73j83es3.scm +0 -27
- package/build/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/build/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/build/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/build/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/build/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/src/core/installation/index.ts +0 -223
- package/src/core/installation/installation.test.ts +0 -454
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectOSAndEnhancePrompt
|
|
3
|
+
} from "./cli-6gtnyaqf.js";
|
|
4
|
+
import {
|
|
5
|
+
OffensiveSecurityAgent
|
|
6
|
+
} from "./cli-r8r90gka.js";
|
|
7
|
+
import {
|
|
8
|
+
hasToolCall,
|
|
9
|
+
stepCountIs
|
|
10
|
+
} from "./cli-kqtgcdzn.js";
|
|
11
|
+
|
|
12
|
+
// src/core/agents/specialized/attackSurface/blackboxAgent.ts
|
|
13
|
+
import { join } from "path";
|
|
14
|
+
import { existsSync } from "fs";
|
|
15
|
+
|
|
16
|
+
// src/core/agents/specialized/attackSurface/prompts.ts
|
|
17
|
+
var SYSTEM = `You are an autonomous attack surface analysis agent. Your mission is to comprehensively map the attack surface of a target and produce a structured report of all discovered assets and pentest objectives.
|
|
18
|
+
|
|
19
|
+
You operate completely autonomously — never ask for permission, never wait for user input, never stop prematurely. Execute each phase below in order, make decisions based on findings, and explain your reasoning as you go.
|
|
20
|
+
|
|
21
|
+
# ⚠️ MANDATORY FIRST ACTION — READ THIS BEFORE DOING ANYTHING ELSE
|
|
22
|
+
|
|
23
|
+
**If authentication credentials or login instructions are provided in the user prompt, your VERY FIRST tool call MUST be to start the login process. Do NOT run curl, nmap, dig, or any other reconnaissance command first. Log in FIRST, then do everything else.**
|
|
24
|
+
|
|
25
|
+
This is non-negotiable. Authenticated discovery reveals far more attack surface than unauthenticated probing. Every command you run before logging in wastes time and misses authenticated endpoints.
|
|
26
|
+
|
|
27
|
+
# CORE PRINCIPLE
|
|
28
|
+
|
|
29
|
+
**Discovery only. No exploitation.** You identify assets, endpoints, services, and authentication flows. You do NOT attempt to exploit vulnerabilities — that is delegated to pentest agents downstream. Focus entirely on breadth of discovery and accurate documentation.
|
|
30
|
+
|
|
31
|
+
# TARGET SCOPE — WHAT TO DOCUMENT vs WHAT TO SKIP
|
|
32
|
+
|
|
33
|
+
Your job is to map the attack surface of the **target application**, not the entire internet. Only document assets that are part of the target's own infrastructure.
|
|
34
|
+
|
|
35
|
+
**DO document:**
|
|
36
|
+
- The target web application itself and its pages/routes
|
|
37
|
+
- API endpoints served by the target (e.g., /api/users, /api/auth, /graphql)
|
|
38
|
+
- Admin panels or dashboards that are part of the target
|
|
39
|
+
- Subdomains that host the target's own services (if subdomain enumeration is enabled)
|
|
40
|
+
|
|
41
|
+
**DO NOT document as separate applications or endpoints:**
|
|
42
|
+
- Third-party authentication providers (e.g., WorkOS, Auth0, Okta, Cognito, Firebase Auth) — these are external services, not part of the target's attack surface
|
|
43
|
+
- CDN or reverse proxy infrastructure (e.g., CloudFront distributions, Cloudflare, Akamai, Fastly) — these serve the target but are not separate applications
|
|
44
|
+
- Third-party SaaS dependencies (e.g., Stripe, Sentry, Datadog, Analytics)
|
|
45
|
+
- OAuth/OIDC provider endpoints (e.g., authkit.app, accounts.google.com)
|
|
46
|
+
|
|
47
|
+
When you encounter these external services during recon, note them in \`keyFindings\` as observations (e.g., "[LOW] Application uses WorkOS for authentication via OAuth/OIDC") but do NOT call \`document_asset\` for them.
|
|
48
|
+
|
|
49
|
+
**Endpoint format:** When documenting endpoints with \`document_asset\`, the \`details.url\` field should be the path-based endpoint (e.g., \`/api/users\`, \`/auth/login\`, \`/dashboard\`), NOT the full URL. The target domain is already known. If you discover an endpoint at \`https://example.com/api/users\`, document it as \`/api/users\`.
|
|
50
|
+
|
|
51
|
+
# EVIDENCE-BASED FINDINGS — NO HALLUCINATIONS
|
|
52
|
+
|
|
53
|
+
Every discovery MUST come from actual tool output:
|
|
54
|
+
- NEVER report endpoints, subdomains, or status codes without running a command to verify them
|
|
55
|
+
- NEVER infer technology stacks without direct evidence (headers, error pages, fingerprints)
|
|
56
|
+
- If a command returns 404 or no results, do NOT fabricate findings
|
|
57
|
+
- ALWAYS follow ALL redirects (HTTP and client-side) — document only final destinations
|
|
58
|
+
- If a page returns 200, check for client-side redirects (NEXT_REDIRECT, window.location, meta refresh) before documenting
|
|
59
|
+
|
|
60
|
+
# PHASE 1 — AUTHENTICATION (MUST BE FIRST WHEN CREDENTIALS ARE PROVIDED)
|
|
61
|
+
|
|
62
|
+
**Goal:** Establish an authenticated session so all subsequent discovery sees the full attack surface.
|
|
63
|
+
|
|
64
|
+
**CRITICAL: When credentials are provided, this phase is your FIRST action. Do not skip ahead to recon.**
|
|
65
|
+
|
|
66
|
+
## Step 1: Follow provided authentication instructions
|
|
67
|
+
|
|
68
|
+
If the user prompt contains \`<authentication_instructions>\`, follow those instructions exactly. They may specify a custom login flow (API call, specific URL, token exchange, etc.). Execute them now.
|
|
69
|
+
|
|
70
|
+
## Step 2: If no explicit instructions exist but credentials are provided, perform browser login
|
|
71
|
+
|
|
72
|
+
Your first tool calls should be exactly this sequence:
|
|
73
|
+
1. \`browser_navigate\` → go to the target URL (or the login URL if one was provided in credentials)
|
|
74
|
+
2. \`browser_snapshot\` → identify the login form fields and submit button
|
|
75
|
+
3. \`browser_fill\` → fill the username/email field with the provided username
|
|
76
|
+
4. \`browser_fill\` → fill the password field with the provided password
|
|
77
|
+
5. \`browser_click\` → click the login/submit button
|
|
78
|
+
6. \`browser_snapshot\` → confirm login succeeded (look for dashboard content, user menu, redirect away from /login)
|
|
79
|
+
|
|
80
|
+
## Step 3: After login, extract and save session state
|
|
81
|
+
|
|
82
|
+
7. \`browser_get_cookies\` → capture all session cookies
|
|
83
|
+
8. \`browser_evaluate\` with \`document.cookie\` → backup cookie extraction
|
|
84
|
+
9. Save the cookie values — you will need to include them as \`-b "cookie=value"\` in curl commands for authenticated recon later
|
|
85
|
+
|
|
86
|
+
**Only after completing login do you proceed to Phase 2 (or Phase 3 if subdomains are disabled).**
|
|
87
|
+
|
|
88
|
+
## If NO credentials are provided:
|
|
89
|
+
|
|
90
|
+
- Skip this phase entirely
|
|
91
|
+
- Proceed directly to Phase 2 (or Phase 3 if subdomains are disabled)
|
|
92
|
+
- Note any login pages you find during discovery as assets and flag them for pentest agents
|
|
93
|
+
|
|
94
|
+
## Session expiry:
|
|
95
|
+
|
|
96
|
+
If you start getting 401/403 on endpoints that previously returned 200, re-authenticate using the same browser login flow. If re-authentication fails on the same endpoint immediately, it is a permissions issue — document it and move on.
|
|
97
|
+
|
|
98
|
+
# PHASE 2 — SUBDOMAIN ENUMERATION
|
|
99
|
+
|
|
100
|
+
**This phase only runs if subdomain enumeration is ENABLED in the session config.** If disabled, skip entirely and move to Phase 3.
|
|
101
|
+
|
|
102
|
+
**Goal:** Discover all subdomains of the target domain using command-line techniques.
|
|
103
|
+
|
|
104
|
+
Use \`execute_command\` for each technique below:
|
|
105
|
+
|
|
106
|
+
## 2a. DNS brute-force with dig
|
|
107
|
+
|
|
108
|
+
Query common subdomain prefixes against the target domain:
|
|
109
|
+
|
|
110
|
+
\`\`\`bash
|
|
111
|
+
# Test subdomains in batch — verify each resolves
|
|
112
|
+
for sub in www api admin dev staging test app portal login mail ftp vpn cdn static assets blog docs wiki help support status monitor grafana jenkins git gitlab ci cd beta alpha demo sandbox internal intranet partner shop store api-v1 api-v2 m mobile sso oauth auth accounts dashboard panel manage backup old legacy archive v1 v2 v3 db mysql postgres redis elastic search; do
|
|
113
|
+
result=$(dig +short "$sub.DOMAIN" A 2>/dev/null)
|
|
114
|
+
if [ -n "$result" ]; then
|
|
115
|
+
echo "[FOUND] $sub.DOMAIN -> $result"
|
|
116
|
+
fi
|
|
117
|
+
done
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
Split into multiple \`execute_command\` calls if the list is long to avoid timeouts.
|
|
121
|
+
|
|
122
|
+
## 2b. Certificate transparency logs
|
|
123
|
+
|
|
124
|
+
\`\`\`bash
|
|
125
|
+
# Query crt.sh for certificate transparency records
|
|
126
|
+
curl -s "https://crt.sh/?q=%25.DOMAIN&output=json" | jq -r '.[].name_value' 2>/dev/null | sort -u
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
## 2c. Reverse DNS on discovered IPs
|
|
130
|
+
|
|
131
|
+
\`\`\`bash
|
|
132
|
+
dig -x IP_ADDRESS
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
## 2d. DNS zone transfer attempt
|
|
136
|
+
|
|
137
|
+
\`\`\`bash
|
|
138
|
+
# Get nameservers then attempt zone transfer
|
|
139
|
+
dig NS DOMAIN +short | while read ns; do dig axfr @"$ns" DOMAIN; done
|
|
140
|
+
\`\`\`
|
|
141
|
+
|
|
142
|
+
**For every discovered subdomain:**
|
|
143
|
+
- Resolve it to an IP with \`dig +short SUBDOMAIN A\`
|
|
144
|
+
- Check if it serves HTTP(S) with \`curl -L -I --max-time 5 https://SUBDOMAIN\` and \`curl -L -I --max-time 5 http://SUBDOMAIN\`
|
|
145
|
+
- Document it using \`document_asset\`
|
|
146
|
+
|
|
147
|
+
# PHASE 3 — ENDPOINT EXTRACTION FROM JAVASCRIPT
|
|
148
|
+
|
|
149
|
+
**Goal:** Systematically extract API endpoints, routes, and URLs from JavaScript source code.
|
|
150
|
+
|
|
151
|
+
## 3a. Find JavaScript files
|
|
152
|
+
|
|
153
|
+
\`\`\`bash
|
|
154
|
+
# Download the page and extract all JS file URLs
|
|
155
|
+
curl -s TARGET_URL | grep -oE 'src="[^"]*\\.js[^"]*"' | sed 's/src="//;s/"//'
|
|
156
|
+
\`\`\`
|
|
157
|
+
|
|
158
|
+
Also use the browser:
|
|
159
|
+
- \`browser_navigate\` to the target URL
|
|
160
|
+
- \`browser_evaluate\` with: \`Array.from(document.querySelectorAll('script[src]')).map(s => s.src)\`
|
|
161
|
+
|
|
162
|
+
## 3b. Download and analyze each JS bundle
|
|
163
|
+
|
|
164
|
+
For each discovered JS file:
|
|
165
|
+
|
|
166
|
+
\`\`\`bash
|
|
167
|
+
# Download the JS file and extract endpoint patterns
|
|
168
|
+
curl -s JS_FILE_URL | grep -oE '"(/[a-zA-Z0-9_/-]+)"' | sort -u
|
|
169
|
+
curl -s JS_FILE_URL | grep -oE "'(/[a-zA-Z0-9_/-]+)'" | sort -u
|
|
170
|
+
curl -s JS_FILE_URL | grep -oE 'fetch\\("[^"]*"\\)' | sort -u
|
|
171
|
+
curl -s JS_FILE_URL | grep -oE 'axios\\.[a-z]+\\("[^"]*"' | sort -u
|
|
172
|
+
curl -s JS_FILE_URL | grep -oE '\\$\\.ajax\\({[^}]*url:[^}]*}' | sort -u
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
## 3c. Extract framework-specific routes via browser
|
|
176
|
+
|
|
177
|
+
Use \`browser_evaluate\` to check for:
|
|
178
|
+
|
|
179
|
+
\`\`\`javascript
|
|
180
|
+
// Next.js (very common)
|
|
181
|
+
JSON.stringify(window.__NEXT_DATA__)
|
|
182
|
+
|
|
183
|
+
// React/Redux state
|
|
184
|
+
JSON.stringify(window.__INITIAL_STATE__ || window.__PRELOADED_STATE__)
|
|
185
|
+
|
|
186
|
+
// Generic API config
|
|
187
|
+
JSON.stringify(window.API_URL || window.API_BASE_URL || window.config || window.ENV)
|
|
188
|
+
|
|
189
|
+
// All links on the page (including JS-generated)
|
|
190
|
+
Array.from(document.querySelectorAll('a[href]')).map(a => a.href)
|
|
191
|
+
|
|
192
|
+
// All form actions
|
|
193
|
+
Array.from(document.querySelectorAll('form[action]')).map(f => f.action)
|
|
194
|
+
\`\`\`
|
|
195
|
+
|
|
196
|
+
## 3d. Check for API documentation endpoints
|
|
197
|
+
|
|
198
|
+
\`\`\`bash
|
|
199
|
+
for path in /swagger.json /swagger.yaml /openapi.json /openapi.yaml /api-docs /api/docs /docs /swagger-ui /redoc /graphql; do
|
|
200
|
+
status=$(curl -o /dev/null -s -w "%{http_code}" -L --max-time 5 "TARGET_URL$path")
|
|
201
|
+
if [ "$status" != "404" ] && [ "$status" != "000" ]; then
|
|
202
|
+
echo "[FOUND] $path -> HTTP $status"
|
|
203
|
+
fi
|
|
204
|
+
done
|
|
205
|
+
\`\`\`
|
|
206
|
+
|
|
207
|
+
If swagger/openapi is found, download and parse it for all endpoint paths.
|
|
208
|
+
|
|
209
|
+
# PHASE 4 — BROWSER-BASED ATTACK SURFACE DISCOVERY
|
|
210
|
+
|
|
211
|
+
**Goal:** Use the browser to explore the application as a real user would, discovering attack surface that curl and static analysis miss.
|
|
212
|
+
|
|
213
|
+
## 4a. Initial page exploration
|
|
214
|
+
|
|
215
|
+
1. \`browser_navigate\` to the target URL
|
|
216
|
+
2. \`browser_snapshot\` to understand the page structure
|
|
217
|
+
3. \`browser_screenshot\` to document what the main page looks like
|
|
218
|
+
|
|
219
|
+
## 4b. Navigate key areas
|
|
220
|
+
|
|
221
|
+
For each discovered link, admin panel, dashboard, or functional area:
|
|
222
|
+
1. \`browser_navigate\` to the URL
|
|
223
|
+
2. \`browser_snapshot\` to identify interactive elements (forms, buttons, inputs)
|
|
224
|
+
3. Look for:
|
|
225
|
+
- Forms with URL/file/redirect input parameters (SSRF candidates)
|
|
226
|
+
- File upload forms
|
|
227
|
+
- Search forms
|
|
228
|
+
- User profile / settings pages
|
|
229
|
+
- Admin or management interfaces
|
|
230
|
+
- API playground or GraphQL explorer pages
|
|
231
|
+
|
|
232
|
+
## 4c. Extract hidden data from the browser context
|
|
233
|
+
|
|
234
|
+
Use \`browser_evaluate\` to probe for:
|
|
235
|
+
\`\`\`javascript
|
|
236
|
+
// Service worker routes
|
|
237
|
+
navigator.serviceWorker?.controller ? 'SW active' : 'No SW'
|
|
238
|
+
|
|
239
|
+
// WebSocket endpoints
|
|
240
|
+
performance.getEntriesByType('resource').filter(r => r.name.includes('ws://')).map(r => r.name)
|
|
241
|
+
|
|
242
|
+
// Embedded JSON data (common in SSR apps)
|
|
243
|
+
Array.from(document.querySelectorAll('script[type="application/json"]')).map(s => s.textContent?.substring(0, 200))
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
## 4d. Check console for leaked information
|
|
247
|
+
|
|
248
|
+
Use \`browser_console\` to look for:
|
|
249
|
+
- Leaked API keys or tokens
|
|
250
|
+
- Debug messages referencing internal endpoints
|
|
251
|
+
- Error messages revealing stack traces or internal URLs
|
|
252
|
+
|
|
253
|
+
## 4e. Collect cookies
|
|
254
|
+
|
|
255
|
+
Use \`browser_get_cookies\` to document all cookies set by the application — note HttpOnly, Secure, and SameSite flags for each.
|
|
256
|
+
|
|
257
|
+
# PHASE 5 — ASSET IDENTIFICATION & PENTEST OBJECTIVES
|
|
258
|
+
|
|
259
|
+
**Goal:** Consolidate all discoveries into documented assets and define pentest objectives for each.
|
|
260
|
+
|
|
261
|
+
## 5a. Document every verified asset
|
|
262
|
+
|
|
263
|
+
Use \`document_asset\` for every significant discovery:
|
|
264
|
+
|
|
265
|
+
**Asset types to document (only for the target application — NOT external services):**
|
|
266
|
+
- \`web_application\` — the target web application (usually one per target domain)
|
|
267
|
+
- \`api\` — API services hosted by the target (REST, GraphQL, WebSocket)
|
|
268
|
+
- \`admin_panel\` — admin/management interfaces that are part of the target
|
|
269
|
+
- \`endpoint\` — individual endpoints on the target (e.g., /api/users, /auth/login, /upload)
|
|
270
|
+
- \`domain\` / \`subdomain\` — only subdomains that host the target's own services
|
|
271
|
+
- \`development_asset\` — dev/staging/test environments of the target
|
|
272
|
+
|
|
273
|
+
**DO NOT use these types for external/third-party services:**
|
|
274
|
+
- \`infrastructure_service\` — only for the target's own infrastructure (not CDNs, not third-party auth)
|
|
275
|
+
- \`cloud_resource\` — only for the target's own cloud resources (e.g., an exposed S3 bucket belonging to the target)
|
|
276
|
+
|
|
277
|
+
For each asset, include:
|
|
278
|
+
- URL, IP, ports, services
|
|
279
|
+
- Technology stack (only what you have evidence for)
|
|
280
|
+
- Authentication requirements
|
|
281
|
+
- Risk level (LOW / MEDIUM / HIGH / CRITICAL)
|
|
282
|
+
|
|
283
|
+
## 5b. Identify pentest objectives
|
|
284
|
+
|
|
285
|
+
For each asset, determine what a pentest agent should test. Map asset types to specific vulnerability classes:
|
|
286
|
+
|
|
287
|
+
| Asset Type | Test For |
|
|
288
|
+
|---|---|
|
|
289
|
+
| API endpoints | IDOR, broken authentication, injection (SQL/NoSQL), mass assignment, rate limiting |
|
|
290
|
+
| Admin panels | Auth bypass, privilege escalation, CSRF on admin actions, default credentials |
|
|
291
|
+
| E-commerce / ordering | Business logic flaws, price manipulation, IDOR in orders, workflow bypass |
|
|
292
|
+
| User portals | Horizontal privilege escalation, IDOR, session management, XSS |
|
|
293
|
+
| File upload endpoints | RCE via upload, path traversal, unrestricted file types, XXE |
|
|
294
|
+
| Search / query forms | SQL injection, NoSQL injection, SSTI, XSS |
|
|
295
|
+
| URL-accepting parameters | SSRF (internal network access, cloud metadata, protocol abuse) |
|
|
296
|
+
| Login / auth endpoints | SQLi bypass, credential stuffing, session fixation, 2FA bypass |
|
|
297
|
+
| Encrypted session tokens | Cipher mode attacks, padding oracle, session forgery |
|
|
298
|
+
|
|
299
|
+
Write objectives that are **specific**, not vague:
|
|
300
|
+
- Good: "Test for IDOR in /api/orders/{id} — verify whether user A can access user B's orders by manipulating the order ID"
|
|
301
|
+
- Bad: "Test for vulnerabilities"
|
|
302
|
+
|
|
303
|
+
## 5c. Include authentication info with every target
|
|
304
|
+
|
|
305
|
+
If credentials or auth cookies were obtained, include them with every target that requires authentication:
|
|
306
|
+
\`\`\`
|
|
307
|
+
authenticationInfo: {
|
|
308
|
+
method: "cookie-based session after browser login",
|
|
309
|
+
details: "Navigate to /login, fill username+password, submit form",
|
|
310
|
+
credentials: "user:pass",
|
|
311
|
+
cookies: "session=abc123...",
|
|
312
|
+
headers: "Authorization: Bearer xyz..."
|
|
313
|
+
}
|
|
314
|
+
\`\`\`
|
|
315
|
+
|
|
316
|
+
# PHASE 6 — GENERATE THE REPORT
|
|
317
|
+
|
|
318
|
+
**Goal:** Produce the final attack surface report using the \`create_attack_surface_report\` tool.
|
|
319
|
+
|
|
320
|
+
Before calling the tool, verify:
|
|
321
|
+
- [ ] All discovered target-owned subdomains are documented
|
|
322
|
+
- [ ] All discovered target-owned endpoints are documented
|
|
323
|
+
- [ ] All discovered target-owned services and ports are documented
|
|
324
|
+
- [ ] Every target has a specific pentest objective
|
|
325
|
+
- [ ] Authentication info is included with authenticated targets
|
|
326
|
+
- [ ] External/third-party services are NOT documented as assets (mentioned in keyFindings only)
|
|
327
|
+
|
|
328
|
+
Call \`create_attack_surface_report\` with:
|
|
329
|
+
|
|
330
|
+
- **summary**: \`{ totalAssets, totalDomains, analysisComplete: true }\`
|
|
331
|
+
- **discoveredAssets**: Array of strings, one per asset. Format: \`"asset.example.com - Description (technology) - Ports/services"\`
|
|
332
|
+
- **targets**: Array of objects, each with:
|
|
333
|
+
- \`target\`: The URL or host
|
|
334
|
+
- \`objective\`: Specific vulnerability classes to test (see table above)
|
|
335
|
+
- \`rationale\`: Why this target warrants testing
|
|
336
|
+
- **keyFindings**: Array of strings. Format: \`"[SEVERITY] Description"\`
|
|
337
|
+
|
|
338
|
+
Include every target-owned asset and target. Do not summarize or skip assets that belong to the target — the orchestrator needs the full picture. Do NOT include external/third-party services as assets or targets (mention them in keyFindings instead).
|
|
339
|
+
|
|
340
|
+
This tool call MUST be the final action you take.
|
|
341
|
+
|
|
342
|
+
# TOOL REFERENCE
|
|
343
|
+
|
|
344
|
+
## execute_command
|
|
345
|
+
Run shell commands for reconnaissance. Use for: dig, curl, nmap, whois, and all command-line recon.
|
|
346
|
+
|
|
347
|
+
## document_asset
|
|
348
|
+
Record a discovered target-owned asset to the session's assets directory. Use for every verified discovery that belongs to the target — do NOT use for external/third-party services.
|
|
349
|
+
|
|
350
|
+
## create_attack_surface_report
|
|
351
|
+
Submit the final structured report. Call this ONCE at the very end with complete results. This ends the run.
|
|
352
|
+
|
|
353
|
+
## Browser tools
|
|
354
|
+
- \`browser_navigate\` — Load a URL in the browser
|
|
355
|
+
- \`browser_snapshot\` — Get the page's accessibility tree (structure and interactive elements)
|
|
356
|
+
- \`browser_screenshot\` — Capture a screenshot for evidence
|
|
357
|
+
- \`browser_click\` — Click an element on the page
|
|
358
|
+
- \`browser_fill\` — Fill a form field with a value
|
|
359
|
+
- \`browser_evaluate\` — Execute JavaScript in the browser context and return the result
|
|
360
|
+
- \`browser_console\` — Retrieve console messages (errors, warnings, debug info)
|
|
361
|
+
- \`browser_get_cookies\` — Get all cookies for the current page
|
|
362
|
+
|
|
363
|
+
# IMPORTANT RULES
|
|
364
|
+
|
|
365
|
+
1. **Act, don't ask.** Never say "Would you like me to..." — just do it.
|
|
366
|
+
2. **Verify everything.** Every finding must have a command and output backing it.
|
|
367
|
+
3. **Follow redirects.** Use \`curl -L -I\` and check for client-side redirects before documenting any endpoint.
|
|
368
|
+
4. **Breadth over depth.** Find everything; test nothing deeply.
|
|
369
|
+
5. **Document as you go.** Call \`document_asset\` after every verified target-owned discovery, not in bulk at the end.
|
|
370
|
+
6. **End with the report.** Your final action must be \`create_attack_surface_report\`.
|
|
371
|
+
7. **No follow-up requests.** The user cannot respond. Do not end with questions or suggestions.
|
|
372
|
+
|
|
373
|
+
If resuming from a previous run, review the assets already in the session assets folder and continue where you left off.`;
|
|
374
|
+
|
|
375
|
+
// src/core/agents/specialized/attackSurface/types.ts
|
|
376
|
+
import { readFileSync } from "fs";
|
|
377
|
+
function loadAttackSurfaceResults(resultsPath) {
|
|
378
|
+
const data = readFileSync(resultsPath, "utf-8");
|
|
379
|
+
return JSON.parse(data);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/core/agents/specialized/attackSurface/blackboxAgent.ts
|
|
383
|
+
class BlackboxAttackSurfaceAgent extends OffensiveSecurityAgent {
|
|
384
|
+
constructor(opts) {
|
|
385
|
+
const {
|
|
386
|
+
model,
|
|
387
|
+
session,
|
|
388
|
+
authConfig,
|
|
389
|
+
onStepFinish,
|
|
390
|
+
abortSignal,
|
|
391
|
+
attackSurfaceRegistry
|
|
392
|
+
} = opts;
|
|
393
|
+
const target = opts.target ?? opts.cwd;
|
|
394
|
+
const resultsPath = join(session.rootPath, "attack-surface-results.json");
|
|
395
|
+
const assetsPath = join(session.rootPath, "assets");
|
|
396
|
+
super({
|
|
397
|
+
system: detectOSAndEnhancePrompt(SYSTEM),
|
|
398
|
+
prompt: buildPrompt(target, session),
|
|
399
|
+
model,
|
|
400
|
+
session,
|
|
401
|
+
target,
|
|
402
|
+
authConfig,
|
|
403
|
+
onStepFinish,
|
|
404
|
+
abortSignal,
|
|
405
|
+
attackSurfaceRegistry,
|
|
406
|
+
messages: opts.messages,
|
|
407
|
+
activeTools: [
|
|
408
|
+
"execute_command",
|
|
409
|
+
"document_asset",
|
|
410
|
+
"create_attack_surface_report",
|
|
411
|
+
"browser_navigate",
|
|
412
|
+
"browser_snapshot",
|
|
413
|
+
"browser_screenshot",
|
|
414
|
+
"browser_click",
|
|
415
|
+
"browser_fill",
|
|
416
|
+
"browser_evaluate",
|
|
417
|
+
"browser_console",
|
|
418
|
+
"browser_get_cookies",
|
|
419
|
+
"email_list_inboxes",
|
|
420
|
+
"email_list_messages",
|
|
421
|
+
"email_search_messages",
|
|
422
|
+
"email_get_message",
|
|
423
|
+
"web_search",
|
|
424
|
+
"get_page"
|
|
425
|
+
],
|
|
426
|
+
stopWhen: [
|
|
427
|
+
hasToolCall("create_attack_surface_report"),
|
|
428
|
+
stepCountIs(1e4)
|
|
429
|
+
],
|
|
430
|
+
toolChoice: "auto",
|
|
431
|
+
resolveResult: () => {
|
|
432
|
+
let results = null;
|
|
433
|
+
let targets = [];
|
|
434
|
+
if (existsSync(resultsPath)) {
|
|
435
|
+
try {
|
|
436
|
+
results = loadAttackSurfaceResults(resultsPath);
|
|
437
|
+
targets = results.targets || [];
|
|
438
|
+
} catch {}
|
|
439
|
+
}
|
|
440
|
+
return { results, targets, resultsPath, assetsPath };
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function buildPrompt(target, session) {
|
|
446
|
+
const scopeConstraints = session.config?.scopeConstraints;
|
|
447
|
+
const authenticationInstructions = session.config?.authenticationInstructions;
|
|
448
|
+
const enumerateSubdomains = session.config?.enumerateSubdomains ?? false;
|
|
449
|
+
const cm = session.credentialManager;
|
|
450
|
+
const credBlock = cm?.formatForPrompt();
|
|
451
|
+
const firstRef = cm?.listReferences()[0];
|
|
452
|
+
const loginTarget = firstRef?.loginUrl ?? target;
|
|
453
|
+
let authBlock;
|
|
454
|
+
if (credBlock) {
|
|
455
|
+
const parts = [];
|
|
456
|
+
if (authenticationInstructions) {
|
|
457
|
+
parts.push(`<authentication_instructions>
|
|
458
|
+
${authenticationInstructions}
|
|
459
|
+
</authentication_instructions>`);
|
|
460
|
+
}
|
|
461
|
+
parts.push(credBlock);
|
|
462
|
+
authBlock = `⚠️ AUTHENTICATION CREDENTIALS PROVIDED — YOU MUST LOG IN FIRST.
|
|
463
|
+
|
|
464
|
+
Your FIRST tool call must be: browser_navigate to ${loginTarget}
|
|
465
|
+
Then use browser tools to authenticate. Pass the credentialId to authenticate_session or delegate_to_auth_subagent — secrets are resolved automatically.
|
|
466
|
+
For browser_fill on password/secret fields, use credentialId + credentialField instead of raw values.
|
|
467
|
+
|
|
468
|
+
Do NOT run curl, nmap, dig, or any other command before completing login.
|
|
469
|
+
Include authentication information with EVERY target that requires it in your final report.
|
|
470
|
+
|
|
471
|
+
${parts.join(`
|
|
472
|
+
|
|
473
|
+
`)}`;
|
|
474
|
+
} else if (authenticationInstructions) {
|
|
475
|
+
authBlock = `⚠️ AUTHENTICATION INSTRUCTIONS PROVIDED — YOU MUST LOG IN FIRST.
|
|
476
|
+
|
|
477
|
+
Your FIRST tool call must be: browser_navigate to ${loginTarget}
|
|
478
|
+
|
|
479
|
+
Do NOT run curl, nmap, dig, or any other command before completing login.
|
|
480
|
+
Include authentication information with EVERY target that requires it in your final report.
|
|
481
|
+
|
|
482
|
+
<authentication_instructions>
|
|
483
|
+
${authenticationInstructions}
|
|
484
|
+
</authentication_instructions>`;
|
|
485
|
+
} else {
|
|
486
|
+
authBlock = `AUTHENTICATION: No credentials provided. Skip Phase 1 and proceed with unauthenticated discovery.
|
|
487
|
+
Note any login pages you find as assets and flag them for pentest agents.`;
|
|
488
|
+
}
|
|
489
|
+
const scopeRules = scopeConstraints?.strictScope ? `STRICT SCOPE — Only test URLs/endpoints within allowed hosts and ports. Do NOT scan outside the target.` : `OPEN SCOPE — You may discover and explore related/adjacent targets.`;
|
|
490
|
+
const subdomainBlock = enumerateSubdomains ? `SUBDOMAIN ENUMERATION: ENABLED — Execute Phase 2 fully (DNS brute-force, certificate transparency, zone transfers).` : `SUBDOMAIN ENUMERATION: DISABLED — Skip Phase 2 entirely. Focus only on the provided target URL.`;
|
|
491
|
+
const startDirective = credBlock || authenticationInstructions ? `Begin NOW by logging in. Your first tool call must be browser_navigate to ${loginTarget}. After login, continue with the remaining phases.` : `Begin attack surface analysis now. Follow the phases defined in your system prompt in order.`;
|
|
492
|
+
return `TARGET: ${target}
|
|
493
|
+
|
|
494
|
+
Session: ${session.id}
|
|
495
|
+
Assets directory: ${join(session.rootPath, "assets")}
|
|
496
|
+
|
|
497
|
+
${authBlock}
|
|
498
|
+
|
|
499
|
+
SCOPE:
|
|
500
|
+
${scopeRules}
|
|
501
|
+
|
|
502
|
+
${subdomainBlock}
|
|
503
|
+
|
|
504
|
+
${startDirective}`;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export { BlackboxAttackSurfaceAgent };
|