generateWordlist
Create custom password wordlists for penetration testing by combining base words with dates, patterns, and variations to generate targeted credential attack dictionaries.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| baseWords | Yes | List of base words (names, pets, places, etc.). | |
| dates | No | List of dates (YYYY-MM-DD, MM-DD, YYYY). Parsed for variations. | |
| customPatterns | No | List of custom patterns/symbols to prepend/append (e.g., '!', '123'). | |
| minYear | No | Minimum year (YYYY) to include in variations. | |
| maxYear | No | Maximum year (YYYY) to include in variations (defaults to current year). | |
| includeLeet | No | Apply basic leetspeak substitutions (a=4, e=3, etc.). | |
| caseVariations | No | Include variations like TitleCase, UPPERCASE. |
Implementation Reference
- src/index.ts:605-613 (registration)Capabilities declaration where 'generateWordlist' tool is registered for discovery by MCP clients."setMode": {}, "generateWordlist": {}, "cancelScan": {}, "createClientReport": {}, "nmapScan": {}, "runJohnTheRipper": {}, "runHashcat": {}, "gobuster": {}, "nikto": {}
- src/index.ts:777-787 (schema)Zod schema defining input parameters and validation for the generateWordlist tool.baseWords: z.array(z.string()).describe("List of base words (names, pets, places, etc.)."), dates: z.array(z.string()).optional().describe("List of dates (YYYY-MM-DD, MM-DD, YYYY). Parsed for variations."), customPatterns: z.array(z.string()).optional().describe("List of custom patterns/symbols to prepend/append (e.g., '!', '123')."), minYear: z.number().int().optional().describe("Minimum year (YYYY) to include in variations."), maxYear: z.number().int().optional().describe("Maximum year (YYYY) to include in variations (defaults to current year)."), includeLeet: z.boolean().optional().default(false).describe("Apply basic leetspeak substitutions (a=4, e=3, etc.)."), caseVariations: z.boolean().optional().default(true).describe("Include variations like TitleCase, UPPERCASE.") }).describe( "Generate a custom password wordlist from target-related words. " + "Use this before running John the Ripper. Example: `{\"baseWords\":[\"Acme\",\"Smith\"],\"dates\":[\"1984\"],\"customPatterns\":[\"!\"]}`" );
- src/index.ts:788-829 (handler)The core handler function that implements the generateWordlist tool logic: generates variations from base words, dates, patterns; applies case and leetspeak transformations; combines prefixes/suffixes; writes unique entries to a temp file and returns path.server.tool("generateWordlist", generateWordlistSchema.shape, async ({ baseWords, dates, customPatterns, minYear, maxYear, includeLeet, caseVariations } /*, extra */) => { console.error(`Received generateWordlist:`, { baseWords: `${baseWords.length} words`, dates, customPatterns }); await ensureTempWordlistDirExists(); const wordlist = new Set<string>(); const currentYear = new Date().getFullYear(); const resolvedMinYear = minYear || currentYear - 10; const resolvedMaxYear = maxYear || currentYear; const years: string[] = []; for (let y = resolvedMinYear; y <= resolvedMaxYear; y++) { years.push(String(y)); years.push(String(y).slice(-2)); } const dateVariations: string[] = []; if (dates) { dates.forEach(dateStr => { const parts = dateStr.split(/[-/]/); if (parts.length === 3) { dateVariations.push(parts[0], parts[0].slice(-2), parts[1], parts[2], parts[1]+parts[2], parts[1]+parts[2]+parts[0], parts[1]+parts[2]+parts[0].slice(-2)); } else if (parts.length === 2) { dateVariations.push(parts[0], parts[1], parts[0]+parts[1]); } else if (parts.length === 1 && parts[0].length === 4) { dateVariations.push(parts[0], parts[0].slice(-2)); } }); } const patterns = customPatterns || []; const suffixes = [...patterns, ...years, ...dateVariations]; const prefixes = [...patterns]; baseWords.forEach(base => { const variations = new Set<string>([base]); if (caseVariations) { variations.add(base.toLowerCase()); variations.add(base.toUpperCase()); variations.add(base.charAt(0).toUpperCase() + base.slice(1).toLowerCase()); } if (includeLeet) { const leetBase = toLeet(base); variations.add(leetBase); if (caseVariations) { /* add leet cases */ variations.add(leetBase.toLowerCase()); variations.add(leetBase.toUpperCase()); variations.add(leetBase.charAt(0).toUpperCase() + leetBase.slice(1).toLowerCase()); } } variations.forEach(v => { wordlist.add(v); prefixes.forEach(p => { wordlist.add(p + v); }); suffixes.forEach(s => { wordlist.add(v + s); }); prefixes.forEach(p => { suffixes.forEach(s => { wordlist.add(p + v + s); }); }); }); }); [...years, ...dateVariations].forEach(dv => wordlist.add(dv)); const filename = `wordlist_${Date.now()}.txt`; const filePath = path.join(TEMP_WORDLIST_DIR, filename); try { await fs.writeFile(filePath, Array.from(wordlist).join('\n')); return { content: [ { type: "text", text: `Generated ${wordlist.size} words.` }, { type: "text", text: `Path: ${filePath}` } ] }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true }; } });
- src/index.ts:510-512 (helper)Helper function toLeet() applies basic leetspeak substitutions, used when includeLeet is true.function toLeet(word: string): string { return word.replace(/a/gi, '4').replace(/e/gi, '3').replace(/i/gi, '1').replace(/o/gi, '0').replace(/s/gi, '5').replace(/t/gi, '7'); }
- src/index.ts:502-508 (helper)Helper function to ensure the temporary wordlist directory exists before writing files.async function ensureTempWordlistDirExists(): Promise<void> { try { await fs.mkdir(TEMP_WORDLIST_DIR, { recursive: true }); } catch (error) { console.error('Error creating temp wordlist directory:', error); } }