Skip to content

Latest commit

 

History

History
74 lines (56 loc) · 2.8 KB

File metadata and controls

74 lines (56 loc) · 2.8 KB

Contributing

Thanks for your interest. This lab is small on purpose, and the bar for incoming contributions is high — not because we want to gatekeep, but because the value of a reference implementation is exactly proportional to its discipline.

What gets merged

Pull requests fall into one of three buckets:

  1. New lab under projects/ — see the checklist below.
  2. Improvement to an existing lab's security model — e.g. closing a gap already documented under "Known limitations" in its threat model.
  3. Documentation / typo / clarity fixes — always welcome.

What does not get merged:

  • New tools or labs without a threat_model.md.
  • Refactors that introduce dynamic dispatch (getattr, eval, globals()[…], operator.__dict__[…], etc.) — see SECURITY.md.
  • "DRY" refactors that hide the security gates inside abstraction layers. Three explicit if op == "..." branches beat one clever decorator.
  • Changes that raise the floor for new contributors without adding security value (mypy strict mode, ruff with 30 plugins, etc.).

Checklist for a new lab

A new directory under projects/ is mergeable when every box is ticked:

  • Has its own README.md (what the lab demonstrates, how to run it).
  • Has its own threat_model.md covering at least:
    • prompt injection vectors specific to its tools / resources;
    • overflow (numeric and/or string, as applicable);
    • denial-of-service surfaces;
    • unauthorized execution paths.
  • Has at least one rejection test per security gate in tests/. A gate without a test is a gate that doesn't exist.
  • Tools have a pure core function (e.g. safe_xxx) that the tests call directly, plus a thin @mcp.tool() wrapper.
  • Constants (ALLOWED_*, MAX_*) are Final and exported for testing.
  • All rejections raise ToolExecutionError and log at WARNING.
  • No eval, exec, getattr-by-string, or dynamic imports.
  • No network or filesystem access unless the lab is specifically about defending such access — and then with a guard tested by rejection cases.

Local development

python3.13 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest

The full suite must pass before pushing.

Commit / PR style

  • One change per PR. If you find a second issue while fixing the first, open a second PR.
  • The PR description should answer: what threat does this address, and which test proves it?
  • Reference the threat-model row number when relevant (e.g. "closes 2.4 in mcp-server-basic/threat_model.md").

Reporting security issues

See SECURITY.md. Do not open public issues for vulnerabilities.

License

By contributing, you agree that your contributions will be licensed under the MIT License.