coding-standards-mcp Template Escape via get_style_guide
1) CNA / Submission Type
- Submission type: Report a vulnerability (CVE ID request)
- Reporter role: Independent security researcher
- Report date: April 14, 2026
2) Reporter Contact (fill before submit)
- Reporter name:
Winegee
- Reporter email:
Winegee@zju.edu.cn
- Permission to share contact with vendor:
Yes
3) Vendor / Product Identification
- Vendor: ggerve
- Product: coding-standards-mcp
- Repository: https://github.com/ggerve/coding-standards-mcp.git
- Reviewed local source path:
python-batch-04/datasets/ggerve-coding-standards-mcp
- Confirmed affected tools:
get_style_guide, get_best_practices
- Reviewed source file:
server.py
4) Vulnerability Type
- CWE: CWE-22 / CWE-73 (Path Traversal / External Control of File Name or Path)
- Short title: The
language argument is interpolated into a template filename and opened from templates/ without canonicalization, allowing traversal to read matching files outside the template directory.
5) Affected Versions
- Confirmed affected: c21ab2754684329eab4feb72427dc9acfe61e52f
- Suspected affected range: revisions containing the same
read_template() implementation in server.py
- Fixed version: Not available at time of report (April 14, 2026)
6) Vulnerability Description
The server is supposed to serve Markdown templates from its bundled templates directory. Instead, both exported tools construct filenames from untrusted language input and pass them into read_template():
get_style_guide(language) builds f"{language}_style_guide.md"
get_best_practices(language) builds f"{language}_best_practices.md"
read_template() then does os.path.join(os.path.dirname(__file__), "templates", filename) and opens the resulting path directly. Because neither the input nor the resolved path is validated, traversal strings such as ../../../../tmp/secret escape templates/ and read files like /tmp/secret_style_guide.md.
7) Technical Root Cause
server.py:64-70
- The exposed tools derive a filename from untrusted
language input.
server.py:23-25
read_template() joins that filename under templates/ and immediately executes with open(template_path, "r") as f:.
- Audit conclusion
- This is a real path traversal, but the reachable file set is constrained by the suffixes the tool appends (
_style_guide.md and _best_practices.md).
8) Attack Prerequisites
- The attacker can call
get_style_guide or get_best_practices.
- A readable target file exists on disk with one of the expected suffixes.
9) Proof of Concept / Reproduction Guidance
- Create a readable file outside the repository, for example
/tmp/secret_style_guide.md.
- Invoke the MCP tool with a traversal payload:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_style_guide",
"arguments": {
"language": "../../../../tmp/secret"
}
}
}
- Expected result
- The returned text is the content of
/tmp/secret_style_guide.md, not a bundled template from templates/.
10) Security Impact
- Confidentiality: Medium. The primitive is limited to files whose names match the expected suffix pattern.
- Integrity: None directly from the confirmed primitive.
- Availability: None or negligible.
- Scope: Unchanged.
11) CVSS v3.1 Suggestion
- Suggested vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Suggested base score: 5.3 (Medium)
12) Workarounds / Mitigations
- Restrict
language to a fixed allowlist such as java, python, and react.
- Resolve the final path and enforce that it stays inside the
templates directory.
- Reject path separators and traversal tokens in template selectors.
13) Recommended Fix
- Replace free-form
language input with an enum or map of known template names.
- If free-form input must remain, validate with a strict regex and then verify the resolved path is under
templates/.
- Add regression tests for payloads containing
/, \\, and ...
14) References
15) Credits
- Discoverer:
Winegee
- Discovery method: Static analysis (CodeQL) plus local source-code audit
16) Additional Notes for Form Mapping
- Audit verdict: Confirmed vulnerability.
- Total reviewed SARIF results for this repository/rule group: 1
- Dynamic exploit replay status: not completed in this pass.
- The practical limitation is filename suffix control, not full arbitrary pathname control.
coding-standards-mcp Template Escape via
get_style_guide1) CNA / Submission Type
2) Reporter Contact (fill before submit)
WinegeeWinegee@zju.edu.cnYes3) Vendor / Product Identification
python-batch-04/datasets/ggerve-coding-standards-mcpget_style_guide,get_best_practicesserver.py4) Vulnerability Type
languageargument is interpolated into a template filename and opened fromtemplates/without canonicalization, allowing traversal to read matching files outside the template directory.5) Affected Versions
read_template()implementation inserver.py6) Vulnerability Description
The server is supposed to serve Markdown templates from its bundled
templatesdirectory. Instead, both exported tools construct filenames from untrustedlanguageinput and pass them intoread_template():get_style_guide(language)buildsf"{language}_style_guide.md"get_best_practices(language)buildsf"{language}_best_practices.md"read_template()then doesos.path.join(os.path.dirname(__file__), "templates", filename)and opens the resulting path directly. Because neither the input nor the resolved path is validated, traversal strings such as../../../../tmp/secretescapetemplates/and read files like/tmp/secret_style_guide.md.7) Technical Root Cause
server.py:64-70languageinput.server.py:23-25read_template()joins that filename undertemplates/and immediately executeswith open(template_path, "r") as f:._style_guide.mdand_best_practices.md).8) Attack Prerequisites
get_style_guideorget_best_practices.9) Proof of Concept / Reproduction Guidance
/tmp/secret_style_guide.md.{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_style_guide", "arguments": { "language": "../../../../tmp/secret" } } }/tmp/secret_style_guide.md, not a bundled template fromtemplates/.10) Security Impact
11) CVSS v3.1 Suggestion
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N12) Workarounds / Mitigations
languageto a fixed allowlist such asjava,python, andreact.templatesdirectory.13) Recommended Fix
languageinput with an enum or map of known template names.templates/./,\\, and...14) References
server.py15) Credits
Winegee16) Additional Notes for Form Mapping