gobuster
Discover hidden files and directories on web servers by brute-forcing paths using custom wordlists to identify potential security vulnerabilities.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Target URL | |
| wordlist | Yes | Path to wordlist | |
| extensions | No | File extensions (comma-separated) | |
| threads | No | Number of threads | |
| statusCodes | No | Valid status codes (comma-separated) | |
| useragent | No | User-Agent string | |
| timeout | No | Timeout for requests | |
| basicAuth | No | Basic authentication credentials (username:password) | |
| cookie | No | Cookie to include in requests | |
| excludeLength | No | Exclude paths of specific lengths | |
| followRedirect | No | Follow HTTP redirects | |
| noTLSValidation | No | Skip TLS certificate validation | |
| rawOptions | No | Raw gobuster options |
Implementation Reference
- src/index.ts:515-550 (handler)Core implementation of the gobuster tool handler. Spawns the 'gobuster' process with sanitized options, captures stdout/stderr, parses lines for successful HTTP status codes (200,301,302) to extract discovered paths, logs results in professional mode, and returns full output along with found paths.async function runGobuster(target: string, rawOptions: string[] = []): Promise<{ fullOutput: string; foundPaths: string[] }> { console.error(`Executing Gobuster: target=${target}, raw_options=${rawOptions.join(' ')}`); if (!target.startsWith('http://') && !target.startsWith('https://')) { throw new Error("Target must be a valid URL starting with http:// or https://"); } let options: string[]; try { options = sanitizeOptions(rawOptions); } catch (error: any) { throw error; } let fullOutput = ""; let foundPaths: string[] = []; try { const baseArgs = ['dir', '-u', target, ...options]; fullOutput += `--- Directory Enumeration ---\nExecuting: gobuster ${baseArgs.join(' ')}\n`; try { const result = await runSpawnCommand('gobuster', baseArgs); fullOutput += `Exit Code: ${result.code}\nStdout:\n${result.stdout}\nStderr:\n${result.stderr}\n`; foundPaths = result.stdout.split('\n').filter(line => line.includes('Status:') && (line.includes('200') || line.includes('301') || line.includes('302'))).map(line => line.match(/^\s*(\/[^\s]*)/)?.[1] || line); } catch (error: any) { fullOutput += `Gobuster command failed to execute: ${error.message}\n`; } if (currentUserSession.mode === UserMode.PROFESSIONAL) { await logMessage(`Ran Gobuster against ${target}.\nOptions: ${options.join(' ')}\nFound: ${foundPaths.length} paths.`); } return { fullOutput, foundPaths }; } catch (error: any) { console.error("Fatal error setting up Gobuster execution:", error); if (currentUserSession.mode === UserMode.PROFESSIONAL) { await logMessage(`Gobuster FAILED fatally before execution.\nTarget: ${target}\nOptions: ${options.join(' ')}\nError: ${error.message}`); } throw new Error(`Gobuster setup failed fatally: ${error.message}`); } }
- src/index.ts:1090-1107 (schema)Zod schema defining the input validation and descriptions for the gobuster tool parameters, including required target URL and wordlist, and various optional gobuster-specific options.const gobusterToolSchema = z.object({ target: z.string().url().describe("Target URL"), wordlist: z.string().describe("Path to wordlist"), extensions: z.string().optional().describe("File extensions (comma-separated)"), threads: z.number().int().positive().optional().describe("Number of threads"), statusCodes: z.string().optional().describe("Valid status codes (comma-separated)"), useragent: z.string().optional().describe("User-Agent string"), timeout: z.string().optional().describe("Timeout for requests"), basicAuth: z.string().optional().describe("Basic authentication credentials (username:password)"), cookie: z.string().optional().describe("Cookie to include in requests"), excludeLength: z.array(z.number()).optional().describe("Exclude paths of specific lengths"), followRedirect: z.boolean().optional().describe("Follow HTTP redirects"), noTLSValidation: z.boolean().optional().describe("Skip TLS certificate validation"), rawOptions: z.array(z.string()).optional().describe("Raw gobuster options") }).describe( "Enumerate hidden directories and files on a web server. Run this after confirming the target hosts a web service. " + "Provide a wordlist and optional extensions. Example: `{\"target\":\"http://example.com\", \"wordlist\":\"/usr/share/wordlists/common.txt\"}`" );
- src/index.ts:1108-1139 (registration)MCP tool registration using server.tool('gobuster'), which constructs gobuster command-line options from input parameters, calls the runGobuster handler, formats response differently for student/professional modes, and handles errors.server.tool("gobuster", gobusterToolSchema.shape, async (args /*: z.infer<typeof gobusterToolSchema> */ /*, extra */) => { const { target, wordlist, extensions, threads, statusCodes, useragent, timeout, basicAuth, cookie, excludeLength, followRedirect, noTLSValidation, rawOptions } = args; console.error(`Received gobuster request:`, args); try { const constructedOptions: string[] = []; constructedOptions.push('-w', wordlist); if (extensions) constructedOptions.push('-x', extensions); if (threads) constructedOptions.push('-t', threads.toString()); if (statusCodes) constructedOptions.push('-s', statusCodes); if (useragent) constructedOptions.push('-a', useragent); if (timeout) constructedOptions.push('--timeout', timeout); if (basicAuth) { const [u,p] = basicAuth.split(':'); constructedOptions.push('-U', u, '-P', p); } if (cookie) constructedOptions.push('-c', cookie); if (excludeLength) constructedOptions.push('-l', excludeLength.join(',')); if (followRedirect) constructedOptions.push('-r'); if (noTLSValidation) constructedOptions.push('-k'); if (rawOptions) constructedOptions.push(...rawOptions); const { fullOutput, foundPaths } = await runGobuster(target, constructedOptions); const responseContent: any[] = []; if (currentUserSession.mode === UserMode.STUDENT) { responseContent.push({ type: "text", text: `Found ${foundPaths.length} paths/files at ${target}:\n\n${foundPaths.join('\n')}` }); if (foundPaths.length > 0) responseContent.push({ type: "text", text: "\n**Next Steps:** ..." }); else responseContent.push({ type: "text", text: "\n**No paths found...**" }); } else { responseContent.push({ type: "text", text: `Found ${foundPaths.length} paths at ${target}` }); if (foundPaths.length > 0) responseContent.push({ type: "text", text: "\n**Paths:**\n" + foundPaths.join('\n') }); responseContent.push({ type: "text", text: "\n**Full Output:**\n" + fullOutput }); } return { content: responseContent }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } });
- src/index.ts:273-291 (helper)Helper function to spawn external commands (like gobuster) using child_process.spawn, capture stdout/stderr, handle errors, and return results. Used by gobuster, nikto, john, hashcat handlers.async function runSpawnCommand(command: string, args: string[]): Promise<{ stdout: string; stderr: string; code: number | null }> { return new Promise((resolve, reject) => { console.error(`Attempting to spawn: ${command} ${args.join(' ')}`); // Added for debugging const process = spawn(command, args); let stdout = ''; let stderr = ''; process.stdout.on('data', (data) => { stdout += data.toString(); }); process.stderr.on('data', (data) => { stderr += data.toString(); }); process.on('error', (error) => { // Explicitly catch spawn errors (e.g., command not found) console.error(`Spawn error for command "${command}": ${error.message}`); reject(new Error(`Failed to start command "${command}": ${error.message}`)); }); process.on('close', (code) => { console.error(`Command "${command}" exited with code ${code}`); // Added for debugging resolve({ stdout, stderr, code }); }); }); }
- src/index.ts:258-270 (helper)Helper function to sanitize and validate command-line options passed to tools like gobuster, preventing injection of unsafe arguments via regex matching safe patterns.const SAFE_OPTION_REGEX = /^(?:-[a-zA-Z0-9]+|--[a-zA-Z0-9\-]+(?:=[^;&|`$\s\(\)\<\>\\]+)?|[^;&|`$\s\(\)\<\>\\]+)$/; function sanitizeOptions(options: string[]): string[] { const sanitized: string[] = []; for (const opt of options) { if (SAFE_OPTION_REGEX.test(opt)) { sanitized.push(opt); } else { throw new Error(`Invalid or potentially unsafe option detected: "${opt}". Only standard flags and simple arguments are allowed.`); } } return sanitized; }