diff --git a/dev/feature_flags.json b/dev/feature_flags.json index b93e283..b2e9cad 100644 --- a/dev/feature_flags.json +++ b/dev/feature_flags.json @@ -7,4 +7,4 @@ "enabled_at": "2026-06-13" } } -} +} \ No newline at end of file diff --git a/server/main.py b/server/main.py index b82c477..30843df 100644 --- a/server/main.py +++ b/server/main.py @@ -2199,7 +2199,9 @@ def _build_vcalendar(data: "EventIn", uid: str) -> str: body.append(vtz) vevent = [ "BEGIN:VEVENT", - "UID:%s" % uid, + # Sanitizamos el UID (quitamos saltos de línea) para que no pueda inyectar + # propiedades/componentes iCal nuevos en el VEVENT. + "UID:%s" % str(uid).replace("\r", "").replace("\n", ""), "DTSTAMP:%s" % dtstamp, _ical_dt_property("DTSTART", data.dtstart, tz, data.all_day), ] @@ -2219,7 +2221,10 @@ def _build_vcalendar(data: "EventIn", uid: str) -> str: # canónica "RRULE:" que entienden Xandikos y los clientes (DAVx5). if rrule.upper().startswith("RRULE:"): rrule = rrule[len("RRULE:"):].strip() - vevent.append("RRULE:%s" % rrule) + # Sanitizar: quitar saltos de línea para que el valor de la RRULE no + # inyecte propiedades/componentes nuevos (los `;`/`,` son separadores + # legítimos de la regla, así que no se escapan). + vevent.append("RRULE:%s" % rrule.replace("\r", "").replace("\n", "")) vevent.append("END:VEVENT") body.append("\r\n".join(vevent)) body.append("END:VCALENDAR") @@ -2240,6 +2245,15 @@ def create_app(vault_dir: str) -> FastAPI: """ state = VaultState(vault_dir) app = FastAPI(title="osint_web", version="0.1.0") + # Anti DNS-rebinding: solo acepta requests cuyo Host sea localhost. Cierra el + # vector por el que una web maliciosa rebindea su dominio a 127.0.0.1 y, desde + # el navegador del usuario, alcanza este service local (sin auth) o el de DuckDB. + from starlette.middleware.trustedhost import TrustedHostMiddleware + + app.add_middleware( + TrustedHostMiddleware, + allowed_hosts=["127.0.0.1", "localhost", "testserver"], + ) app.state.vault = state # -- Vault -- diff --git a/tests/test_server.py b/tests/test_server.py index 4e9bc87..7899c94 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -25,6 +25,17 @@ sys.path.insert(0, os.path.join(_HERE, "..", "server")) import main as srv # noqa: E402 +@pytest.fixture(autouse=True) +def _flag_off_por_defecto(monkeypatch, tmp_path): + """Por defecto los tests corren con OSINT_DB_BACKEND OFF (camino histórico + vault + Xandikos), independientemente del estado real de + ``dev/feature_flags.json`` en disco. Apunta ``_FLAGS_FILE`` a un archivo + inexistente (→ False). Los tests que prueban el camino ON sobrescriben + ``srv._FLAGS_FILE`` dentro del propio test, ganando sobre este default. + """ + monkeypatch.setattr(srv, "_FLAGS_FILE", str(tmp_path / "_no_flags.json")) + + # --------------------------------------------------------------------------- # Fixtures: vault sintético mínimo # ---------------------------------------------------------------------------