From e9ccb971e08c7dadcb9775f16ccd88b7b606114f Mon Sep 17 00:00:00 2001 From: dbrockmann Date: Tue, 1 Sep 2026 11:58:53 +0200 Subject: [PATCH] fix: restrict component resolution to scoped tokens --- README.md | 3 +++ joinly/container.py | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e3c884e..74f565d 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,9 @@ Start the joinly server in the first terminal (note, we are not using `--client` docker run -p 8000:8000 ghcr.io/joinly-ai/joinly:latest ``` +> [!WARNING] +> The joinly MCP server has no authentication and is meant to run locally with a single trusted client. Do not expose it beyond `localhost` or a trusted private network. + While the server is running, start the example client implementation in the second terminal window to connect to it and join a meeting: ```bash uvx joinly-client --env-file .env diff --git a/joinly/container.py b/joinly/container.py index c92eab1..6b7cfd7 100644 --- a/joinly/container.py +++ b/joinly/container.py @@ -14,11 +14,10 @@ def _resolve(spec: str | type[T], *, base: str, suffix: str) -> type[T]: - """Turn direct type, dotted path, or short token into a class object. + """Turn direct type or short token into a class object. Discovers paths by convention: - if `spec` is a type, return it directly. - - if `spec` is a dotted path, import the module and return the class. - if `spec` is a short token, map to `..`. """ @@ -26,16 +25,16 @@ def _resolve(spec: str | type[T], *, base: str, suffix: str) -> type[T]: return spec if "." in spec: - # fully qualified - mod, _, cls = spec.rpartition(".") + msg = f"Invalid component token '{spec}': dotted import paths are not allowed." + raise ImportError(msg) + + # short token + if spec.lower().endswith(suffix.lower()): + base_name = spec[: -len(suffix)] else: - # short token - if spec.lower().endswith(suffix.lower()): - base_name = spec[: -len(suffix)] - else: - base_name = "".join(p.capitalize() for p in re.split(r"[_\- ]+", spec)) - mod = f"{base}.{base_name.lower()}" - cls = base_name + suffix + base_name = "".join(p.capitalize() for p in re.split(r"[_\- ]+", spec)) + mod = f"{base}.{base_name.lower()}" + cls = base_name + suffix try: module = importlib.import_module(mod)