diff --git a/src/tinyweb/app.py b/src/tinyweb/app.py index b63ed3c..4bb059c 100644 --- a/src/tinyweb/app.py +++ b/src/tinyweb/app.py @@ -73,11 +73,22 @@ def load_or_create_identity(): return identity -# Remote peers on the Reticulum mesh can only reach a narrow, read-only surface. -# Any other method/path is rejected here — CSRF cannot authenticate mesh callers -# (the attacker controls both the "cookie" and the "form" side of the check), so -# gating by whitelist is the only safe option. -_RNS_ALLOWED = {("GET", "/api/sites")} +# Remote peers on the Reticulum mesh can reach read-only public pages. +# Only GET is allowed; POST is blocked because CSRF cannot authenticate +# mesh callers (the attacker controls both the "cookie" and the "form" side). +_RNS_ALLOWED_GET = { + "/", "/about", "/api/sites", "/share/preview", +} + +_RNS_ALLOWED_PREFIXES = ("/pages", "/tags", "/api/sites") + + +def _rns_is_allowed(method, path): + if method != "GET": + return False + if path in _RNS_ALLOWED_GET: + return True + return any(path.startswith(p) for p in _RNS_ALLOWED_PREFIXES) def rns_request_handler(path, data, request_id, link_id, remote_identity, requested_at): @@ -85,7 +96,7 @@ def rns_request_handler(path, data, request_id, link_id, remote_identity, reques data = {"method": "GET", "path": "/", "query": {}, "body": {}, "gateway_host": ""} method = data.get("method", "GET") req_path = data.get("path", "/") - if (method, req_path) not in _RNS_ALLOWED: + if not _rns_is_allowed(method, req_path): return { "status": 403, "content_type": "text/plain; charset=utf-8",