merge: hardening seguridad osint_web (TrustedHost + escape iCal + tests del flag)

This commit is contained in:
2026-06-13 01:22:36 +02:00
3 changed files with 28 additions and 3 deletions
+1 -1
View File
@@ -7,4 +7,4 @@
"enabled_at": "2026-06-13"
}
}
}
}
+16 -2
View File
@@ -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:<cuerpo>" 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 --
+11
View File
@@ -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
# ---------------------------------------------------------------------------