diff --git a/data/mcp/mcp_hardcoded_secrets.yaml b/data/mcp/mcp_hardcoded_secrets.yaml new file mode 100644 index 000000000..7d8d5162b --- /dev/null +++ b/data/mcp/mcp_hardcoded_secrets.yaml @@ -0,0 +1,82 @@ +info: + id: "mcp_hardcoded_secrets" + name: "MCP Hardcoded Secrets Detection" + description: "Detect hardcoded credentials, API keys, tokens, and private keys embedded in MCP server source code, which can be exposed if the repository or distribution package is accessible to unauthorized parties." + author: "ATR (Agent Threat Rules)" + categories: + - code + +prompt_template: | + As a professional AI-agent security analyst, precisely detect hardcoded secrets + in MCP server source code. Hardcoded credentials embedded directly in source + files — API keys, access tokens, private keys, passwords — can be extracted by + anyone who gains read access to the repository, package, or running container. + Require concrete evidence of a genuine secret value; only report when the string + matches a known credential pattern with sufficient entropy or format. + + ## Vulnerability Definition + Hardcoded secrets occur when sensitive authentication material — cloud provider + keys (`AKIA…`), API tokens (`sk-…`, `ghp_…`, `xoxb-…`), private keys + (`-----BEGIN … PRIVATE KEY-----`), database passwords, JWT secrets — is + committed directly in source code rather than loaded from environment variables, + a secrets manager, or a properly git-ignored configuration file. + + ## Detection Criteria (require a concrete secret pattern) + + ### 1. Cloud provider credentials + **Code Patterns:** + - AWS access keys: `AKIA[0-9A-Z]{16}`, AWS secret keys assigned as string + literals. + - Azure / GCP keys, service account JSON embedded as a string or object. + - Cloudflare / DigitalOcean / Linode API tokens in assignments. + + ### 2. SaaS API tokens + **Code Patterns:** + - OpenAI / Anthropic / other LLM API keys: `sk-[a-zA-Z0-9]{20,}`, + `sk-ant-…`. + - GitHub tokens: `ghp_[a-zA-Z0-9]{36}`, `gho_…`, `ghs_…`. + - Slack tokens: `xox[baprs]-…`. + - Stripe keys: `sk_live_…`, `rk_live_…`. + - Generic `API_KEY = "…"`, `SECRET_KEY = "…"`, `TOKEN = "…"` assignments + with high-entropy values (>20 chars, mixed case + digits). + + ### 3. Private keys and certificates + **Code Patterns:** + - PEM blocks: `-----BEGIN RSA PRIVATE KEY-----`, `-----BEGIN EC PRIVATE KEY-----`, + `-----BEGIN PRIVATE KEY-----`, `-----BEGIN OPENSSH PRIVATE KEY-----`. + - PGP private key blocks, certificate bundles with private key material. + + ### 4. Database / service passwords + **Code Patterns:** + - Connection strings with embedded passwords: + `mongodb://user:password@host`, `postgres://user:pass@host`. + - Password assignments: `password = "…"`, `DB_PASS = "…"` where the value is + a non-placeholder string (not ``, `your_password`, `changeme`, + `example`, `xxx`). + + ## Strict Judgment Standards + - **Environment variables**: Do not report `os.environ.get('API_KEY')` or + `process.env.API_KEY` — these are correct practices. + - **Placeholders**: Do not report obvious placeholder values (`your_key_here`, + `xxx`, `changeme`, `example`, ``, empty strings). + - **Test fixtures**: Do not report secrets in files under test directories + (`test/`, `__tests__/`, `*_test.*`, `*.spec.*`) that are clearly fake values. + - **Documentation**: Do not report secrets inside comments that serve as + usage examples with placeholder-style values. + - **Low-entropy values**: Do not report short or dictionary-word strings that + do not match any credential format. + + ## Output Requirements + Only output when finding concrete hardcoded secrets: + - Specific file path and line number + - The type of secret (API key, token, private key, password, etc.) + - The redacted value (show only enough to identify the type, e.g. + `AKIA****XXXX`) + - Technical analysis: how the secret could be extracted by an unauthorized party + - Impact assessment: what resources or services the exposed credential grants + access to + - Remediation: move secrets to environment variables or a secrets manager, + rotate the exposed credential, add `.env` to `.gitignore`, use + pre-commit secret scanners. + + **Strict Requirement: provide the file, line number, and secret type with a redacted value. Remain silent when no concrete evidence exists.** diff --git a/data/mcp/mcp_insecure_deserialization.yaml b/data/mcp/mcp_insecure_deserialization.yaml new file mode 100644 index 000000000..20e8dd13e --- /dev/null +++ b/data/mcp/mcp_insecure_deserialization.yaml @@ -0,0 +1,75 @@ +info: + id: "mcp_insecure_deserialization" + name: "MCP Insecure Deserialization Detection" + description: "Detect MCP server tools that deserialize caller-supplied data using unsafe serializers (pickle, marshal, eval-based JSON, yaml.load, unserialize) without validation, enabling remote code execution on the MCP host." + author: "ATR (Agent Threat Rules)" + categories: + - code + +prompt_template: | + As a professional AI-agent security analyst, precisely detect insecure + deserialization vulnerabilities in MCP server tools. The agent (or an upstream + prompt-injection) controls tool arguments; if those arguments are deserialized + using an unsafe serializer, the MCP host can execute attacker-crafted payloads. + Require a concrete argument-to-deserialization-sink path; only report with + evidence. + + ## Vulnerability Definition + An MCP tool handler takes caller-supplied arguments (strings, base64 blobs, or + nested objects) and passes them to a deserializer that can instantiate + arbitrary objects or execute code — `pickle.loads`, `marshal.loads`, + `yaml.load` (unsafe), `unserialize` (PHP), `ObjectInputStream` (Java), + `eval`/`Function()` on JSON-like strings — without type/schema validation. + Because tool arguments are model/attacker-influenced, this is argument-driven + RCE on the MCP host. + + ## Detection Criteria (require tainted argument -> deserialization sink) + + ### 1. Python unsafe deserializers + **Code Patterns:** + - `pickle.loads(args.data)` / `pickle.load(open(args.file))` on + caller-controlled input. + - `marshal.loads(args.data)` / `yaml.load(args.data)` without `Loader=SafeLoader` + / `yaml.unsafe_load()`. + - `dill.loads()` / `shelve.open()` on attacker-influenced data. + - `jsonpickle.decode(args.data)` on caller-controlled input — jsonpickle can + instantiate arbitrary classes via `{"py/object": "..."}` directives, + carrying the same RCE risk as pickle. + + ### 2. JavaScript / dynamic evaluation as deserialization + **Code Patterns:** + - `eval(args.expr)` / `new Function(args.code)` used to parse a structured + argument. + - `vm.runInNewContext(args.script)` / `vm.Script` on caller input. + - `JSON.parse` followed by `eval` of a contained field. + + ### 3. Other language-specific unsafe deserializers + **Code Patterns:** + - PHP `unserialize($args['data'])` without `allowed_classes` restriction. + - Java `ObjectInputStream.readObject()` on caller-controlled bytes. + - .NET `BinaryFormatter.Deserialize()` / `LosFormatter.Deserialize()` on + attacker input. + - Ruby `Marshal.load(args.data)` / `YAML.load` (unsafe) on caller input. + + ## Strict Judgment Standards + - **Safe serializers**: Do not report `json.loads` / `JSON.parse` / + `yaml.safe_load` / `yaml.load(..., Loader=SafeLoader)` — these do not + instantiate arbitrary objects. + - **Trusted data**: Do not report deserialization of server-generated or + statically-defined data with no caller influence. + - **Type-restricted**: Do not report PHP `unserialize` with `allowed_classes: + false` or an explicit allowlist. + - **Test/example**: Do not report sample handlers with hardcoded test payloads. + + ## Output Requirements + Only output when finding a concrete deserialization path: + - Specific file paths and line numbers for the tainted argument and the sink + - The tool parameter name and the exact deserialization call + - Technical analysis: how a crafted payload achieves code execution or object + instantiation + - Impact assessment: RCE scope on the MCP host + - Remediation: use safe serializers (`json`, `yaml.safe_load`), avoid + `eval`/`pickle`/`unserialize` on untrusted data, enforce schema validation, + restrict `allowed_classes`. + + **Strict Requirement: provide the tainted-argument source and the deserialization sink with line numbers. Remain silent when no concrete evidence exists.** diff --git a/data/mcp/mcp_path_traversal.yaml b/data/mcp/mcp_path_traversal.yaml new file mode 100644 index 000000000..72a2436b0 --- /dev/null +++ b/data/mcp/mcp_path_traversal.yaml @@ -0,0 +1,71 @@ +info: + id: "mcp_path_traversal" + name: "MCP Tool Path Traversal Detection" + description: "Detect MCP server tools that accept file or directory path arguments and pass them to filesystem APIs without canonicalization or directory-boundary checks, enabling arbitrary file read/write outside the intended scope." + author: "ATR (Agent Threat Rules)" + categories: + - code + +prompt_template: | + As a professional AI-agent security analyst, precisely detect path-traversal + vulnerabilities in MCP server tools. The agent (or an upstream prompt-injection) + controls tool arguments; if a path argument reaches a filesystem API without + canonicalization or boundary checks, the MCP server can read or write files + outside the intended directory. Require a concrete argument-to-filesystem-sink + path; only report with evidence. + + ## Vulnerability Definition + An MCP tool handler takes caller-supplied arguments containing a file path, + directory, or filename and passes them to filesystem APIs (`fs.readFile`, + `fs.writeFile`, `open()`, `os.path.join`, `Path.Combine`, etc.) without + resolving the absolute path and verifying it stays within an allowed root + directory. Because tool arguments are model/attacker-influenced, this enables + arbitrary file access on the MCP host. + + ## Detection Criteria (require tainted argument -> filesystem sink) + + ### 1. Unsanitized path to filesystem API + **Code Patterns:** + - `fs.readFile(args.path)` / `fs.readFile(path.join(baseDir, args.filename))` + where `args.filename` contains `../` sequences that escape `baseDir`. + - `open(args.file)` / `os.path.join(workdir, user_input)` with no subsequent + canonicalization check. + - `Path.Combine(root, userInput)` without verifying `result.StartsWith(root)`. + - Filename argument used in write/delete APIs: `fs.writeFile`, `fs.unlink`, + `os.remove`, `shutil.rmtree` without boundary enforcement. + + ### 2. Missing canonicalization + **Code Patterns:** + - No call to `path.resolve()` / `fs.realpath()` / `os.path.abspath()` / + `os.path.realpath()` before the filesystem operation. + - Canonicalized path not compared against the allowed root with a prefix check + (e.g., `resolved.startsWith(allowedRoot + sep)`). + - Symlink-following without restriction, allowing escape via symlinks. + + ### 3. Template / pattern injection into paths + **Code Patterns:** + - Path built via string interpolation: `` `${baseDir}/${args.name}.json` `` + where `args.name` contains `/` or `..` to traverse directories. + - Glob or regex patterns derived from user input that can match files outside + the intended scope. + + ## Strict Judgment Standards + - **Fixed paths**: Do not report hardcoded, constant file paths with no argument + interpolation. + - **Properly validated paths**: Do not report paths that are canonicalized and + boundary-checked before the filesystem operation. + - **Schema-restricted input**: Do not report arguments constrained by a strict + schema (e.g., enum of allowed filenames, no path separators allowed). + - **Test/example**: Do not report sample handlers with placeholder paths. + + ## Output Requirements + Only output when finding a concrete path-traversal path: + - Specific file paths and line numbers for the tainted argument and the sink + - The tool parameter name and the exact filesystem call + - Technical analysis: how a crafted path escapes the intended directory + - Impact assessment: which files or directories could be accessed + - Remediation: canonicalize paths with `resolve`/`realpath`, enforce a directory + boundary check, reject path separators in filename arguments, use a safe + allowlist. + + **Strict Requirement: provide the tainted-argument source and the filesystem sink with line numbers. Remain silent when no concrete evidence exists.** diff --git a/data/mcp/mcp_ssrf.yaml b/data/mcp/mcp_ssrf.yaml new file mode 100644 index 000000000..644ead5ff --- /dev/null +++ b/data/mcp/mcp_ssrf.yaml @@ -0,0 +1,69 @@ +info: + id: "mcp_ssrf" + name: "MCP Server-Side Request Forgery (SSRF) Detection" + description: "Detect MCP server tools that accept URL or hostname arguments from the caller and fetch them without validating against internal/private network ranges, enabling server-side request forgery." + author: "ATR (Agent Threat Rules)" + categories: + - code + +prompt_template: | + As a professional AI-agent security analyst, precisely detect Server-Side Request + Forgery (SSRF) vulnerabilities in MCP server tools. The agent (or an upstream + prompt-injection) controls tool arguments; if a URL or hostname argument reaches + an HTTP client or socket without validation, the MCP server can be coerced into + accessing internal services, cloud metadata endpoints, or other restricted + resources. Require a concrete argument-to-network-request path; only report with + evidence. + + ## Vulnerability Definition + An MCP tool handler takes caller-supplied arguments containing a URL, hostname, + or IP address and passes them to a network client (`fetch`, `axios`, `requests`, + `urllib`, raw socket, etc.) without checking the destination against internal or + private address ranges. Because tool arguments are model/attacker-influenced, + this enables SSRF from the MCP host. + + ## Detection Criteria (require tainted argument -> network sink) + + ### 1. Unvalidated URL fetch + **Code Patterns:** + - `fetch(args.url)` / `axios.get(args.url)` / `requests.get(params["url"])` + with no prior allowlist or IP-range check on the URL. + - URL constructed by concatenating a user-supplied host/path: + `` `https://${args.host}/${args.path}` `` passed directly to a client. + - Tool argument used as the `baseURL` / `endpoint` of an API client without + validation. + + ### 2. Internal/private address access + **Code Patterns:** + - No blocklist for `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, + `192.168.0.0/16`, `169.254.169.254` (cloud metadata), `::1`, `fc00::/7`. + - DNS rebinding exposure: hostname validated but resolution not re-checked + after DNS lookup. + - Redirect following enabled without re-validating the final destination. + + ### 3. Scheme / protocol confusion + **Code Patterns:** + - No scheme restriction, allowing `file://`, `gopher://`, `dict://`, `ftp://` + schemes to reach local files or internal services. + - URL parsing that accepts a user-supplied scheme without an `http`/`https` + allowlist. + + ## Strict Judgment Standards + - **Fixed URLs**: Do not report hardcoded, constant URLs with no argument + interpolation. + - **Validated destinations**: Do not report URLs passed through a strict + allowlist of domains or a properly implemented SSRF guard (IP-range check + + scheme check + redirect-following disabled or re-validated). + - **Test/example**: Do not report sample handlers with placeholder URLs. + + ## Output Requirements + Only output when finding a concrete SSRF path: + - Specific file paths and line numbers for the tainted argument and the sink + - The tool parameter name and the exact network call + - Technical analysis: how a crafted URL reaches an internal or restricted + resource + - Impact assessment: what internal endpoints or metadata could be accessed + - Remediation: validate destinations against an allowlist, block private/loop + back ranges, restrict schemes to http/https, disable or re-validate redirects. + + **Strict Requirement: provide the tainted-argument source and the network sink with line numbers. Remain silent when no concrete evidence exists.**