Candados en las puertas de atrás: crons, API keys y colas
En una plataforma con módulos de pago apareció un hallazgo serio: desde el panel se podían encender funciones pagadas sin haberlas contratado. La corrección obvia fue agregar la validación en las rutas del panel. Se probó, funcionó, y el agujero seguía abierto. No por el panel, sino por cuatro puertas traseras que no pasaban por ahí.
El problema de fondo
Una regla de negocio que decide si algo se puede usar, como "el módulo está contratado, vigente y encendido", suele ponerse en el middleware que protege las rutas del panel. Eso protege el panel. No protege el efecto: enviar el mensaje, generar el archivo, llamar a la API externa. Y en casi cualquier sistema hay más de un camino que produce el mismo efecto.
Puerta 1: la API pública con llave
Muchos sistemas ofrecen una API para que el cliente se integre, con una llave por cuenta. La llave autentica: dice quién hace la petición. No autoriza: no dice si esa cuenta tiene derecho hoy a lo que pide. Una llave creada cuando el módulo estaba contratado sigue funcionando para siempre si nadie vuelve a consultar el contrato en cada uso.
Puerta 2: los crons
Los procesos programados no entran por HTTP, así que no pasan por ningún middleware. Un envío programado, un recordatorio o una sincronización diaria siguen corriendo para cuentas que ya no tienen el módulo. En un cron, la regla debe estar en la propia consulta que selecciona qué procesar. Y para que no se desincronice, esa condición SQL debería generarse desde la misma función que usa el resto del sistema, no copiarse a mano.
Puerta 3: despachadores y colas
Un webhook pendiente, un mensaje en cola o un reintento se crearon cuando la cuenta tenía permiso. Entre la creación y el despacho, el módulo pudo vencer. Si el despachador procesa la fila sin volver a comprobar, ejecuta algo que ya no corresponde. La verificación va al momento de ejecutar, no solo al momento de encolar.
Puerta 4: servicios llamados desde varios sitios
Un servicio de envío puede llamarse desde el panel, desde la API, desde un cron y desde un flujo automático. Poner la validación en cada llamador garantiza que algún día se olvide en uno. La regla va en el único punto de efecto: dentro de la función que envía, que es por donde todos pasan.
Cómo encontrarlas
La técnica es cambiar la pregunta. En vez de buscar dónde se autoriza la función, se busca dónde se produce el efecto. Si el efecto es enviar un mensaje, se buscan todas las llamadas a la función de envío en el código, y se comprueba cada una: ¿desde aquí se puede llegar sin haber validado? Una búsqueda de texto bien hecha lista todos los caminos en segundos.
Cerrar un agujero en la puerta principal no lo cierra en la casa. Busca todas las puertas que dan al mismo cuarto.
Lista de comprobación
- ¿La API con llave vuelve a consultar el contrato en cada petición?
- ¿Los crons filtran por la regla dentro de su consulta?
- ¿Los despachadores verifican al ejecutar, no solo al encolar?
- ¿La regla vive en el punto de efecto y no en cada llamador?
- ¿Hay una sola fuente de verdad para la regla, usada en todos esos sitios?
Esta revisión aplica a cualquier invariante de acceso: planes y módulos de pago, cuentas suspendidas, límites de consumo o permisos por rol. Cada vez que se corrige una autorización, vale la pena recorrer las cuatro puertas antes de darla por cerrada.