Skip to main content
Glama
firetix

MCP Vulnerability Checker Server

by firetix

get_vex_status

Check VEX vulnerability status to determine actual impact and exploitability for specific products using CVE IDs and optional product names.

Instructions

Check VEX vulnerability status for specific products

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cve_idYesCheck Vulnerability Exploitability eXchange (VEX) status for specific products to determine actual impact and exploitability. Provide a CVE ID in format CVE-YYYY-NNNN and optionally a product name (e.g., 'Windows 11', 'RHEL 8', 'Apache HTTP Server'). Returns vendor-provided exploitability statements, false positive filtering, and product-specific impact assessment.
productNoProduct name or identifier to check VEX status for (optional). Examples: 'Windows 11', 'RHEL 8', 'Ubuntu 22.04', 'Apache HTTP Server'

Implementation Reference

  • The main asynchronous handler function that validates CVE ID, queries NVD for vendor statements, infers VEX statuses, provides product-specific guidance, and returns formatted TextContent with comprehensive VEX report.
    async def get_vex_status(
        cve_id: str,
        product: Optional[str] = None,
    ) -> List[types.TextContent | types.ImageContent | types.EmbeddedResource]:
        """
        Check VEX (Vulnerability Exploitability eXchange) status for a CVE and product.
    
        VEX Status definitions:
        - not_affected: Product is not affected by the vulnerability
        - affected: Product is affected and vulnerable
        - fixed: Vulnerability has been fixed in the product
        - under_investigation: Vendor is investigating the impact
    
        Args:
            cve_id: CVE identifier in format CVE-YYYY-NNNN
            product: Product name or identifier (optional)
    
        Returns:
            List of content containing VEX status information or guidance
        """
        # Clean up CVE ID format
        cve_id = cve_id.upper().strip()
        if not cve_id.startswith("CVE-"):
            cve_id = f"CVE-{cve_id}"
    
        # Validate CVE ID format (CVE-YYYY-NNNN)
        if not re.match(r"^CVE-\d{4}-\d{4,}$", cve_id):
            return [
                types.TextContent(
                    type="text",
                    text=f"Error: Invalid CVE ID format. Expected format: CVE-YYYY-NNNN (e.g., CVE-2021-44228). Got: {cve_id}",
                )
            ]
    
        headers = {
            "User-Agent": "MCP VEX Status Checker v1.0",
            "Accept": "application/json",
        }
    
        vex_data = {}
        vendor_statements = []
    
        try:
            timeout = httpx.Timeout(15.0, connect=10.0)
            async with httpx.AsyncClient(
                follow_redirects=True, headers=headers, timeout=timeout
            ) as client:
                # Check 1: NVD for vendor statements and VEX-like information
                try:
                    nvd_url = (
                        f"https://services.nvd.nist.gov/rest/json/cves/2.0?cveId={cve_id}"
                    )
                    nvd_response = await client.get(nvd_url)
                    if nvd_response.status_code == 200:
                        nvd_data = nvd_response.json()
                        if nvd_data.get("totalResults", 0) > 0:
                            cve_item = nvd_data["vulnerabilities"][0]["cve"]
    
                            # Analyze references for vendor statements
                            for ref in cve_item.get("references", []):
                                url = ref.get("url", "").lower()
                                tags = ref.get("tags", [])
                                source = ref.get("source", "")
    
                                # Look for vendor statements
                                if (
                                    "vendor advisory" in tags
                                    or "vendor" in url
                                    or any(
                                        vendor in url
                                        for vendor in [
                                            "microsoft",
                                            "oracle",
                                            "redhat",
                                            "ubuntu",
                                            "debian",
                                            "apache",
                                            "cisco",
                                            "vmware",
                                        ]
                                    )
                                ):
                                    # Try to determine VEX-like status from URL/tags
                                    status = "under_investigation"  # Default
                                    confidence = "low"
    
                                    if any(
                                        keyword in url
                                        for keyword in [
                                            "patch",
                                            "fix",
                                            "update",
                                            "resolved",
                                        ]
                                    ):
                                        status = "fixed"
                                        confidence = "medium"
                                    elif any(
                                        keyword in url
                                        for keyword in [
                                            "not-affected",
                                            "unaffected",
                                            "not_affected",
                                        ]
                                    ):
                                        status = "not_affected"
                                        confidence = "high"
                                    elif any(
                                        keyword in url
                                        for keyword in ["affected", "vulnerable"]
                                    ):
                                        status = "affected"
                                        confidence = "medium"
    
                                    vendor_statements.append(
                                        {
                                            "vendor": source,
                                            "url": ref.get("url", ""),
                                            "inferred_status": status,
                                            "confidence": confidence,
                                            "tags": tags,
                                        }
                                    )
    
                            vex_data["nvd_vendor_statements"] = vendor_statements
    
                except Exception as e:
                    vex_data["nvd_error"] = str(e)
    
                # Check 2: GitHub for VEX documents (CSAF format)
                # Note: This would require GitHub API for full search
                vex_data["github_vex_search"] = {
                    "status": "manual_check_recommended",
                    "search_urls": [
                        f"https://github.com/search?q={cve_id}+VEX&type=code",
                        f"https://github.com/search?q={cve_id}+CSAF&type=code",
                        f"https://github.com/search?q={cve_id}+vulnerability+status&type=code",
                    ],
                }
    
                # Check 3: Known VEX data sources
                vex_sources = {
                    "CISA": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog",
                    "RedHat": f"https://access.redhat.com/security/cve/{cve_id}",
                    "Microsoft": f"https://msrc.microsoft.com/blog/tag/cve-{cve_id.lower()}/",
                    "Ubuntu": f"https://ubuntu.com/security/{cve_id}",
                    "Debian": f"https://security-tracker.debian.org/tracker/{cve_id}",
                }
    
                vex_data["recommended_vex_sources"] = vex_sources
    
        except Exception as e:
            return [
                types.TextContent(
                    type="text",
                    text=f"Error: Failed to check VEX status: {str(e)}",
                )
            ]
    
        # Format the response
        result = f"📋 **VEX Status Report: {cve_id}**\n"
        if product:
            result += f"🔍 **Product:** {product}\n"
        result += "\n"
    
        # VEX Overview
        result += "💡 **What is VEX?**\n"
        result += "VEX (Vulnerability Exploitability eXchange) communicates the exploitability status of vulnerabilities in specific products.\n\n"
    
        result += "📊 **VEX Status Categories:**\n"
        result += "   • 🔴 **affected** - Product is vulnerable and exploitable\n"
        result += (
            "   • 🟢 **not_affected** - Product is not affected by this vulnerability\n"
        )
        result += "   • ✅ **fixed** - Vulnerability has been patched/fixed\n"
        result += "   • 🟡 **under_investigation** - Vendor is investigating impact\n\n"
    
        # Vendor Statement Analysis
        vendor_statements = vex_data.get("nvd_vendor_statements", [])
        if vendor_statements:
            result += f"🏭 **Vendor Statements Analysis:** Found {len(vendor_statements)} vendor reference(s)\n\n"
    
            # Group by inferred status
            status_groups = {}
            for stmt in vendor_statements:
                status = stmt["inferred_status"]
                if status not in status_groups:
                    status_groups[status] = []
                status_groups[status].append(stmt)
    
            for status, statements in status_groups.items():
                status_emoji = {
                    "fixed": "✅",
                    "not_affected": "🟢",
                    "affected": "🔴",
                    "under_investigation": "🟡",
                }.get(status, "⚪")
    
                result += f"**{status_emoji} {status.replace('_', ' ').title()}:** {len(statements)} statement(s)\n"
                for stmt in statements[:3]:  # Show first 3
                    confidence_emoji = {
                        "high": "🔥",
                        "medium": "⚡",
                        "low": "💫",
                    }.get(stmt["confidence"], "❓")
                    result += f"   • {stmt.get('vendor', 'Unknown')} {confidence_emoji}\n"
                    result += f"     URL: {stmt.get('url', 'N/A')[:80]}...\n"
                if len(statements) > 3:
                    result += f"   ... and {len(statements) - 3} more\n"
                result += "\n"
        else:
            result += "🏭 **Vendor Statements:** ⚪ No vendor statements found in NVD references\n\n"
    
        # Product-specific guidance
        if product:
            result += f"🎯 **Product-Specific Guidance for '{product}':**\n"
    
            # Try to match product with known vendors
            product_lower = product.lower()
            if any(
                vendor in product_lower
                for vendor in ["microsoft", "windows", "office", "azure"]
            ):
                result += "   • Check Microsoft Security Response Center (MSRC)\n"
                result += (
                    f"   • URL: https://msrc.microsoft.com/blog/tag/{cve_id.lower()}/\n"
                )
            elif any(
                vendor in product_lower for vendor in ["redhat", "rhel", "centos", "fedora"]
            ):
                result += "   • Check Red Hat Security Portal\n"
                result += f"   • URL: https://access.redhat.com/security/cve/{cve_id}\n"
            elif any(vendor in product_lower for vendor in ["ubuntu", "canonical"]):
                result += "   • Check Ubuntu Security Notices\n"
                result += f"   • URL: https://ubuntu.com/security/{cve_id}\n"
            elif any(vendor in product_lower for vendor in ["debian"]):
                result += "   • Check Debian Security Tracker\n"
                result += (
                    f"   • URL: https://security-tracker.debian.org/tracker/{cve_id}\n"
                )
            elif any(vendor in product_lower for vendor in ["apache"]):
                result += "   • Check Apache Security Reports\n"
                result += (
                    "   • URL: https://httpd.apache.org/security/vulnerabilities_24.html\n"
                )
            else:
                result += "   • Check the vendor's security advisory page\n"
                result += f"   • Search for '{cve_id}' on the vendor's website\n"
            result += "\n"
    
        # Manual VEX Check Guidance
        result += "🔍 **Manual VEX Verification:**\n\n"
    
        vex_sources = vex_data.get("recommended_vex_sources", {})
        for source, url in vex_sources.items():
            result += f"**{source}:**\n"
            result += f"   • URL: {url}\n"
            if source == "CISA":
                result += f"   • Check if {cve_id} is in Known Exploited Vulnerabilities Catalog\n"
            else:
                result += "   • Look for VEX statements or vulnerability status\n"
            result += "\n"
    
        # GitHub VEX Search
        github_data = vex_data.get("github_vex_search", {})
        if github_data.get("search_urls"):
            result += "**🐙 GitHub VEX Document Search:**\n"
            for url in github_data["search_urls"]:
                result += f"   • {url}\n"
            result += "   • Look for CSAF/VEX documents mentioning this CVE\n\n"
    
        # Creating VEX Statements
        result += "📝 **Creating VEX Statements:**\n"
        result += "If you're a vendor/maintainer, create VEX statements using:\n"
        result += "   • **CSAF Format:** Common Security Advisory Framework\n"
        result += "   • **OpenVEX:** Simplified VEX format\n"
        result += "   • **SARIF:** Static Analysis Results Interchange Format\n\n"
    
        result += "💻 **VEX Tools:**\n"
        result += "   • OpenVEX CLI: https://github.com/openvex/vexctl\n"
        result += "   • CSAF Validator: https://github.com/csaf-poc/csaf_distribution\n"
        result += "   • VEX Hub: https://vexhub.org/\n\n"
    
        # Current VEX Ecosystem Status
        result += "🌐 **VEX Ecosystem Status:**\n"
        result += "   • 📈 **Adoption:** Growing, but still early stage\n"
        result += (
            "   • 🏢 **Major Vendors:** Microsoft, Red Hat, Google starting adoption\n"
        )
        result += "   • 🔧 **Tools:** Limited but improving tooling ecosystem\n"
        result += "   • 📋 **Standards:** CSAF 2.0, OpenVEX gaining traction\n\n"
    
        result += "⚠️ **Important Notes:**\n"
        result += (
            "   • VEX adoption is still developing - many vendors don't provide VEX yet\n"
        )
        result += "   • Manual verification of vendor advisories is still necessary\n"
        result += "   • VEX statements are authoritative only from the product vendor\n"
        result += "   • Absence of VEX statement doesn't mean product is affected\n\n"
    
        result += f"📊 **Report Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
    
        return [types.TextContent(type="text", text=result)]
  • MCP tool schema registration defining the input parameters: required 'cve_id' (string) and optional 'product' (string), with detailed descriptions.
    types.Tool(
        name="get_vex_status",
        description="Check VEX vulnerability status for specific products",
        inputSchema={
            "type": "object",
            "required": ["cve_id"],
            "properties": {
                "cve_id": {
                    "type": "string",
                    "description": vex_description,
                },
                "product": {
                    "type": "string",
                    "description": "Product name or identifier to check VEX status for (optional). Examples: 'Windows 11', 'RHEL 8', 'Ubuntu 22.04', 'Apache HTTP Server'",
                },
            },
        },
    ),
  • Tool dispatch logic in the @app.call_tool() handler that validates arguments and calls the get_vex_status function.
    elif name == "get_vex_status":
        if "cve_id" not in arguments:
            return [
                types.TextContent(
                    type="text", text="Error: Missing required argument 'cve_id'"
                )
            ]
        product = arguments.get("product")  # Optional parameter
        return await get_vex_status(arguments["cve_id"], product)
Behavior2/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 but offers minimal information. It states what the tool does but doesn't describe response format, error conditions, rate limits, authentication requirements, or whether this is a read-only operation. For a tool with no annotation coverage, this leaves significant behavioral gaps.

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

Conciseness5/5

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

The description is extremely concise at just 8 words, front-loading the core purpose without unnecessary elaboration. Every word earns its place - 'Check' (verb), 'VEX vulnerability status' (what), 'for specific products' (scope). There's zero waste or redundancy in this single-sentence description.

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

Completeness2/5

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

For a tool with no annotations, no output schema, and 2 parameters, the description is insufficiently complete. It doesn't explain what VEX status entails, what format the response takes, whether this queries external databases, or what distinguishes VEX from other vulnerability assessments. Given the technical nature of vulnerability management and the lack of structured metadata, the description should provide more context.

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?

Schema description coverage is 100%, so the schema already fully documents both parameters. The description doesn't add any parameter semantics beyond what's in the schema - it mentions CVE ID and product name but provides no additional context about format requirements, validation rules, or usage patterns. Baseline 3 is appropriate when schema does all the parameter documentation work.

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

Purpose4/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 a specific verb ('Check') and resource ('VEX vulnerability status for specific products'). It distinguishes from siblings like 'cve_lookup' or 'search_vulnerabilities' by focusing on VEX status rather than general vulnerability information. However, it doesn't explicitly differentiate from all siblings in the description text itself.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'cve_lookup' or 'get_exploit_availability'. It mentions checking VEX status but doesn't explain when this is preferable to other vulnerability assessment tools. There's no mention of prerequisites, limitations, or specific contexts where this tool is most appropriate.

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/firetix/vulnerability-intelligence-mcp-server'

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