Skip to main content
Glama
x0base

mcp-security-toolkit

by x0base

sensitive_files_list

Identify sensitive file paths for any tech stack (PHP, WordPress, .NET, Java, Node, Python, K8s, Docker, CI). No network required.

Instructions

Return curated sensitive-path lists for a given tech stack.

Args: stack: Comma-separated stack hints. Supported keys: common, php, wordpress, dotnet, java, node, python, k8s, docker, ci. include_common: If True (default), always include the common set.

Returns: FilesReport with paths (each {path, why}). No network is performed.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
stackNocommon
include_commonNo

Implementation Reference

  • The main handler function 'sensitive_files_list' that takes a stack string (comma-separated) and include_common flag, looks up sensitive file paths from the PATHS dictionary, deduplicates them, and returns a FilesReport dict. This is the core logic of the tool.
    def sensitive_files_list(stack: str = "common", include_common: bool = True) -> dict:
        """Return curated sensitive-path lists for a given tech stack.
    
        Args:
            stack: Comma-separated stack hints. Supported keys:
                common, php, wordpress, dotnet, java, node, python, k8s, docker, ci.
            include_common: If True (default), always include the `common` set.
    
        Returns:
            FilesReport with `paths` (each {path, why}). No network is performed.
        """
        if not isinstance(stack, str):
            return {"error": "stack must be a string"}
    
        requested = [s.strip().lower() for s in stack.split(",") if s.strip()]
        if not requested:
            requested = ["common"]
        if include_common and "common" not in requested:
            requested = ["common", *requested]
    
        seen: set[str] = set()
        out: list[FileEntry] = []
        for s in requested:
            for entry in PATHS.get(s, []):
                if entry["path"] not in seen:
                    seen.add(entry["path"])
                    out.append(FileEntry(**entry))
    
        return FilesReport(stacks_requested=requested, paths=out).model_dump()
  • Registers sensitive_files_list as an MCP tool via mcp.tool()(sensitive_files_list.sensitive_files_list).
    mcp.tool()(sensitive_files_list.sensitive_files_list)
  • Pydantic models FileEntry (path + why) and FilesReport (stacks_requested, paths, note) that define the schema for the tool's output.
    class FileEntry(BaseModel):
        path: str
        why: str
    
    
    class FilesReport(BaseModel):
        stacks_requested: list[str]
        paths: list[FileEntry] = Field(default_factory=list)
        note: str = (
            "Paths only. This tool does not probe the target. "
            "For authorized testing only — fetching these against systems you do not own "
            "may be unlawful."
        )
  • The PATHS dictionary containing all sensitive file path data organized by tech stack (common, php, wordpress, dotnet, java, node, python, k8s, docker, ci), each with a path and a 'why' explanation.
    PATHS: dict[str, list[dict[str, str]]] = {
        "common": [
            {"path": "/.env", "why": "12-factor config leak (DB creds, API keys)"},
            {"path": "/.env.local", "why": "12-factor local override"},
            {"path": "/.env.production", "why": "12-factor prod config"},
            {"path": "/.git/config", "why": "exposed git repo"},
            {"path": "/.git/HEAD", "why": "exposed git repo (alternate probe)"},
            {"path": "/.svn/entries", "why": "exposed svn repo"},
            {"path": "/.DS_Store", "why": "macOS directory listing leak"},
            {"path": "/robots.txt", "why": "disclosed paths"},
            {"path": "/sitemap.xml", "why": "endpoint inventory"},
            {"path": "/crossdomain.xml", "why": "flash CORS policy"},
            {"path": "/clientaccesspolicy.xml", "why": "silverlight CORS policy"},
            {"path": "/security.txt", "why": "RFC 9116 contact"},
            {"path": "/.well-known/security.txt", "why": "RFC 9116 contact"},
            {"path": "/server-status", "why": "Apache mod_status info disclosure"},
            {"path": "/server-info", "why": "Apache mod_info"},
            {"path": "/backup.zip", "why": "common backup leak name"},
            {"path": "/backup.tar.gz", "why": "common backup leak name"},
            {"path": "/db.sql", "why": "common DB dump leak name"},
        ],
        "php": [
            {"path": "/phpinfo.php", "why": "info disclosure"},
            {"path": "/info.php", "why": "info disclosure"},
            {"path": "/test.php", "why": "leftover test endpoint"},
            {"path": "/config.php.bak", "why": "editor backup leak"},
            {"path": "/wp-config.php.bak", "why": "WordPress config backup"},
            {"path": "/composer.json", "why": "dependency inventory"},
            {"path": "/composer.lock", "why": "exact dependency versions"},
            {"path": "/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php", "why": "CVE-2017-9841 PHPUnit RCE"},
        ],
        "wordpress": [
            {"path": "/wp-admin/", "why": "admin UI exposure"},
            {"path": "/wp-login.php", "why": "login endpoint"},
            {"path": "/xmlrpc.php", "why": "XML-RPC enabled (brute / pingback abuse)"},
            {"path": "/wp-json/wp/v2/users", "why": "user enumeration via REST API"},
            {"path": "/wp-content/debug.log", "why": "WP debug log leak"},
            {"path": "/wp-config.php", "why": "WP config (often blocked, sometimes leaked via .bak)"},
            {"path": "/readme.html", "why": "WordPress version fingerprint"},
        ],
        "dotnet": [
            {"path": "/web.config", "why": ".NET config"},
            {"path": "/web.config.bak", "why": "editor backup leak"},
            {"path": "/Trace.axd", "why": "ASP.NET trace handler"},
            {"path": "/elmah.axd", "why": "ELMAH error log handler"},
            {"path": "/_vti_pvt/service.cnf", "why": "FrontPage extensions"},
        ],
        "java": [
            {"path": "/WEB-INF/web.xml", "why": "Java web app descriptor"},
            {"path": "/WEB-INF/classes/application.properties", "why": "Spring properties"},
            {"path": "/actuator", "why": "Spring Boot actuator index"},
            {"path": "/actuator/env", "why": "Spring env (CVE-2018-1273-family)"},
            {"path": "/actuator/heapdump", "why": "memory dump (full credentials)"},
            {"path": "/actuator/health", "why": "actuator presence probe"},
            {"path": "/actuator/mappings", "why": "endpoint inventory"},
            {"path": "/manager/html", "why": "Tomcat manager UI"},
            {"path": "/host-manager/html", "why": "Tomcat host-manager UI"},
        ],
        "node": [
            {"path": "/package.json", "why": "dep inventory"},
            {"path": "/package-lock.json", "why": "exact dep versions"},
            {"path": "/yarn.lock", "why": "exact dep versions"},
            {"path": "/.npmrc", "why": "npm registry / token leak"},
            {"path": "/server.js", "why": "exposed source"},
        ],
        "python": [
            {"path": "/requirements.txt", "why": "dep inventory"},
            {"path": "/Pipfile.lock", "why": "exact dep versions"},
            {"path": "/poetry.lock", "why": "exact dep versions"},
            {"path": "/settings.py", "why": "django settings leak"},
            {"path": "/manage.py", "why": "django entry"},
            {"path": "/console", "why": "Werkzeug debug console (Flask)"},
        ],
        "k8s": [
            {"path": "/metrics", "why": "Prometheus metrics often unauthed"},
            {"path": "/healthz", "why": "k8s health probe"},
            {"path": "/api/v1/namespaces/default/pods", "why": "kube-apiserver if exposed"},
        ],
        "docker": [
            {"path": "/v2/", "why": "Docker registry index"},
            {"path": "/v2/_catalog", "why": "Docker registry image enumeration"},
        ],
        "ci": [
            {"path": "/.github/workflows/", "why": "exposed CI configs"},
            {"path": "/.gitlab-ci.yml", "why": "exposed CI configs"},
            {"path": "/jenkins/script", "why": "Jenkins script console"},
        ],
    }
  • Import of the sensitive_files_list module at the top of server.py.
        sensitive_files_list,
        wordlist_gen,
    )

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.3.1

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses that no network is performed and describes the return format (FilesReport with paths). This provides good transparency about the tool's behavior and non-destructive nature.

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 concise, with a clear summary line followed by structured argument definitions. Every sentence adds information without redundancy or fluff.

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

Completeness5/5

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

Given the simple nature of the tool (2 parameters, no output schema), the description covers all necessary aspects: input parameters, default behavior, return structure, and side-effect information (no network). It is complete for an agent to use correctly.

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

Parameters5/5

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

The schema has 0% description coverage, but the description fully explains both parameters: stack lists supported keys, and include_common describes its default and effect. This adds significant value beyond the schema's type and default fields.

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 'Return curated sensitive-path lists for a given tech stack,' specifying the verb, resource, and context. It effectively distinguishes this tool from siblings like graphql_introspect or http_diff, which have 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 Guidelines4/5

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

The description explains how to use the stack and include_common parameters, and notes that no network is performed. While it doesn't explicitly list when not to use the tool or alternatives, the provided context is sufficient for typical usage.

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