import json
from pathlib import Path
from mcp.core import get_example, get_schema
from mcp.validate import validate_asset
_MINIMAL_SCHEMA = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {"type": "string", "minLength": 1},
},
"required": ["id"],
"additionalProperties": False,
}
def _seed_roots(tmp_path: Path, monkeypatch) -> tuple[Path, Path]:
schemas_dir = tmp_path / "schemas"
schemas_dir.mkdir()
(schemas_dir / "asset.schema.json").write_text(json.dumps(_MINIMAL_SCHEMA))
examples_dir = tmp_path / "examples"
examples_dir.mkdir()
monkeypatch.setenv("SYN_SCHEMAS_DIR", str(schemas_dir))
monkeypatch.setenv("SYN_EXAMPLES_DIR", str(examples_dir))
return schemas_dir, examples_dir
def test_get_schema_rejects_traversal(monkeypatch, tmp_path):
schemas_dir, _ = _seed_roots(tmp_path, monkeypatch)
res = get_schema("../asset")
assert res["ok"] is False
assert res["reason"] == "validation_failed"
assert any(err["msg"] == "invalid_path" for err in res["errors"])
valid = get_schema("asset")
assert valid["ok"] is True
# Absolute path pointing outside the root should be rejected
absolute_name = str((tmp_path / "elsewhere").resolve())
res_abs = get_schema(absolute_name)
assert res_abs["ok"] is False
assert res_abs["reason"] == "validation_failed"
def test_get_example_rejects_traversal(monkeypatch, tmp_path):
_, examples_dir = _seed_roots(tmp_path, monkeypatch)
nested = examples_dir / "nested"
nested.mkdir()
example_path = nested / "asset.json"
example_path.write_text(
json.dumps({"$schema": "jsonschema/asset.schema.json", "id": "example"})
)
res = get_example("../asset.json")
assert res["ok"] is False
assert res["reason"] == "validation_failed"
assert any(err["msg"] == "invalid_path" for err in res["errors"])
res_abs = get_example(str(example_path))
assert res_abs["ok"] is False
assert res_abs["reason"] == "validation_failed"
valid = get_example("nested/asset.json")
assert valid["ok"] is True
assert valid["schema"] == "asset"
def test_validate_asset_schema_path_guard(monkeypatch, tmp_path):
_seed_roots(tmp_path, monkeypatch)
asset = {"$schema": "jsonschema/asset.schema.json", "id": "ok"}
res = validate_asset(asset, "../asset")
assert res["ok"] is False
assert res["reason"] == "validation_failed"
assert any(err["msg"] == "schema_outside_configured_root" for err in res["errors"])
valid = validate_asset(asset, "asset")
assert valid["ok"] is True
assert valid.get("errors") == []