# Seguridad

FOSFENO es un **aparato de directo**, no un servicio en internet. Está pensado
para una red local: tú, tu móvil y el proyector. Esta página cuenta qué asume
el diseño, qué pasa si la red no es de fiar, y cómo cerrarlo.

## El modelo de amenaza, en una frase

Cualquiera que alcance `http://<ip-de-fosfeno>/` **manda sobre las visuales**.
Por defecto no hay contraseña: es lo cómodo para casa, un ensayo o una red
tuya, y es como funcionó desde el principio.

Eso está bien en tu salón. En **la wifi de un bar o de un festival** significa
que un desconocido puede:

- Apagar o reiniciar el equipo en mitad de la sesión.
- Cambiar de motor, de preset y de mapping.
- **Ejecutar código** en el escenario, porque el editor de Hydra/GLSL es
  precisamente eso, y el navegador del kiosko arranca con permiso automático de
  **cámara y micrófono**.
- Llenarte la tarjeta subiendo archivos a la galería.

No es un fallo escondido: es la consecuencia de no pedir credenciales. La
solución está abajo y son dos líneas de configuración.

## La clave compartida

En `config.json`:

```json
"auth": {
  "token": "loquesea-largo-y-tuyo"
}
```

O sin tocar el archivo, por variable de entorno:

```bash
FOSFENO_TOKEN=loquesea-largo-y-tuyo ./fosfeno
```

Con la clave puesta:

- **El código QR del proyector ya la lleva dentro.** Escaneas y entras, igual
  que siempre. No hay que teclear nada.
- Quien solo conozca la IP **no se conecta**: el WebSocket rechaza la conexión,
  así que no puede ni mirar el estado ni mandar órdenes.
- Las subidas a la galería también la piden.
- El escenario la recibe del propio servidor al abrirse. No hay nada que
  configurar en el navegador.

La contrapartida: si escribes la dirección a mano tendrás que añadir
`?k=tu-clave` al final. Por eso el QR es el camino cómodo.

> Con `token` vacío (el valor de fábrica) todo funciona exactamente como antes.
> Actívala cuando pinches fuera de casa.

## Lo que ya está cerrado

Estas no dependen de que actives nada:

| | |
|---|---|
| **Path traversal** | Las rutas de archivos (`/panel`, `/stage`, `/lib`, `/data`, `/pm/variantes`) resuelven y comprueban que no salen de su carpeta. Probado con `../`, `%2e%2e%2f`, doble codificación y rutas absolutas |
| **Nombres de archivo subidos** | Pasan por `secure_filename` y una lista blanca de extensiones. No se puede escribir fuera de `data/videos` ni subir un `.sh` |
| **Inyección de comandos** | Ningún `shell=True`, ningún `os.system`. Todos los procesos se lanzan con lista de argumentos |
| **Rutas de presets de projectM** | La categoría y el visual vienen del panel, así que se validan contra la carpeta de presets antes de usarse |
| **XSS en el panel** | Los nombres de clips, capas y favoritos se pintan con `textContent`, nunca con `innerHTML` |
| **CORS** | El WebSocket solo acepta su **mismo origen**. Antes admitía cualquiera, así que una web abierta en el móvil de alguien de la sala podía mandar órdenes |
| **Tamaño de subida** | 512 MB por archivo (antes 4 GB, suficiente para llenar una microSD en tres peticiones) |
| **Payloads del WebSocket** | Los ajustes se filtran por lista blanca de claves y las capas del mapping se sanean antes de guardarse, así que no se puede meter basura en el estado ni en `data/mapping.json` |

## Lo que NO deberías hacer

- **No lo expongas a internet.** Nada de abrir el puerto 80 en el router ni
  ponerle un túnel. No está pensado para eso y la clave compartida no es
  autenticación seria.
- **No dejes el apagado remoto a mano de una red pública** sin clave. El
  instalador da permiso `sudo` sin contraseña para `reboot` y `poweroff`
  (`install.sh`), que es lo que hace que el botón del panel funcione.
- **No pongas datos personales en `data/videos`.** Cualquiera que entre al
  panel puede listarlos y reproducirlos.

## Lo que no se sube al repositorio

`.gitignore` deja fuera lo de cada instalación: `.venv/`, `*.log` (el log del
servidor lleva IPs), `data/mapping.json`, `data/pm-favoritos.json`,
`data/videos/*` y `data/presets-projectm/`. En el repo solo van código,
documentación y los presets de fábrica.

## Si encuentras algo

Es un proyecto pequeño de un hacklab: abre una incidencia en el Gitea del
proyecto contando qué has visto y cómo reproducirlo.
