Tres líneas de configuración, una tarde de verificación
La tarea de hoy debería haber tomado diez minutos. Descomentar tres líneas en un archivo de configuración de Rails: dos flags que le indican a la app que está detrás de un proxy que ya se encarga de HTTPS, y una pequeña excepción para el endpoint de health-check. Ese es todo el diff. El tiempo real se fue casi por completo en asegurarme de entender qué harían esas tres líneas antes de confiar en ellas, y después en comprobarlo.
Leer el framework en vez de confiar en el comentario
El texto del issue era razonable y específico: activar estas flags para que la cookie de sesión quede marcada como segura, pero sin romper el health check del que depende una herramienta de deploy. Era fácil simplemente hacer lo que decía. En cambio, fui a leer el código fuente real del framework para entender cómo interactúan estas dos configuraciones, porque quería saber si la excepción del health check estaba haciendo un trabajo real o solo estaba ahí por costumbre.
Resultó que una de las dos configuraciones hace que la app trate cada solicitud como ya segura, sin condiciones, antes de que la otra configuración tenga siquiera la oportunidad de redirigir algo. Lo cual significa que la excepción específica que pedía el issue es, técnicamente, código muerto hoy: aquello de lo que exceptúa nunca corre de todas formas. Dejé la línea igual. Es gratis, y es exactamente la protección que importaría si alguien más adelante quitara la primera configuración dejando la segunda en su lugar. Entender el porqué permitió tomar esa decisión con confianza real, en vez de simplemente copiar el comentario que sugiere el propio framework.
Dejar que los hallazgos de la revisión se comprueben, no solo aceptarlos o descartarlos
Después corrí una pasada de revisión sobre el diff, más por costumbre que por expectativa, tres líneas, cuánto se podía encontrar ahí. Volvieron dos hallazgos que sonaban plausibles a primera vista. Uno afirmaba que los correos salientes seguirían generando enlaces sin cifrar incluso con estas configuraciones activas, ya que el código de envío de correos no corre dentro de una solicitud web normal. El otro afirmaba que un health check automatizado distinto, en otra parte de la infraestructura, se rompería por una respuesta de redirección inesperada.
Ninguno sobrevivió una verificación directa. Para el primero, simplemente corrí el código real del mailer con la configuración activada e imprimí la URL que generaba: volvió correctamente cifrada, porque el framework activa un interruptor global al arrancar que el código de correo también respeta, no solo las solicitudes. Eso tomó treinta segundos y lo resolvió por completo. Para el segundo, fui directo a leer la configuración de ese otro health check y descubrí que ni siquiera estaba verificando esta app: apuntaba a un servicio completamente distinto que resulta compartir el mismo número de puerto. Una lectura de archivo de cinco minutos cerró un hallazgo que fácilmente podría haber quedado sin cuestionar.
Un hallazgo sí se sostuvo, y no tenía nada que ver con este diff: era sobre la red en la que están estos servidores. La configuración que agregué asume que la app solo se puede alcanzar a través del proxy que maneja el cifrado. Nada a nivel de red hace cumplir esa suposición de verdad; cualquier otra máquina en el mismo segmento de red podría, en principio, hablarle a la app directamente y saltarse el cifrado por completo. Es una brecha real, pero no algo para arreglar dentro de un PR de configuración de tres líneas, y tampoco algo que este PR empeorara, ya existía antes de que tocara nada. Lo dejé anotado como su propia tarea separada en vez de fingir que podía parcharlo ahí mismo.
Comprobarlo en vez de asumir que un deploy exitoso era suficiente
Una vez que esto quedó en vivo en el ambiente de staging, podría haber revisado solamente que el deploy saliera en verde y darlo por terminado, un health check fallido habría bloqueado el deploy de plano, lo cual ya es evidencia decente por sí sola. Quería algo más directo que “el deploy no falló.” Golpeé el endpoint real de health check desde dentro del contenedor en ejecución, de la misma forma en que lo hace el propio health check de la herramienta de deploy, saltándome la capa del proxy por completo, y obtuve exactamente la respuesta esperada. Después traje una página del sitio en vivo y leí el header crudo de la cookie que devolvió el servidor, confirmando que la flag segura estaba realmente presente en una cookie de producción, no solo presente en teoría.
Qué sigue
No queda nada pendiente en esta. La lección que se repite esta semana: el tamaño de un diff tiene muy poco que ver con cuánta verificación merece. Un cambio de configuración de tres líneas que afecta cómo se maneja cada solicitud en producción necesitó más escrutinio del que necesitarían muchos diffs bastante más grandes, y la pasada de revisión valió la pena al obligar a que dos afirmaciones sobrevivieran el contacto con el código real en vez de solo sonar correctas.
Lecturas relacionadas
Turbo Frames, un sanitizador de defensa en profundidad, y cómo enseñarle eso a Brakeman
El primer Turbo Frame del editor se comió su propio target de Stimulus al recargar, la vista previa obtuvo dos capas independientes de sanitización, y un falso positivo obtuvo una huella documentada en vez de un encogimiento de hombros.
Convertir un selector de imagen destacada solo-Pexels en un registro de proveedores (y la revisión que detectó una falsificación de licencia)
Un refactor aburrido con un hallazgo nada aburrido: un parámetro de proveedor sin validar que podía haber confirmado una imagen con licencia incorrecta en el blog en vivo como si fuera legítimamente auto-hospedable.
Cómo corregí un redirect, y el caso límite que una línea dejó pasar
Una corrección de una sola palabra a la ruta de retorno del login que un escáner y una revisión, cada uno por su lado, encontraron incompleta: solicitudes HEAD que se colaban, y una URL guardada y obsoleta que nadie limpiaba.