7 puntos por GN⁺ 2025-06-09 | 2 comentarios | Compartir por WhatsApp
  • Cloudflare desarrolló una nueva biblioteca de proveedor OAuth usando el LLM Claude de Anthropic y también publicó los prompts
  • La estructura del código es limpia, pero deja bastante que desear en pruebas y validación de seguridad
  • Se encontraron decisiones no estándar o riesgosas en CORS y en la implementación de algunas especificaciones de autenticación
  • Aunque la implementación criptográfica tiene puntos fuertes, también reveló bugs de seguridad graves y malentendidos del protocolo
  • La codificación automática basada en LLM puede ayudar, pero para una seguridad de nivel productivo sigue siendo indispensable una revisión minuciosa por parte de expertos

Panorama general de la biblioteca OAuth de Cloudflare

  • Cloudflare escribió en gran parte de forma automática una biblioteca de proveedor OAuth utilizando el LLM Claude de Anthropic
  • El resultado de Claude pasó por una revisión de seguridad y cumplimiento de estándares hecha por ingenieros experimentados de Cloudflare, y la empresa mostró de forma transparente en el historial de commits cómo fue la interacción con la IA
  • Después de la implementación inicial, la calidad se fue ajustando mediante prompts adicionales a Claude y revisión de los resultados
  • Se deja claro que no dependieron solo de la IA, sino que se enfatiza la verificación cruzada con documentos RFC y la revisión de expertos clave

Primera impresión del experto y análisis del código

  • Como suele pasar con el estilo de programación de los LLM, el código está concentrado en un solo archivo, aunque la estructura es consistente y hay relativamente pocos comentarios innecesarios
  • Hay pruebas funcionales, pero no alcanzan el nivel exigido para un servicio crítico de autenticación como OAuth
    • Se notan omisiones en verificaciones obligatorias de la especificación (MUST/MUST NOT) y una validación débil de parámetros

Preocupaciones de seguridad y explicación del traductor

1. Problema con la política CORS ("YOLO CORS")

  • Se encontró una configuración de encabezados CORS que permite casi cualquier origen, lo que prácticamente desactiva la política del mismo origen
  • Esta fue una parte decidida directamente por una persona, no por el LLM
  • Como la función de credentials no está habilitada, el riesgo de una amenaza crítica de seguridad en el navegador es menor, pero falta claridad sobre la causa y el objetivo de esa decisión

2. Falta de encabezados estándar de seguridad

  • En las respuestas HTTP faltan X-Content-Type-Options: nosniff y HTTP Strict Transport Security, entre otros encabezados de seguridad clave
  • Por la naturaleza de una API JSON, algunos encabezados pueden parecer menos necesarios, pero su aplicación sigue siendo importante para prevenir vulnerabilidades en clientes y navegadores

3. Señales de poco dominio del estándar OAuth

  • Para admitir public clients, se implementó el método implicit grant, que fue retirado en OAuth 2.1
    • En realidad, esa función podía sustituirse suficientemente con PKCE o con una flexibilización de CORS
    • Parece que Claude recomendó implicit grant, y en la etapa real de emisión del token ni siquiera lo valida correctamente
  • Manejo deficiente de Basic Auth: en OAuth se requiere un esquema particular de codificación URL, pero aquí se omitió
    • Eso puede derivar en un bug de seguridad secundario si el client secret incluye dos puntos
    • Aun así, la biblioteca genera por sí misma el client ID y el secret, por lo que puede controlar el formato

4. Problemas de seguridad en el código de generación de IDs de token

  • El método de generación de cadenas aleatorias para IDs de token tiene un sesgo estadístico (biased)
    • La reducción de entropía podría facilitar ataques, aunque la amenaza práctica parece limitada
  • A diferencia de la afirmación de que "cada línea de código fue revisada por expertos", el bug seguía presente en el commit inicial
    • El hecho de que un desarrollador hiciera 21 commits directos a la rama principal el primer día sugiere falta de una revisión sistemática

Funciones criptográficas y ejemplos de interacción con el LLM

  • El diseño del cifrado del almacén de tokens estuvo dirigido por humanos, mientras que Claude apoyó en la implementación
  • Se aplicó un método que cifra las props de cada token y envuelve una clave simétrica para cada token
  • Cuando Claude propuso a mitad del proceso un diseño incorrecto, el ingeniero dejó clara la intención y el objetivo de seguridad para corregirlo
    • Ejemplo: tras señalar la vulnerabilidad que surgiría al usar un hash SHA-256 como wrapping key, se cambió a un enfoque basado en HMAC
    • Ante la propuesta de PBKDF2, se marcó su ineficiencia de rendimiento y se ajustó a una clave HMAC de 32 bytes
  • Este proceso muestra bien que trabajar con IA exige un alto nivel de conocimiento del dominio
    • Para alguien no especialista, incluso detectar una falla crítica puede ser muy difícil

Evaluación general e implicaciones

  • Aunque es una primera versión y el nivel general es aceptable, sigue siendo arriesgado aplicarla directamente en producción
  • Desarrollar un proveedor OAuth requiere por naturaleza una validación de seguridad y funcionalidad extremadamente exigente
    • En grandes empresas es normal contar con cientos de miles de pruebas automatizadas y revisiones de seguridad en múltiples capas
    • No es un área donde la codificación automática basada en LLM pueda aplicarse “fácilmente”
  • El historial de commits del proyecto muestra de forma interesante hasta qué punto un LLM puede funcionar como apoyo
    • Aun así, algunos defectos son errores que tanto los LLM como las personas cometen con frecuencia, y también aparecen en respuestas de Stack Overflow y otras comunidades
    • En áreas de código donde importan la minuciosidad y el detalle, tanto la IA como los humanos necesitan una atención muy cuidadosa
  • Para revisar código con ayuda de LLM o confiar en sus resultados, es indispensable tener experiencia real de implementación y pensamiento de System 2
    • En tareas simples o no críticas, el LLM puede encargarse suficientemente, pero en sistemas clave relacionados con autenticación o seguridad conviene que el diseño y la implementación estén liderados por expertos

2 comentarios

 
GN⁺ 2025-06-09
Opiniones en Hacker News
  • Este caso deja muy claro que hace falta mucho conocimiento de dominio al interactuar con un LLM. Por ejemplo, un desarrollador común podría no darse cuenta del “defecto crítico” que Claude inventó a mitad del proceso. Incluso notar como extraña la migración a PBKDF2 depende de tener experiencia en el tema. Mi conclusión es que, para aprovechar bien un LLM, hace falta un buen revisor y un buen “líder”. Si sabes menos que el LLM sobre el tema en cuestión, entonces necesariamente debe tratarse de algo de baja importancia o debes tener suficiente tiempo para validar toda la salida.

    • En este nuevo entorno me da curiosidad de dónde van a salir los expertos de dominio. Al final, me pregunto quién va a poder llegar a saber tanto en profundidad.

    • Siempre me parece extraña la opinión de que “solo se usa LLM en áreas que uno no conoce; si eres experto, programas directo”. Más bien, mientras más experto seas, mejor puedes revisar la salida del LLM, y mientras más se parezca tu forma de explicar lo que quieres a la de un experto del dominio, mejor sale el resultado. En cierto modo es obvio, porque un LLM es un motor de texto generado estadísticamente.

    • Los LLM tienden demasiado a agregar valores por defecto, manejo de excepciones y todo tipo de atajos. Por eso generan con facilidad código que parece funcionar, pero que en realidad tiene problemas o está a punto de fallar. Intenté enfatizar esto varias veces en el CLAUDE.md que escribí, pero aun así a veces seguía produciendo ese tipo de resultados.

    • Yo he usado LLM para hacer la mayor parte del trabajo de despliegue en k8s. Sí produce algo funcional rápido, pero siempre había que recordarle que usara secretos y que no hiciera commits de credenciales en texto plano. Ese tipo de error es realmente peligroso. En tutoriales educativos a menudo omiten seguridad para enfocarse en lo básico, y como hay demasiados ejemplos así en los datos de entrenamiento del LLM, supongo que por eso responde de esa manera.

    • Con el tiempo espero que las herramientas de programación con IA puedan investigar por sí solas el conocimiento de dominio. Algunas herramientas de “investigación con IA” que ya existen son muy buenas en eso, pero todavía no están bien integradas con las herramientas de código. La investigación podría apoyarse no solo en internet público, sino también en conocimiento de dominio contenido en documentación interna de la empresa. Aun así, parte de ese conocimiento solo está en la cabeza de las personas, así que el usuario tendrá que transmitirlo directamente.

  • Hace poco escribí un consumer de Kafka con ayuda de IA para una migración de datos. Este tipo de proyecto corto, hecho desde cero, donde yo sí conozco bastante bien el lenguaje (Go) pero llevaba tiempo sin usarlo, fue justo el escenario donde el uso de IA dio el máximo rendimiento. Como todos los datos llegaban a un solo topic, implementé un procesamiento paralelo bastante complejo para asegurar rendimiento. En general, sentí que con IA fui como 2 veces más rápido. En particular ayudó mucho poder preguntarle directo en vez de buscar cuando olvidaba algo de sintaxis de Go. Pero había al menos 4 bugs potenciales escondidos, además de muchos más bugs obvios. Si no hubiera estado familiarizado con Kafka o con multithreading, probablemente lo habría mandado a producción de inmediato. En proyectos grandes o de largo plazo, la mejora ronda entre 10% y 20%. Esa es la tendencia con los modelos actuales. En conjunto, esto se parece al aumento de productividad que se obtuvo al cambiar a lenguajes con gestión de memoria. Está muy lejos de esa fantasía donde un PM reemplaza a los desarrolladores, al menos a la velocidad de cambio de los últimos 3 años. Mi verdadera preocupación es más bien que, si un desarrollador de nivel medio con talento “tipo tormenta técnica” se vuelve 10 veces más eficiente gracias a la IA, también podría volverse más peligroso al no detectar ni saber responder a bugs sutiles. No creo que los ingenieros senior/staff puedan soportar una avalancha de revisiones. Y también me preocupa que el proceso de crecer de junior a senior se vuelva más frágil. Ya de por sí los programadores de copiar y pegar son un problema, y la IA solo refuerza ese patrón. El mercado terminará resolviéndolo, pero me inquieta pensar que eso podría tardar décadas.

    • Los bugs que genera la IA son realmente sutiles. Yo también puse en producción un bug sutil después de hacer que la IA escribiera código multihilo. Aunque haya revisión y pruebas, no se alcanza el mismo nivel de concentración que cuando uno lo escribe a mano. Por un tiempo, siento que el código escrito por IA debería usarse solo en áreas donde ya sepamos qué bugs típicos revisar y donde un fallo no tenga impacto crítico.

    • Yo también siento una mejora de alrededor de 10% a 20% en “trabajo importante”. Es un cambio real, pero no altera la esencia del desarrollo de software. Al final, es una reafirmación de la tesis de Brooks en "No Silver Bullet".

    • También coincido con el punto del “talento técnico intermedio tipo tormenta”. Sobre todo en consultoría, donde la realidad es que a menudo se trata a los veteranos como si ofrecieran poco valor frente a su costo. Antes yo también era del tipo que resolvía rápido, y más adelante me tocó sufrir explicándole a PMs no técnicos las debilidades de soluciones de corto plazo. Las grandes empresas tecnológicas probablemente detecten este problema rápido, pero en la práctica el código que maneja datos financieros o médicos muchas veces lo escriben contratistas temporales baratos. Eso ya era un problema antes de los LLM. Ahora debe ser una época mucho más difícil para los desarrolladores que trabajan en áreas sensibles a seguridad.

    • Mencionaste que encontraste bugs sutiles en el código generado; me hace pensar si sería posible detectar automáticamente esos bugs con tests también generados por IA. Claro, el propio código de prueba también podría tener bugs, pero me imagino un futuro donde nos enfoquemos más en revisar los resultados de las pruebas que el código generado en sí.

    • Dices que había procesamiento paralelo complejo, pero me pregunto si eso no era algo que podía resolverse aprovechando partition y consumer-group.

  • Me desespera ver gente que confía activamente en los LLM y trabaja apoyándose en ellos de forma acrítica, como si se lanzaran por un precipicio. Es peligroso depender por completo de una caja negra para hacer el trabajo y además delegarle la validación. Encima, es una estructura que consume una cantidad enorme de energía, y también se usa como excusa para reemplazar personas. Sinceramente, no me creo eso de que este entorno haga la vida 10 veces mejor.

  • Cuando comparas desarrollar algo tú mismo frente a validar el resultado hecho por otra persona, especialmente código generado por LLM, los humanos muchas veces tendemos a dejarnos engañar por una apariencia plausible y aceptar los problemas con menos sentido crítico. La “forma” del código también influye mucho en encontrar bugs. Para comprobarlo, una forma sería insertar bugs a propósito en el código y hacer un experimento para ver si los revisores los detectan. Cuando uno implementa algo con sus propias manos, piensa mucho más despacio, con más detalle, y presta atención a los detalles, por eso descubre bugs inesperados. Por eso suelen recomendar que, con fines de aprendizaje, la mejor forma es implementar una “versión de juguete” de la herramienta por cuenta propia. Es algo conectado con cómo funciona la cognición humana.

    • La capacidad de encontrar bugs sutiles en código que se ve limpio por fuera nace de una mezcla de cinismo y sospecha adquirida con mucha experiencia revisando. Como he dedicado muchísimo tiempo a hacer reviews, ahora siempre asumo que cualquier código tiene problemas potenciales. No sé si habría menos bugs si yo mismo lo hubiera escrito, porque también he cometido muchos errores tontos en mi propio código, así que no puedo asegurarlo. De hecho, es poco probable que yo mismo hubiera terminado usando esta librería, porque tengo demasiadas cosas que hacer y normalmente eso acaba en manos de ingenieros junior. Lo que sí tengo claro es que el hecho de que un humano escriba el código no elimina los bugs. De hecho, muchos de los bugs que produjo Claude son del tipo totalmente típico que una persona podría cometer sin problema. Por otro lado, por ahora no creo que en Cloudflare los desarrolladores vayan a ser reemplazados por LLM. Contratar más gente no depende de cuánto trabajo haya, sino del presupuesto. Si los LLM mejoran la productividad, eso podría traducirse en mayores ingresos y en un ciclo de contratación de más personas. (Claro, esta es una opinión personal, no la postura oficial de la empresa).
  • En el artículo dijeron que no había demasiados comentarios innecesarios, pero en el código real sí hay comentarios sin sentido como // Get the Origin header from the request.

    • Ese tipo de comentario es una señal muy clara de que se usó un LLM; no aporta nada y siempre lo borro.

    • Para una persona esos comentarios no sirven, pero sospecho que, desde la perspectiva del LLM, tener la función del código escrita también en lenguaje natural podría ayudarle a entenderlo, como una especie de piedra de Rosetta. Tal vez el costo sea gastar más tokens, pero sí me daría curiosidad comprobar si un LLM realmente edita mejor código con exceso de comentarios.

    • Comparto la experiencia de que Claude tiene una fuerte tendencia a escribir este tipo de comentarios inútiles y redundantes con muchísima frecuencia.

  • Algo que me gustaría proponer es congelar una rama del código y luego usar IAs para que por un lado intenten crear y ocultar vulnerabilidades, y por otro intenten encontrarlas y corregirlas. O sea, aplicar a desarrollo de software la evolución tipo ajedrez.

  • Yo soy justamente el autor de esta librería, o más precisamente el autor del prompt. No soy tan experto en OAuth como Neil, pero sí conozco bastante del tema, y me dio mucho gusto que él revisara el código. Hubo un malentendido con lo de “YOLO CORS”, pero no fue un error tonto de principiante. Esas configuraciones de CORS se hicieron a propósito, después de pensarlas bien. Solo deshabilitamos CORS en los endpoints del API de OAuth, como intercambio de tokens y registro de clientes, y en endpoints de API que requieren OAuth bearer token. Esos endpoints no se autentican con credenciales del navegador, como cookies, así que concluí que en realidad CORS no estaba protegiendo nada ahí. La esencia de CORS es ser una barrera de seguridad que evita adjuntar credenciales automáticamente; como el bearer token debe ser adjuntado explícitamente por el cliente, sigue siendo seguro incluso en cross-origin. De hecho, hace tiempo discutí esto con autores de la especificación de CORS, porque he sostenido que la verdadera seguridad está en usar bearer tokens en vez de credenciales del navegador. Por otra parte, sobre la crítica de que la generación del ID de token era ineficiente, no creo que llegue a ser “crítica”. La seguridad en sí no está comprometida, y además el algoritmo se puede cambiar después sin problema. Lo de los 21 commits a main en un mismo día hechos por una sola persona se ve así por cómo GitHub mostró las fechas después de reescribir el historial de git. Y gracias de verdad por los elogios a la implementación criptográfica. Eso no lo generó la IA; fue resultado de instrucciones explícitas de diseño de mi parte.

    • Dijiste “se deshabilitan los headers CORS en la API de OAuth”, pero en realidad lo que se hace es configurar los headers CORS para desactivar las reglas de CORS. Por el contexto se entiende, pero igual puede prestarse a confusión.

    • Me da curiosidad saber si Cloudflare planea usar esta librería en producción de verdad.

  • Me preocupa pensar que muchas respuestas populares de Stack Overflow tienen exactamente los mismos errores, y que Claude seguramente aprendió de ahí. Más que los huecos de seguridad o los errores en sí, lo que me da miedo es que el acervo de conocimiento social quede congelado en las respuestas populares de internet previas a la llegada de los LLM.

    • A mí también me preocupa. Si algunos servicios que uso declararan públicamente que “no usan LLM para escribir código”, eso sería un enorme punto de confianza.
  • Ver que en ForgeRock hubo cientos de bugs de seguridad en una implementación de OAuth, incluso con cientos de miles de pruebas automatizadas, modelado de amenazas, SAST/DAST de primer nivel y revisión de expertos, vuelve a dejar claro lo complicado que es OAuth. Algunos incluso la describen como una implementación “como incendio en un basurero”. Yo, de hecho, nunca he leído la especificación ni he intentado implementarla.

    • Siempre que me ha tocado participar en una implementación de OAuth, la experiencia ha sido terriblemente compleja.

    • OAuth es realmente molesto y tiene demasiados nichos.

    • En realidad, el código nuevo siempre va a tener bugs. Mientras más complejo sea, más seguro es eso. Por eso las empresas tratan de usar código y herramientas battle tested ya probados en campo. Bromas aparte, me parece interesante cómo Anthropic está usando de forma práctica su propia IA generativa sobre su propio código. Me pregunto si también la van a usar en la API de autenticación de MCP.

    • Eso de “cientos de miles de pruebas” suena a puro crecimiento cuantitativo, o hasta hace sospechar que de plano las generó un LLM. También me pregunto quién mantiene todo eso en la práctica.

  • Me pregunto si esta tendencia de hacer commit de los prompts al git se va a volver algo generalizado o si solo tiene un carácter de showcase.

    • La razón por la que hice commit del prompt es que me pareció una observación demasiado valiosa ver directamente qué resultados producía el LLM con ese prompt. Pensé que a otras personas también les resultaría interesante, y así fue. Por cierto, yo tampoco sabía cómo escribir “bien” prompts; simplemente lo redacté de forma natural, como se lo escribiría a una persona, y sentí que funcionó bastante bien.