diff --git a/common.py b/common.py index 14bc735..ec6adf3 100644 --- a/common.py +++ b/common.py @@ -132,6 +132,9 @@ async def oauth_authorize(request: Request): if not code_challenge: return HTMLResponse("

Fehler

PKCE erforderlich (code_challenge fehlt).

", status_code=400) + if not redirect_uri.startswith(("https://claude.ai/", "https://claude.com/")): + return HTMLResponse("

Fehler

Ungueltige redirect_uri.

", status_code=400) + code = secrets.token_urlsafe(32) _auth_codes[code] = { "client_id": client_id, diff --git a/mail/server.py b/mail/server.py index 0932870..661caf5 100644 --- a/mail/server.py +++ b/mail/server.py @@ -161,7 +161,11 @@ def _discover_folders(acct_path): def _open_folder(acct_path, folder_name): - path = os.path.join(acct_path, folder_name) + base = os.path.realpath(acct_path) + path = os.path.realpath(os.path.join(base, folder_name)) + # Path-Traversal verhindern: muss innerhalb des Account-Verzeichnisses bleiben + if path != base and not path.startswith(base + os.sep): + return None return mailbox.Maildir(path, create=False) if os.path.isdir(path) else None diff --git a/tests/test_all.py b/tests/test_all.py index fc06d9e..f625950 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -48,12 +48,12 @@ def get_token_pkce(port): challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b"=").decode() r = httpx.get(f"http://127.0.0.1:{port}/authorize", params={ "response_type": "code", "client_id": "test", - "redirect_uri": "http://localhost/cb", "code_challenge": challenge, "code_challenge_method": "S256", + "redirect_uri": "https://claude.ai/api/mcp/auth_callback", "code_challenge": challenge, "code_challenge_method": "S256", }, follow_redirects=False, timeout=10) assert r.status_code == 302 code = r.headers["location"].split("code=")[1].split("&")[0] r2 = httpx.post(f"http://127.0.0.1:{port}/token", data={ - "grant_type": "authorization_code", "code": code, "client_id": "test", "code_verifier": verifier, + "grant_type": "authorization_code", "code": code, "client_id": "test", "client_secret": TEST_SECRET, "code_verifier": verifier, }, timeout=10) assert r2.status_code == 200 return r2.json()["access_token"]