Skip to main content
Glama
SlanyCukr

Bug Bounty MCP Server

by SlanyCukr

nikto_scan

Scan web servers for vulnerabilities by executing Nikto with configurable options for target, port, SSL, plugins, output format, and evasion techniques.

Instructions

Execute Nikto web server vulnerability scanner.

Args: target: Target hostname or IP address port: Port number to scan ssl: Use SSL/HTTPS plugins: Nikto plugins to run output_format: Output format (txt, xml, csv) evasion: Evasion techniques to use additional_args: Additional Nikto arguments

Returns: Web server vulnerability scan results

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
additional_argsNo
evasionNo
output_formatNotxt
pluginsNo
portNo80
sslNo
targetYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • MCP registration and thin handler for 'nikto_scan' tool, proxies to REST API /api/nikto endpoint.
    def nikto_scan(
        target: str,
        port: str = "80",
        ssl: bool = False,
        plugins: str = "",
        output_format: str = "txt",
        evasion: str = "",
        additional_args: str = "",
    ) -> dict[str, Any]:
        """Execute Nikto web server vulnerability scanner.
    
        Args:
            target: Target hostname or IP address
            port: Port number to scan
            ssl: Use SSL/HTTPS
            plugins: Nikto plugins to run
            output_format: Output format (txt, xml, csv)
            evasion: Evasion techniques to use
            additional_args: Additional Nikto arguments
    
        Returns:
            Web server vulnerability scan results
        """
        data = {
            "target": target,
            "port": port,
            "ssl": ssl,
            "plugins": plugins,
            "output_format": output_format,
            "evasion": evasion,
            "additional_args": additional_args,
        }
    
        logger.info(f"🔍 Starting Nikto vulnerability scan on {target}")
        result = api_client.safe_post("api/nikto", data)
    
        if result.get("success"):
            logger.info(f"✅ Nikto scan completed on {target}")
        else:
            logger.error("❌ Nikto scan failed")
    
        return result
  • Core handler function for Nikto scan execution, registered via @tool() decorator, handles param extraction, command building, execution, and parsing.
    @tool()
    def execute_nikto():
        """Execute Nikto web server vulnerability scanner."""
        data = request.get_json()
        params = extract_nikto_params(data)
    
        logger.info(f"Executing Nikto scan on {params['target']}")
    
        started_at = datetime.now()
        command = build_nikto_command(params)
        execution_result = execute_command(command, params["timeout"])
        ended_at = datetime.now()
    
        return parse_nikto_output(execution_result, params, command, started_at, ended_at)
  • Helper function to extract and process input parameters for Nikto scan, including aggressive mode preset.
    def extract_nikto_params(data):
        """Extract nikto parameters from request data."""
        # Check for aggressive mode
        aggressive = data.get("aggressive", False)
    
        # Base parameters
        params = {
            "target": data["target"],
            "port": data.get("port", "80"),
            "ssl": data.get("ssl", False),
            "plugins": data.get("plugins", ""),
            "output_format": data.get("output_format", "txt"),
            "evasion": data.get("evasion", ""),
            "timeout": data.get("timeout", 600),
            "max_time": data.get("max_time", ""),
            "mutate": data.get("mutate", ""),
            "additional_args": data.get("additional_args", ""),
            # Authentication parameters
            "auth_type": data.get("auth_type", ""),  # basic, digest, ntlm
            "username": data.get("username", ""),
            "password": data.get("password", ""),
            # Custom headers
            "headers": data.get("headers", {}),  # Dict of header_name: header_value
            "user_agent": data.get("user_agent", ""),
            "cookies": data.get("cookies", ""),
            # Proxy settings
            "proxy": data.get("proxy", ""),
            # Other advanced options
            "virtual_host": data.get("virtual_host", ""),
            "config_file": data.get("config_file", ""),
        }
    
        # Apply aggressive preset if requested
        if aggressive:
            # Nikto aggressive preset
            params.update(
                {
                    "plugins": "@@ALL",
                    "timeout": 30,
                    "max_time": 3600,
                    "evasion": "1,2,3,4,5,6,7,8,9,A,B",
                    "mutate": "1,2,3,4,5,6",
                    "output_format": "json",
                }
            )
        return params
  • Helper function to construct the full Nikto CLI command from processed parameters.
    def build_nikto_command(params):
        """Build nikto command from parameters."""
        cmd_parts = ["nikto", "-h", params["target"]]
    
        if params["port"] and params["port"] != "80":
            cmd_parts.extend(["-p", str(params["port"])])
    
        if params["ssl"]:
            cmd_parts.append("-ssl")
    
        if params["plugins"]:
            cmd_parts.extend(["-Plugins", params["plugins"]])
    
        if params["output_format"] != "txt":
            cmd_parts.extend(["-Format", params["output_format"]])
    
        if params["evasion"]:
            cmd_parts.extend(["-evasion", params["evasion"]])
    
        if params["max_time"]:
            cmd_parts.extend(["-maxtime", str(params["max_time"])])
    
        if params["mutate"]:
            cmd_parts.extend(["-mutate", params["mutate"]])
    
        # Authentication support
        if params["auth_type"] and params["username"] and params["password"]:
            auth_string = f"{params['username']}:{params['password']}"
            if params["auth_type"].lower() == "basic":
                cmd_parts.extend(["-id", auth_string])
            elif params["auth_type"].lower() == "digest":
                # Nikto handles digest automatically when credentials are provided
                cmd_parts.extend(["-id", auth_string])
    
        # Custom headers support
        if params["headers"]:
            for header_name, header_value in params["headers"].items():
                cmd_parts.extend(["-header", f"{header_name}: {header_value}"])
    
        # User Agent
        if params["user_agent"]:
            cmd_parts.extend(["-useragent", params["user_agent"]])
    
        # Cookies
        if params["cookies"]:
            cmd_parts.extend(["-cookie", params["cookies"]])
    
        # Proxy support
        if params["proxy"]:
            cmd_parts.extend(["-useproxy", params["proxy"]])
    
        # Virtual host
        if params["virtual_host"]:
            cmd_parts.extend(["-vhost", params["virtual_host"]])
    
        # Config file
        if params["config_file"]:
            cmd_parts.extend(["-config", params["config_file"]])
    
        if params["additional_args"]:
            cmd_parts.extend(params["additional_args"].split())
    
        return " ".join(cmd_parts)
  • Helper function to parse Nikto command output and structure it into findings with metadata.
    def parse_nikto_output(execution_result, params, command, started_at, ended_at):
        """Parse nikto execution result and format response."""
        duration_ms = int((ended_at - started_at).total_seconds() * 1000)
    
        result = {
            "tool": "nikto",
            "target": params["target"],
            "params": params,
            "command": command,
            "started_at": started_at.isoformat(),
            "ended_at": ended_at.isoformat(),
            "duration_ms": duration_ms,
            "success": execution_result["success"],
            "raw_output": execution_result.get("stdout", ""),
            "error_output": execution_result.get("stderr", ""),
            "return_code": execution_result.get("return_code", -1),
            "findings": [],
            "stats": {"findings": 0, "dupes": 0, "payload_bytes": 0},
        }
    
        # Parse basic findings from output if successful
        if execution_result["success"] and result["raw_output"]:
            try:
                findings = []
                lines = result["raw_output"].strip().split("\n")
    
                for line in lines:
                    line = line.strip()
                    # Look for Nikto findings (lines that contain vulnerability indicators)
                    if any(
                        indicator in line.lower()
                        for indicator in [
                            "osvdb",
                            "cve",
                            "potential",
                            "vulnerability",
                            "misconfiguration",
                            "directory",
                            "file found",
                            "server version",
                        ]
                    ):
                        findings.append(
                            {
                                "type": "vulnerability",
                                "target": params["target"],
                                "evidence": {"raw_output": line},
                                "severity": "info",  # Direct mapping
                                "confidence": "medium",  # Direct mapping
                                "tags": ["nikto", "web-server"],
                                "raw_ref": line,
                            }
                        )
    
                result["findings"] = findings
                result["stats"]["findings"] = len(findings)
                result["stats"]["payload_bytes"] = len(result["raw_output"].encode("utf-8"))
            except Exception as e:
                logger.warning(f"Failed to parse Nikto findings: {e}")
    
        return result
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. While it mentions 'Execute Nikto web server vulnerability scanner' and describes parameters, it lacks critical behavioral details such as whether this is a read-only or destructive operation, expected execution time, rate limits, authentication requirements, or potential impacts on the target system. The description doesn't compensate for the absence of annotations.

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 with a clear purpose statement followed by 'Args:' and 'Returns:' sections, making it easy to scan. It's appropriately sized for a tool with 7 parameters, though some sentences could be more concise (e.g., 'Execute Nikto web server vulnerability scanner' is efficient, but the parameter explanations are brief and front-loaded).

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

Completeness3/5

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

Given the tool's complexity (7 parameters, no annotations, but with an output schema), the description is moderately complete. It covers the purpose and parameters adequately but lacks behavioral context and usage guidelines. The presence of an output schema means the description doesn't need to explain return values, but it should still address when and how to use the tool effectively.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate by explaining parameters. It provides a clear list of 7 parameters with brief semantics (e.g., 'target: Target hostname or IP address'), adding meaningful context beyond the schema's titles. However, it doesn't detail format specifics (e.g., valid evasion techniques or plugin names), leaving some gaps in parameter understanding.

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 ('Execute') and resource ('Nikto web server vulnerability scanner'), making it immediately understandable. However, it doesn't explicitly differentiate this Nikto scanner from sibling tools like 'nmap_scan' or 'nuclei_scan', which are also vulnerability scanners but for different purposes.

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. With many sibling tools available for scanning and vulnerability assessment (e.g., 'nmap_scan', 'nuclei_scan', 'wpscan_analyze'), there's no indication of Nikto's specific use cases, prerequisites, or how it complements or differs from other tools in the server.

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/SlanyCukr/bugbounty-mcp-server'

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