Skip to main content
Glama

check_vulnerabilities

Scan project dependencies for security vulnerabilities using OSV.dev database. Choose scan modes for detailed reports, quick overviews, or critical issues only.

Instructions

Scans project dependencies (package.json, composer.json) for known security vulnerabilities using the OSV.dev database. Supports multiple scan modes: 'full' for detailed reports, 'summary' for quick overview, 'critical-high-only' for auto-scans showing only actionable issues. Use this tool when: user asks about security/vulnerabilities, after package installations (npm install, composer update), before commits/builds, or when starting work in a new project with dependency files.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_pathNoPath to project directory (default: current directory)
file_typeNoWhich file(s) to check (default: both)
scan_modeNoOutput detail level: 'full' shows all vulnerabilities with details, 'summary' shows only counts, 'critical-high-only' shows detailed info for CRITICAL/HIGH only (default: full)

Implementation Reference

  • Handler for the check_vulnerabilities tool call. Extracts parameters (project_path, file_type, scan_mode), invokes appropriate scanning functions for package.json and/or composer.json, and returns formatted markdown results.
    if (request.params.name === "check_vulnerabilities") {
      const projectPath =
        (request.params.arguments?.project_path as string) || process.cwd();
      const fileType =
        (request.params.arguments?.file_type as string) || "both";
      const scanMode =
        (request.params.arguments?.scan_mode as ScanMode) || "full";
    
      let result = "";
    
      if (fileType === "package.json" || fileType === "both") {
        result += await checkPackageJson(projectPath, scanMode);
        result += "\n\n";
      }
    
      if (fileType === "composer.json" || fileType === "both") {
        result += await checkComposerJson(projectPath, scanMode);
      }
    
      return {
        content: [
          {
            type: "text",
            text: result,
          },
        ],
      };
    }
  • JSON schema defining the input parameters for the check_vulnerabilities tool: project_path (string), file_type (enum), scan_mode (enum).
    inputSchema: {
      type: "object",
      properties: {
        project_path: {
          type: "string",
          description:
            "Path to project directory (default: current directory)",
        },
        file_type: {
          type: "string",
          enum: ["package.json", "composer.json", "both"],
          description: "Which file(s) to check (default: both)",
        },
        scan_mode: {
          type: "string",
          enum: ["full", "summary", "critical-high-only"],
          description:
            "Output detail level: 'full' shows all vulnerabilities with details, " +
            "'summary' shows only counts, 'critical-high-only' shows detailed info for CRITICAL/HIGH only (default: full)",
        },
      },
    },
  • src/index.ts:407-436 (registration)
    Tool registration in the ListTools response, including name, description, and reference to inputSchema.
    {
      name: "check_vulnerabilities",
      description:
        "Scans project dependencies (package.json, composer.json) for known security vulnerabilities using the OSV.dev database. " +
        "Supports multiple scan modes: 'full' for detailed reports, 'summary' for quick overview, 'critical-high-only' for auto-scans showing only actionable issues. " +
        "Use this tool when: user asks about security/vulnerabilities, after package installations (npm install, composer update), " +
        "before commits/builds, or when starting work in a new project with dependency files.",
      inputSchema: {
        type: "object",
        properties: {
          project_path: {
            type: "string",
            description:
              "Path to project directory (default: current directory)",
          },
          file_type: {
            type: "string",
            enum: ["package.json", "composer.json", "both"],
            description: "Which file(s) to check (default: both)",
          },
          scan_mode: {
            type: "string",
            enum: ["full", "summary", "critical-high-only"],
            description:
              "Output detail level: 'full' shows all vulnerabilities with details, " +
              "'summary' shows only counts, 'critical-high-only' shows detailed info for CRITICAL/HIGH only (default: full)",
          },
        },
      },
    },
  • Helper function that scans package.json for dependencies, queries OSV API for vulnerabilities, counts by severity, and generates markdown report based on scan mode.
    async function checkPackageJson(
      projectPath: string,
      mode: ScanMode
    ): Promise<string> {
      try {
        const packageJsonPath = path.join(projectPath, "package.json");
        const content = await fs.readFile(packageJsonPath, "utf-8");
        const packageJson = JSON.parse(content);
    
        const allDeps = {
          ...packageJson.dependencies,
          ...packageJson.devDependencies,
        };
    
        let results = "# Security Scan Results (package.json)\n\n";
        let criticalCount = 0;
        let highCount = 0;
        let moderateCount = 0;
        let lowCount = 0;
    
        const allVulnerabilities: Array<{
          packageName: string;
          version: string;
          vulnerabilities: Vulnerability[];
        }> = [];
    
        for (const [packageName, versionRange] of Object.entries(allDeps)) {
          // Extract version from range (simplified - remove ^~>=< symbols)
          const version = (versionRange as string).replace(/[\^~>=<]/g, "");
    
          const vulnerabilities = await checkVulnerability(
            packageName,
            version,
            "npm"
          );
    
          if (vulnerabilities.length > 0) {
            allVulnerabilities.push({ packageName, version, vulnerabilities });
    
            for (const vuln of vulnerabilities) {
              const severity = vuln.severity.toUpperCase();
              if (severity.includes("CRITICAL")) criticalCount++;
              else if (severity.includes("HIGH")) highCount++;
              else if (severity.includes("MODERATE")) moderateCount++;
              else lowCount++;
            }
          }
        }
    
        // Summary mode: just show counts
        if (mode === "summary") {
          const total = criticalCount + highCount + moderateCount + lowCount;
          if (total === 0) {
            results += "\nāœ… **No known security vulnerabilities found!**\n";
          } else {
            results += `## šŸ“Š Summary\n`;
            results += `- šŸ”“ Critical: ${criticalCount}\n`;
            results += `- 🟠 High: ${highCount}\n`;
            results += `- 🟔 Moderate: ${moderateCount}\n`;
            results += `- 🟢 Low: ${lowCount}\n`;
            results += `\n**Total vulnerabilities found: ${total}**\n\n`;
            results += `Run with scan_mode="full" for detailed information.\n`;
          }
          return results;
        }
    
        // Full or critical-high-only mode: show details
        for (const { packageName, version, vulnerabilities } of allVulnerabilities) {
          results += formatVulnerabilities(
            vulnerabilities,
            packageName,
            version,
            mode
          );
        }
    
        // Summary section
        const total = criticalCount + highCount + moderateCount + lowCount;
        if (total === 0) {
          results += "\nāœ… **No known security vulnerabilities found!**\n";
        } else {
          results += `\n## šŸ“Š Summary\n`;
          if (mode === "critical-high-only") {
            results += `- šŸ”“ Critical: ${criticalCount}\n`;
            results += `- 🟠 High: ${highCount}\n`;
            if (moderateCount + lowCount > 0) {
              results += `\n_Also found ${moderateCount + lowCount} moderate/low severity issues (hidden in this mode)._\n`;
              results += `_Run with scan_mode="full" to see all vulnerabilities._\n`;
            }
          } else {
            results += `- šŸ”“ Critical: ${criticalCount}\n`;
            results += `- 🟠 High: ${highCount}\n`;
            results += `- 🟔 Moderate: ${moderateCount}\n`;
            results += `- 🟢 Low: ${lowCount}\n`;
            results += `\n**Total vulnerabilities found: ${total}**\n`;
          }
        }
    
        return results;
      } catch (error) {
        if ((error as NodeJS.ErrnoException).code === "ENOENT") {
          return "āŒ package.json file not found in this directory.";
        }
        throw error;
      }
    }
  • Core helper that queries the OSV.dev API for vulnerabilities in a specific package/version/ecosystem and maps results to standardized Vulnerability interface.
    async function checkVulnerability(
      packageName: string,
      version: string,
      ecosystem: string
    ): Promise<Vulnerability[]> {
      try {
        const response = await fetch("https://api.osv.dev/v1/query", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            package: {
              name: packageName,
              ecosystem: ecosystem,
            },
            version: version,
          }),
        });
    
        if (!response.ok) {
          throw new Error(`OSV API error: ${response.statusText}`);
        }
    
        const data = (await response.json()) as OSVResponse;
    
        if (!data.vulns || data.vulns.length === 0) {
          return [];
        }
    
        return data.vulns.map((vuln) => {
          let severity = "UNKNOWN";
    
          // Try to get severity from different sources
          if (vuln.database_specific?.severity) {
            severity = vuln.database_specific.severity;
          } else if (vuln.severity && vuln.severity.length > 0) {
            // CVSS score parsing
            const cvss = vuln.severity.find((s) => s.type === "CVSS_V3");
            if (cvss) {
              const score = parseFloat(cvss.score.split("/")[0] || "0");
              if (score >= 9.0) severity = "CRITICAL";
              else if (score >= 7.0) severity = "HIGH";
              else if (score >= 4.0) severity = "MODERATE";
              else severity = "LOW";
            }
          }
    
          return {
            id: vuln.id,
            summary: vuln.summary || "No description available",
            severity: severity,
            references: vuln.references || [],
            package_name: packageName,
            affected_versions: [version],
          };
        });
      } catch (error) {
        console.error(`Error checking ${packageName}:`, error);
        return [];
      }
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior by explaining the different scan modes ('full', 'summary', 'critical-high-only') and their outputs, and mentions it uses the OSV.dev database. However, it lacks details on potential side effects, error handling, or performance characteristics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the core purpose, followed by usage guidelines. It is appropriately sized, but could be slightly more concise by integrating the usage scenarios more tightly with the initial explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (3 parameters, no output schema, no annotations), the description does a good job covering purpose, usage, and behavior. However, it lacks information on output format or error handling, which would be helpful for an AI agent to understand what to expect from the tool's execution.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds some context by mentioning 'project dependencies' and 'multiple scan modes', but does not provide additional semantic details beyond what the schema specifies. This meets the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('scans project dependencies') and resources ('package.json, composer.json'), and distinguishes its function by mentioning the OSV.dev database. It explicitly lists what it does without being tautological or vague.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use the tool, listing specific scenarios such as 'user asks about security/vulnerabilities', 'after package installations', 'before commits/builds', and 'when starting work in a new project with dependency files'. This gives clear context for usage without alternatives needed since no sibling tools exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/Kalvisan/guardian-mcp'

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