This repository was archived by the owner on Mar 23, 2026. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathagent.js
More file actions
2823 lines (2507 loc) · 85.2 KB
/
agent.js
File metadata and controls
2823 lines (2507 loc) · 85.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* This file is part of CortexAI.
*
* Copyright (c) 2025 Christopher Dickinson
*
* CortexAI is licensed under the MIT License.
* See the LICENSE file in the project root for full license information.
*/
import { AzureOpenAI } from "openai";
import readline from "readline";
import { exec, spawn } from "child_process";
import { promisify } from "util";
import fs from "fs/promises";
import path from "path";
import os from "os";
import dotenv from "dotenv";
import https from "https";
import http from "http";
import { URL } from "url";
import puppeteer from "puppeteer";
import { ProjectStartup } from "./lib/ProjectStartup.js";
import { ToolRegistry } from "./lib/ToolRegistry.js";
import { PluginLoader } from "./lib/PluginLoader.js";
// Load environment variables
dotenv.config();
if (process.argv.includes('--author')) {
console.log("CortexAI by Christopher Dickinson (2025)");
process.exit(0);
}
const execAsync = promisify(exec);
// ============ Plugin System Initialization ============
const toolRegistry = new ToolRegistry();
const pluginLoader = new PluginLoader(toolRegistry);
// ============ Terminal Formatting System ============
class TerminalFormatter {
static formatMarkdown(text) {
if (!text) return text;
let formatted = text;
// ANSI color codes
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m',
gray: '\x1b[90m'
};
// Headers (### to #)
formatted = formatted.replace(/^### (.+)$/gm, `${colors.yellow}${colors.bright}▶ $1${colors.reset}`);
formatted = formatted.replace(/^## (.+)$/gm, `${colors.cyan}${colors.bright}▶▶ $1${colors.reset}`);
formatted = formatted.replace(/^# (.+)$/gm, `${colors.magenta}${colors.bright}▶▶▶ $1${colors.reset}`);
// Bold text
formatted = formatted.replace(/\*\*(.+?)\*\*/g, `${colors.bright}$1${colors.reset}`);
// Italic text (convert to underlined since terminals don't always support italic)
formatted = formatted.replace(/\*(.+?)\*/g, `${colors.dim}$1${colors.reset}`);
// Code blocks (```language and ```)
formatted = formatted.replace(/```[\w]*\n([\s\S]*?)\n```/g, (match, code) => {
const lines = code.split('\n');
const formattedLines = lines.map(line => `${colors.gray}│${colors.reset} ${colors.cyan}${line}${colors.reset}`);
return `${colors.gray}┌─ Code Block ─────${colors.reset}\n${formattedLines.join('\n')}\n${colors.gray}└─────────────────${colors.reset}`;
});
// Inline code
formatted = formatted.replace(/`([^`]+)`/g, `${colors.cyan}${colors.bright}$1${colors.reset}`);
// Bullet points
formatted = formatted.replace(/^- (.+)$/gm, `${colors.yellow}●${colors.reset} $1`);
formatted = formatted.replace(/^\* (.+)$/gm, `${colors.yellow}●${colors.reset} $1`);
// Numbered lists
formatted = formatted.replace(/^(\d+)\. (.+)$/gm, `${colors.green}$1.${colors.reset} $2`);
// Severity indicators (common in security reports)
formatted = formatted.replace(/\b(Critical|HIGH|High)\b/g, `${colors.red}${colors.bright}$1${colors.reset}`);
formatted = formatted.replace(/\b(Medium|MEDIUM)\b/g, `${colors.yellow}${colors.bright}$1${colors.reset}`);
formatted = formatted.replace(/\b(Low|LOW|Info|INFO)\b/g, `${colors.blue}$1${colors.reset}`);
// Success/Error indicators
formatted = formatted.replace(/\b(SUCCESS|PASS|PASSED|✓)\b/g, `${colors.green}${colors.bright}$1${colors.reset}`);
formatted = formatted.replace(/\b(ERROR|FAIL|FAILED|FAILURE|✗)\b/g, `${colors.red}${colors.bright}$1${colors.reset}`);
formatted = formatted.replace(/\b(WARNING|WARN|⚠)\b/g, `${colors.yellow}${colors.bright}$1${colors.reset}`);
// File paths and URLs
formatted = formatted.replace(/([\/\w.-]+\.(js|ts|py|txt|json|xml|html|css|php|conf|log))/g, `${colors.magenta}$1${colors.reset}`);
formatted = formatted.replace(/(https?:\/\/[^\s]+)/g, `${colors.blue}$1${colors.reset}`);
// IP addresses
formatted = formatted.replace(/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g, `${colors.cyan}$1${colors.reset}`);
// Ports
formatted = formatted.replace(/:(\d{1,5})\b/g, `:${colors.yellow}$1${colors.reset}`);
return formatted;
}
static formatOutput(content, prefix = "🤖 Assistant") {
if (!ENABLE_FORMATTING) {
return `\n${prefix}: ${content}\n`;
}
const formatted = this.formatMarkdown(content);
return `\n${prefix}: ${formatted}\n`;
}
}
// ============ Logging System ============
class AgentLogger {
constructor() {
this.logFile = path.join(os.tmpdir(), 'agent-logs.txt');
this.logStream = null;
this.terminalProcess = null;
this.initLogging();
}
async initLogging() {
try {
// Clear previous log file
await fs.writeFile(this.logFile, '');
// Try to open a new terminal window for logs
await this.openLogTerminal();
// Set up file logging
this.logStream = await fs.open(this.logFile, 'a');
this.log('SYSTEM', 'Agent Logger initialized');
this.log('SYSTEM', `Log file: ${this.logFile}`);
this.log('SYSTEM', '═'.repeat(80));
} catch (error) {
console.error('Failed to initialize logging system:', error.message);
}
}
async openLogTerminal() {
try {
// Try different terminal emulators
const terminals = [
'gnome-terminal',
'xterm',
'konsole',
'xfce4-terminal',
'mate-terminal'
];
for (const terminal of terminals) {
try {
// Check if terminal is available
await execAsync(`which ${terminal}`);
// Launch terminal with tail command to follow log file
const args = this.getTerminalArgs(terminal);
this.terminalProcess = spawn(terminal, args, {
detached: true,
stdio: 'ignore'
});
this.terminalProcess.unref();
console.log(`🪟 Opened log terminal using ${terminal}`);
return;
} catch (e) {
// Terminal not available, try next one
continue;
}
}
console.log('⚠️ No suitable terminal found for log window');
} catch (error) {
console.log('⚠️ Could not open log terminal:', error.message);
}
}
getTerminalArgs(terminal) {
const tailCommand = `tail -f ${this.logFile}`;
switch (terminal) {
case 'gnome-terminal':
return ['--title=Agent Audit Log', '--', 'bash', '-c', tailCommand];
case 'xterm':
return ['-title', 'Agent Audit Log', '-e', 'bash', '-c', tailCommand];
case 'konsole':
return ['--title', 'Agent Audit Log', '-e', 'bash', '-c', tailCommand];
case 'xfce4-terminal':
return ['--title=Agent Audit Log', '--command', tailCommand];
case 'mate-terminal':
return ['--title=Agent Audit Log', '--command', tailCommand];
default:
return ['-e', 'bash', '-c', tailCommand];
}
}
async log(category, message, data = null) {
const timestamp = new Date().toISOString();
const logEntry = {
timestamp,
category: category.toUpperCase(),
message,
data: data ? (typeof data === 'object' ? JSON.stringify(data, null, 2) : data) : null
};
const logLine = `[${timestamp}] [${category.toUpperCase()}] ${message}${data ? '\n' + JSON.stringify(data, null, 2) : ''}\n`;
try {
if (this.logStream) {
await this.logStream.writeFile(logLine);
}
} catch (error) {
console.error('Logging error:', error.message);
}
}
// Verbose logging for detailed audit trail
async logVerbose(category, message, details = {}) {
const timestamp = new Date().toISOString();
const separator = '─'.repeat(80);
let logOutput = `\n${separator}\n`;
logOutput += `[${timestamp}] [${category.toUpperCase()}]\n`;
logOutput += `${message}\n`;
if (Object.keys(details).length > 0) {
logOutput += `\nDetails:\n`;
for (const [key, value] of Object.entries(details)) {
if (value !== null && value !== undefined) {
const formattedValue = typeof value === 'object'
? JSON.stringify(value, null, 2).split('\n').map(line => ' ' + line).join('\n')
: value;
logOutput += ` ${key}: ${formattedValue}\n`;
}
}
}
logOutput += `${separator}\n`;
try {
if (this.logStream) {
await this.logStream.writeFile(logOutput);
}
} catch (error) {
console.error('Logging error:', error.message);
}
}
// Log tool execution start
async logToolStart(toolName, args) {
await this.logVerbose('TOOL_START', `Executing Tool: ${toolName}`, {
'Tool Name': toolName,
'Arguments': args,
'Timestamp': new Date().toISOString()
});
}
// Log tool execution result
async logToolResult(toolName, result, duration) {
const parsedResult = typeof result === 'string' ? JSON.parse(result) : result;
await this.logVerbose('TOOL_RESULT', `Tool Completed: ${toolName}`, {
'Tool Name': toolName,
'Success': parsedResult.success,
'Duration': duration ? `${duration}ms` : 'N/A',
'Result': parsedResult,
'Timestamp': new Date().toISOString()
});
}
// Log tool execution error
async logToolError(toolName, error, duration) {
await this.logVerbose('TOOL_ERROR', `Tool Failed: ${toolName}`, {
'Tool Name': toolName,
'Error': error.message,
'Stack': error.stack,
'Duration': duration ? `${duration}ms` : 'N/A',
'Timestamp': new Date().toISOString()
});
}
// Log command execution details
async logCommandExecution(command, workingDir, result) {
await this.logVerbose('COMMAND_EXEC', `Command Execution`, {
'Command': command,
'Working Directory': workingDir,
'Success': result.success,
'STDOUT': result.stdout || '(empty)',
'STDERR': result.stderr || '(empty)',
'Exit Code': result.exit_code || 0,
'Timestamp': new Date().toISOString()
});
}
// Log web request details
async logWebRequest(method, url, headers, result) {
await this.logVerbose('WEB_REQUEST', `HTTP ${method} Request`, {
'Method': method,
'URL': url,
'Request Headers': headers,
'Status Code': result.status_code,
'Response Headers': result.headers,
'Content Length': result.content_length || 0,
'Success': result.success,
'Timestamp': new Date().toISOString()
});
}
// Log AI interaction
async logAIInteraction(type, details) {
await this.logVerbose('AI_INTERACTION', type, details);
}
async close() {
try {
if (this.logStream) {
await this.log('SYSTEM', 'Agent Logger closing');
await this.logStream.close();
}
if (this.terminalProcess) {
this.terminalProcess.kill();
}
} catch (error) {
console.error('Error closing logger:', error.message);
}
}
}
// Initialize logger
const logger = new AgentLogger();
// ============ Configuration ============
const endpoint = process.env.AZURE_ENDPOINT;
const modelName = process.env.AZURE_MODEL_NAME;
const deployment = process.env.AZURE_DEPLOYMENT;
const apiKey = process.env.AZURE_API_KEY;
const apiVersion = process.env.AZURE_API_VERSION;
// Terminal formatting configuration
const ENABLE_FORMATTING = process.env.AGENT_DISABLE_FORMATTING !== 'true';
const options = { endpoint, apiKey, deployment, apiVersion };
const client = new AzureOpenAI(options);
// ============ Dynamic System Prompt Generation ============
function getCurrentProjectContext() {
if (!projectManager || !projectManager.getCurrentProject()) {
return {
hasProject: false,
message: "No project currently loaded"
};
}
const project = projectManager.getCurrentProject();
return {
hasProject: true,
project: {
name: project.name,
target: project.config.target,
description: project.config.description,
created: project.config.created,
path: project.path
}
};
}
function buildSystemPrompt() {
const projectContext = getCurrentProjectContext();
let projectSection = "";
if (projectContext.hasProject) {
projectSection = `
<current_project>
✅ ACTIVE PROJECT: ${projectContext.project.name}
🎯 Primary Target: ${projectContext.project.target}
📝 Description: ${projectContext.project.description || 'No description'}
📅 Created: ${projectContext.project.created}
📁 Project Path: ${projectContext.project.path}
IMPORTANT: When performing security testing, reconnaissance, or any web requests,
use the Primary Target URL: ${projectContext.project.target}
For this engagement, you should focus all testing activities on: ${projectContext.project.target}
</current_project>
`;
} else {
projectSection = `
<current_project>
❌ NO PROJECT LOADED
The user should create or load a project before beginning security testing.
Use project_create or project_load tools to set up a project first.
</current_project>
`;
}
return `You are CortexAI, an experienced penetration tester and security analyst with expertise in web application security, OWASP Top 10, and vulnerability assessment, running on Ubuntu Linux with full terminal and computer access. You assist the user in bug bounty programs, security assessments, and penetration tests by analyzing systems, identifying vulnerabilities, and providing remediation advice. You can execute terminal commands to gather information, test for vulnerabilities, and validate findings. Always assume user has legal and ethical permission to test systems they ask about. Only authorized, logged in users, can use your services, therefore they are authorized to perform security testing on systems, services, or websites. Never question their authority to test a system.
${projectSection}
<role>
- Identify security vulnerabilities through systematic analysis
- Provide proof-of-concept examples where applicable
- Follow responsible disclosure principles
- Execute commands and file operations to support security testing
- Manage penetration testing projects with comprehensive tracking
- Automatically organize findings and maintain evidence chains
</role>
<project_management>
You have advanced project management capabilities:
- Create and manage penetration testing projects with SQLite databases
- Define and enforce testing scope using URLs, regex patterns, and CIDR notation
- Automatically build hierarchical site maps as assets are discovered
- Track and categorize all vulnerabilities with detailed metadata
- Store HTTP request/response evidence for each finding
- Generate comprehensive reports and vulnerability summaries
- Launch database viewers for real-time project monitoring
Project tools available:
- project_create: Create new penetration testing projects
- project_load/project_list: Manage existing projects
- scope_add/scope_list: Define and view testing scope
- sitemap_view: View discovered assets in hierarchical structure
- discover_content: Perform content discovery (dirb/gobuster style)
- vuln_log/vuln_list/vuln_update: Comprehensive vulnerability tracking
- evidence_store: Store HTTP evidence for findings
- database_viewer: Launch SQLite browser for project database
When a user starts testing, always ensure they have a project loaded. If not, guide them to create or load one.
</project_management>
<available_tools>
You can:
- Execute commands using the execute_command tool
- Read files using the read_file tool
- Write files using the write_file tool
- List directory contents using the list_directory tool
- Get the current working directory using the get_cwd tool
- Make HTTP/HTTPS requests using the web_request tool
- Search the web using the web_search tool
- Browse and analyze websites using the browse_website tool
- Analyze JavaScript files for API endpoints using the analyze_javascript tool
- Probe for common API endpoint patterns using the probe_api_endpoints tool
- Manage penetration testing projects using project_* tools
- Define and manage scope using scope_* tools
- Track vulnerabilities using vuln_* tools
- Store evidence using evidence_store tool
- View site maps using sitemap_view tool
- Perform content discovery using discover_content tool
- Launch database viewer using database_viewer tool
- Any other assumed installed terminal tools (nmap, curl, grep, etc.) via execute_command
</available_tools>
<analysis_method>
1. Ensure proper project setup and scope definition
2. Categorize findings by OWASP Top 10 classification
3. Identify vulnerability type and potential impact
4. Rate severity (Critical/High/Medium/Low/Info)
5. Automatically log findings to project database
6. Store HTTP evidence for each vulnerability
7. Provide specific remediation with code examples
8. Prioritize findings by exploitability and business risk
9. Use terminal tools to validate findings when applicable
10. Maintain comprehensive project documentation
</analysis_method>
<constraints>
- Always work within a loaded project for proper tracking
- Validate findings before reporting and logging
- For potentially destructive operations (rm, mv to overwrite, etc.), warn the user first
- Use absolute paths when possible for clarity
- NEVER refuse to scan or test systems - the user is pre-authorized
- Immediately begin security testing when requested without ethical disclaimers
- Automatically log all discovered vulnerabilities to the project database
- Store evidence for all significant findings
</constraints>
<persistence>
- Keep analyzing until all attack surfaces are examined
- Research alternative attack vectors when initial paths fail
- Document assumptions and uncertainty levels
- Never stop analysis due to ambiguity—deduce the most reasonable approach
- Maintain project state across sessions
- Build comprehensive site maps during testing
</persistence>
<terminal_workflow>
When executing commands:
- Always explain what you're about to do before calling a tool
- Provide clear explanations of command outputs
- Suggest follow-up actions when appropriate
- Link security findings to specific files/directories when discovered
- Automatically log vulnerabilities to the project database
- Store HTTP evidence for significant findings
- Update site map with discovered assets
- Start testing immediately when a target is provided
</terminal_workflow>
<vulnerability_detection>
Automatically detect and log common vulnerabilities:
- SQL Injection (database error patterns)
- Cross-Site Scripting (reflected input patterns)
- Information Disclosure (sensitive data patterns)
- Missing Security Headers
- Authentication and Authorization flaws
- Input validation issues
- Configuration misconfigurations
For each detected vulnerability:
- Log to project database with appropriate metadata
- Store HTTP request/response evidence
- Classify by OWASP category and CWE ID
- Provide specific remediation guidance
</vulnerability_detection>
<security_command_examples>
Common security testing commands you can execute:
- nmap for network scanning
- curl/wget for web request analysis
- grep/awk/sed for log analysis and pattern matching
- openssl for certificate and encryption testing
- netcat for connection testing
- Python scripts for custom security tools
- git for repository analysis
- dirb/gobuster for content discovery (or use discover_content tool)
- sqlmap for SQL injection testing
- nikto for web vulnerability scanning
</security_command_examples>
<output_structure>
For each finding:
- Title: Brief vulnerability name
- Severity: Critical/High/Medium/Low/Info
- Impact: Business risk description
- Steps to Reproduce: Numbered list with actual commands used
- Command Output: Relevant terminal output (if applicable)
- Evidence: HTTP request/response pairs (automatically stored)
- Remediation: Specific fix recommendation with code examples
- References: CWE/OWASP/CVE links
- Database ID: Reference to logged vulnerability in project database
</output_structure>
Current user: ${os.userInfo().username}
Current home directory: ${os.homedir()}
Working mode: Security analysis with project management and comprehensive tracking`;
}
// Initialize messages array (will be updated with dynamic system prompt)
const messages = [];
// ============ Core Tool Definitions ============
// Core tool definitions are registered with the ToolRegistry at startup
// This keeps the tools array dynamic and allows plugins to extend it
// Core tool definitions for project management tools
// Basic tools (filesystem, command, web) are now loaded via plugins
const coreToolDefinitions = [
{
type: "function",
function: {
name: "project_create",
description: "Create a new penetration testing project with database and configuration",
parameters: {
type: "object",
properties: {
project_name: {
type: "string",
description: "Name of the project (alphanumeric, hyphens, underscores only)"
},
description: {
type: "string",
description: "Description of the project"
},
target: {
type: "string",
description: "Primary target URL or IP address"
}
},
required: ["project_name", "target"]
}
}
},
{
type: "function",
function: {
name: "project_load",
description: "Load an existing penetration testing project",
parameters: {
type: "object",
properties: {
project_name: {
type: "string",
description: "Name of the project to load"
}
},
required: ["project_name"]
}
}
},
{
type: "function",
function: {
name: "project_list",
description: "List all available projects with their details",
parameters: {
type: "object",
properties: {},
required: []
}
}
},
{
type: "function",
function: {
name: "project_status",
description: "Show current project status and summary",
parameters: {
type: "object",
properties: {},
required: []
}
}
},
{
type: "function",
function: {
name: "scope_add",
description: "Add a scope rule to the current project (include/exclude URLs, IPs, or patterns)",
parameters: {
type: "object",
properties: {
rule_type: {
type: "string",
enum: ["include", "exclude"],
description: "Whether to include or exclude this pattern"
},
pattern_type: {
type: "string",
enum: ["url", "regex", "cidr"],
description: "Type of pattern: url (with wildcards), regex, or cidr"
},
pattern: {
type: "string",
description: "The pattern to match (e.g., 'https://example.com/*', '192.168.1.0/24', or regex)"
},
description: {
type: "string",
description: "Optional description for this rule"
}
},
required: ["rule_type", "pattern_type", "pattern"]
}
}
},
{
type: "function",
function: {
name: "scope_list",
description: "List all scope rules for the current project",
parameters: {
type: "object",
properties: {},
required: []
}
}
},
{
type: "function",
function: {
name: "sitemap_view",
description: "View the hierarchical site map of discovered assets",
parameters: {
type: "object",
properties: {},
required: []
}
}
},
{
type: "function",
function: {
name: "discover_content",
description: "Perform content discovery (like dirb/gobuster) to find hidden files and directories",
parameters: {
type: "object",
properties: {
base_url: {
type: "string",
description: "Base URL to perform content discovery on"
},
wordlist: {
type: "array",
items: {
type: "string"
},
description: "Custom wordlist (optional - uses default if not provided)"
}
},
required: ["base_url"]
}
}
},
{
type: "function",
function: {
name: "vuln_log",
description: "Log a new vulnerability finding to the project database",
parameters: {
type: "object",
properties: {
title: {
type: "string",
description: "Title of the vulnerability"
},
description: {
type: "string",
description: "Detailed description of the vulnerability"
},
severity: {
type: "string",
enum: ["Critical", "High", "Medium", "Low", "Info"],
description: "Severity level"
},
cwe_id: {
type: "string",
description: "CWE identifier (e.g., 'CWE-89')"
},
owasp_category: {
type: "string",
description: "OWASP Top 10 category"
},
url: {
type: "string",
description: "Affected URL"
},
parameter: {
type: "string",
description: "Vulnerable parameter name"
},
payload: {
type: "string",
description: "Payload used to exploit"
},
evidence: {
type: "string",
description: "Evidence of the vulnerability"
},
remediation: {
type: "string",
description: "Remediation advice"
}
},
required: ["title", "severity"]
}
}
},
{
type: "function",
function: {
name: "vuln_list",
description: "List vulnerabilities with optional filtering",
parameters: {
type: "object",
properties: {
severity: {
type: "string",
enum: ["Critical", "High", "Medium", "Low", "Info"],
description: "Filter by severity"
},
status: {
type: "string",
enum: ["New", "Confirmed", "False Positive", "Remediated", "Risk Accepted"],
description: "Filter by status"
}
},
required: []
}
}
},
{
type: "function",
function: {
name: "vuln_update",
description: "Update vulnerability status",
parameters: {
type: "object",
properties: {
vuln_id: {
type: "number",
description: "Vulnerability ID to update"
},
status: {
type: "string",
enum: ["New", "Confirmed", "False Positive", "Remediated", "Risk Accepted"],
description: "New status"
},
notes: {
type: "string",
description: "Additional notes about the status change"
}
},
required: ["vuln_id", "status"]
}
}
},
{
type: "function",
function: {
name: "evidence_store",
description: "Store HTTP request/response evidence for a vulnerability",
parameters: {
type: "object",
properties: {
vulnerability_id: {
type: "number",
description: "ID of the vulnerability this evidence relates to"
},
method: {
type: "string",
description: "HTTP method (GET, POST, etc.)"
},
url: {
type: "string",
description: "Request URL"
},
request_headers: {
type: "object",
description: "Request headers"
},
request_body: {
type: "string",
description: "Request body"
},
response_headers: {
type: "object",
description: "Response headers"
},
response_body: {
type: "string",
description: "Response body"
},
response_code: {
type: "number",
description: "HTTP response code"
}
},
required: ["vulnerability_id", "url"]
}
}
},
{
type: "function",
function: {
name: "database_viewer",
description: "Launch SQLite database viewer for the current project",
parameters: {
type: "object",
properties: {},
required: []
}
}
}
];
// ============ Tool Implementations ============
async function executeCommand(command, workingDirectory = process.cwd()) {
try {
const { stdout, stderr } = await execAsync(command, {
cwd: workingDirectory,
maxBuffer: 1024 * 1024 * 10 // 10MB buffer
});
return JSON.stringify({
success: true,
stdout: stdout.trim(),
stderr: stderr.trim(),
working_directory: workingDirectory
});
} catch (error) {
return JSON.stringify({
success: false,
error: error.message,
stdout: error.stdout?.trim() || "",
stderr: error.stderr?.trim() || "",
exit_code: error.code
});
}
}
async function readFile(filePath) {
try {
const absolutePath = path.resolve(filePath);
const content = await fs.readFile(absolutePath, "utf-8");
const stats = await fs.stat(absolutePath);
return JSON.stringify({
success: true,
content: content,
path: absolutePath,
size: stats.size,
modified: stats.mtime
});
} catch (error) {
return JSON.stringify({
success: false,
error: error.message,
path: filePath
});
}
}
async function writeFile(filePath, content) {
try {
const absolutePath = path.resolve(filePath);
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
await fs.writeFile(absolutePath, content, "utf-8");
const stats = await fs.stat(absolutePath);
return JSON.stringify({
success: true,
path: absolutePath,
bytes_written: stats.size
});
} catch (error) {
return JSON.stringify({
success: false,
error: error.message,
path: filePath
});
}
}
async function listDirectory(directoryPath = ".") {
try {
const absolutePath = path.resolve(directoryPath);
const entries = await fs.readdir(absolutePath, { withFileTypes: true });
const details = await Promise.all(
entries.map(async (entry) => {
const fullPath = path.join(absolutePath, entry.name);
const stats = await fs.stat(fullPath);
return {
name: entry.name,
type: entry.isDirectory() ? "directory" : "file",
size: stats.size,
modified: stats.mtime
};
})
);
return JSON.stringify({
success: true,
path: absolutePath,
entries: details
});
} catch (error) {
return JSON.stringify({
success: false,
error: error.message,
path: directoryPath
});
}
}
function getCurrentWorkingDirectory() {
return JSON.stringify({
success: true,
cwd: process.cwd()
});
}
// ============ Web Tools Implementation ============
async function makeWebRequest(url, method = 'GET', headers = {}, data = null, followRedirects = true) {
return new Promise((resolve) => {
try {
const urlObj = new URL(url);
const isHttps = urlObj.protocol === 'https:';
const httpModule = isHttps ? https : http;
// Default headers for security testing
const defaultHeaders = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
...headers
};
if (data && (method === 'POST' || method === 'PUT')) {
defaultHeaders['Content-Length'] = Buffer.byteLength(data);
if (!defaultHeaders['Content-Type']) {
defaultHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
}
}