js.extract_secrets
Extract potential API keys, tokens, and secrets from JavaScript source code to identify security vulnerabilities in applications.
Instructions
Heuristically extract potential API keys, tokens, and secrets from JS
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | JavaScript source code |
Implementation Reference
- src/tools/js.ts:144-227 (handler)The handler function for 'js.extract_secrets' that uses regex patterns to detect and extract API keys, tokens, AWS keys, Google keys, and potential secret candidates from JavaScript source code.async ({ source }: any): Promise<ToolResult> => { try { const secrets: any = { apiKeys: [], tokens: [], passwords: [], awsKeys: [], googleKeys: [], candidates: [], }; // API Key patterns const apiKeyPatterns = [ /(?:api[_-]?key|apikey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, /(?:secret[_-]?key|secretkey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, ]; // Token patterns const tokenPatterns = [ /(?:token|access[_-]?token)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, /(?:bearer|authorization)[\s:]+["'`]?([A-Za-z0-9_\-\.]{20,})["'`]?/gi, ]; // AWS keys const awsPattern = /AKIA[0-9A-Z]{16}/g; // Google API keys const googlePattern = /AIza[0-9A-Za-z\-_]{35}/g; // Extract matches apiKeyPatterns.forEach((pattern) => { let match: RegExpExecArray | null; while ((match = pattern.exec(source)) !== null) { secrets.apiKeys.push(match[1]); } }); tokenPatterns.forEach((pattern) => { let match: RegExpExecArray | null; while ((match = pattern.exec(source)) !== null) { secrets.tokens.push(match[1]); } }); const awsMatches = source.match(awsPattern) || []; secrets.awsKeys = Array.from(new Set(awsMatches)); const googleMatches = source.match(googlePattern) || []; secrets.googleKeys = Array.from(new Set(googleMatches)); // General long strings that might be secrets const candidatePattern = /["'`]([A-Za-z0-9_\-]{32,})["'`]/g; let candidateMatch: RegExpExecArray | null; while ((candidateMatch = candidatePattern.exec(source)) !== null) { const candidate = candidateMatch[1]; // Filter out URLs and common false positives if ( !candidate.startsWith('http') && !candidate.includes('/') && candidate.length < 200 ) { secrets.candidates.push(candidate); } } // Deduplicate secrets.apiKeys = Array.from(new Set(secrets.apiKeys)); secrets.tokens = Array.from(new Set(secrets.tokens)); secrets.candidates = Array.from(new Set(secrets.candidates)).slice(0, 50); return formatToolResult(true, { ...secrets, summary: { totalApiKeys: secrets.apiKeys.length, totalTokens: secrets.tokens.length, totalAwsKeys: secrets.awsKeys.length, totalGoogleKeys: secrets.googleKeys.length, totalCandidates: secrets.candidates.length, }, }); } catch (error: any) { return formatToolResult(false, null, error.message); } }
- src/tools/js.ts:133-228 (registration)Registration of the 'js.extract_secrets' tool via server.tool call, including description, input schema, and inline handler function.'js.extract_secrets', { description: 'Heuristically extract potential API keys, tokens, and secrets from JS', inputSchema: { type: 'object', properties: { source: { type: 'string', description: 'JavaScript source code' }, }, required: ['source'], }, }, async ({ source }: any): Promise<ToolResult> => { try { const secrets: any = { apiKeys: [], tokens: [], passwords: [], awsKeys: [], googleKeys: [], candidates: [], }; // API Key patterns const apiKeyPatterns = [ /(?:api[_-]?key|apikey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, /(?:secret[_-]?key|secretkey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, ]; // Token patterns const tokenPatterns = [ /(?:token|access[_-]?token)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi, /(?:bearer|authorization)[\s:]+["'`]?([A-Za-z0-9_\-\.]{20,})["'`]?/gi, ]; // AWS keys const awsPattern = /AKIA[0-9A-Z]{16}/g; // Google API keys const googlePattern = /AIza[0-9A-Za-z\-_]{35}/g; // Extract matches apiKeyPatterns.forEach((pattern) => { let match: RegExpExecArray | null; while ((match = pattern.exec(source)) !== null) { secrets.apiKeys.push(match[1]); } }); tokenPatterns.forEach((pattern) => { let match: RegExpExecArray | null; while ((match = pattern.exec(source)) !== null) { secrets.tokens.push(match[1]); } }); const awsMatches = source.match(awsPattern) || []; secrets.awsKeys = Array.from(new Set(awsMatches)); const googleMatches = source.match(googlePattern) || []; secrets.googleKeys = Array.from(new Set(googleMatches)); // General long strings that might be secrets const candidatePattern = /["'`]([A-Za-z0-9_\-]{32,})["'`]/g; let candidateMatch: RegExpExecArray | null; while ((candidateMatch = candidatePattern.exec(source)) !== null) { const candidate = candidateMatch[1]; // Filter out URLs and common false positives if ( !candidate.startsWith('http') && !candidate.includes('/') && candidate.length < 200 ) { secrets.candidates.push(candidate); } } // Deduplicate secrets.apiKeys = Array.from(new Set(secrets.apiKeys)); secrets.tokens = Array.from(new Set(secrets.tokens)); secrets.candidates = Array.from(new Set(secrets.candidates)).slice(0, 50); return formatToolResult(true, { ...secrets, summary: { totalApiKeys: secrets.apiKeys.length, totalTokens: secrets.tokens.length, totalAwsKeys: secrets.awsKeys.length, totalGoogleKeys: secrets.googleKeys.length, totalCandidates: secrets.candidates.length, }, }); } catch (error: any) { return formatToolResult(false, null, error.message); } } );
- src/tools/js.ts:136-142 (schema)Input schema for the tool, requiring a 'source' field containing the JavaScript code to analyze.inputSchema: { type: 'object', properties: { source: { type: 'string', description: 'JavaScript source code' }, }, required: ['source'], },