Skip to main content
Glama

js.analyze

Analyze JavaScript files to extract endpoints and secrets for security testing and vulnerability assessment.

Instructions

Download, beautify, and analyze a JavaScript file - extract endpoints and secrets

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesURL of the JS file to analyze

Implementation Reference

  • Handler function for 'js.analyze' tool: Downloads JS from URL using axios, beautifies with js-beautify, extracts endpoints (URLs and paths) using regex, extracts API keys using regex patterns, stores analysis in Redis via setWorkingMemory, returns formatted result with summary.
    async ({ url }: any): Promise<ToolResult> => {
      try {
        // Download
        let source: string;
        try {
          const response = await axios.get(url, {
            timeout: 30000,
            headers: {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            },
          });
          source = response.data;
        } catch (error: any) {
          return formatToolResult(false, null, `Failed to download: ${error.message}`);
        }
    
        // Beautify
        let beautified: string;
        try {
          beautified = beautify.js(source, {
            indent_size: 2,
            space_in_empty_paren: true,
            preserve_newlines: true,
          });
        } catch {
          beautified = source;
        }
    
        // Find endpoints
        const urlRegex = /\bhttps?:\/\/[\w\-\.:%]+[\w\-\/_\.\?\=\%\&\#]*/g;
        const urls = Array.from(new Set(beautified.match(urlRegex) || []));
        const pathRegex = /["'`](\/[-a-zA-Z0-9_@:\/\.]+)["'`]/g;
        const paths: string[] = [];
        let match: RegExpExecArray | null;
        while ((match = pathRegex.exec(beautified)) !== null) {
          paths.push(match[1]);
        }
        const endpoints = {
          urls,
          paths: Array.from(new Set(paths)),
        };
    
        // Extract secrets (simplified)
        const secrets: any = {
          apiKeys: [],
          tokens: [],
          candidates: [],
        };
        const apiKeyPattern = /(?:api[_-]?key|apikey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi;
        let keyMatch: RegExpExecArray | null;
        while ((keyMatch = apiKeyPattern.exec(beautified)) !== null) {
          secrets.apiKeys.push(keyMatch[1]);
        }
        secrets.apiKeys = Array.from(new Set(secrets.apiKeys));
    
        await setWorkingMemory(`js:analysis:${url}`, {
          endpoints,
          secrets,
        }, 7200);
    
        return formatToolResult(true, {
          url,
          endpoints,
          secrets,
          summary: {
            endpointsFound: (endpoints.urls?.length || 0) + (endpoints.paths?.length || 0),
            secretsFound: (secrets.apiKeys?.length || 0) + (secrets.tokens?.length || 0),
          },
        });
      } catch (error: any) {
        return formatToolResult(false, null, error.message);
      }
    }
  • Input schema and description for the 'js.analyze' tool: requires a single 'url' string parameter.
      description: 'Download, beautify, and analyze a JavaScript file - extract endpoints and secrets',
      inputSchema: {
        type: 'object',
        properties: {
          url: { type: 'string', description: 'URL of the JS file to analyze' },
        },
        required: ['url'],
      },
    },
  • Registers the 'js.analyze' tool within the registerJsTools function using server.tool(name, schema, handler). This function is called from src/index.ts.
    server.tool(
      'js.analyze',
      {
        description: 'Download, beautify, and analyze a JavaScript file - extract endpoints and secrets',
        inputSchema: {
          type: 'object',
          properties: {
            url: { type: 'string', description: 'URL of the JS file to analyze' },
          },
          required: ['url'],
        },
      },
      async ({ url }: any): Promise<ToolResult> => {
        try {
          // Download
          let source: string;
          try {
            const response = await axios.get(url, {
              timeout: 30000,
              headers: {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
              },
            });
            source = response.data;
          } catch (error: any) {
            return formatToolResult(false, null, `Failed to download: ${error.message}`);
          }
    
          // Beautify
          let beautified: string;
          try {
            beautified = beautify.js(source, {
              indent_size: 2,
              space_in_empty_paren: true,
              preserve_newlines: true,
            });
          } catch {
            beautified = source;
          }
    
          // Find endpoints
          const urlRegex = /\bhttps?:\/\/[\w\-\.:%]+[\w\-\/_\.\?\=\%\&\#]*/g;
          const urls = Array.from(new Set(beautified.match(urlRegex) || []));
          const pathRegex = /["'`](\/[-a-zA-Z0-9_@:\/\.]+)["'`]/g;
          const paths: string[] = [];
          let match: RegExpExecArray | null;
          while ((match = pathRegex.exec(beautified)) !== null) {
            paths.push(match[1]);
          }
          const endpoints = {
            urls,
            paths: Array.from(new Set(paths)),
          };
    
          // Extract secrets (simplified)
          const secrets: any = {
            apiKeys: [],
            tokens: [],
            candidates: [],
          };
          const apiKeyPattern = /(?:api[_-]?key|apikey)[\s:=]+["'`]([A-Za-z0-9_\-]{20,})["'`]/gi;
          let keyMatch: RegExpExecArray | null;
          while ((keyMatch = apiKeyPattern.exec(beautified)) !== null) {
            secrets.apiKeys.push(keyMatch[1]);
          }
          secrets.apiKeys = Array.from(new Set(secrets.apiKeys));
    
          await setWorkingMemory(`js:analysis:${url}`, {
            endpoints,
            secrets,
          }, 7200);
    
          return formatToolResult(true, {
            url,
            endpoints,
            secrets,
            summary: {
              endpointsFound: (endpoints.urls?.length || 0) + (endpoints.paths?.length || 0),
              secretsFound: (secrets.apiKeys?.length || 0) + (secrets.tokens?.length || 0),
            },
          });
        } catch (error: any) {
          return formatToolResult(false, null, error.message);
        }
      }
    );
  • src/index.ts:36-36 (registration)
    Top-level call to registerJsTools(server) in the main server initialization, which registers js.analyze and other JS tools.
    registerJsTools(server);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/telmon95/VulneraMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server