Un desarrollador solicita a un asistente que corrija una consulta de búsqueda de clientes que está fallando. El parche sugerido logra que la prueba pase, pero sustituye el filtro acotado al tenant (inquilino/cliente) por una búsqueda basada únicamente en el customerId. Tras fusionarse la pull request, un usuario que conoce el identificador de otro tenant recibe el registro de dicho cliente. El atacante no necesitó acceso al repositorio, al sistema de CI ni al asistente de programación; simplemente utilizó una solicitud normal de la aplicación dirigida a un endpoint cuya comprobación de autorización había desaparecido silenciosamente.
Un cambio no verificado es cualquier propuesta de modificación de código, dependencia, configuración o flujo de trabajo que aún no ha superado controles independientes de su autor. El resultado generado por el asistente entra en esta categoría incluso cuando compila, cuenta con una explicación plausible y corrige el defecto reportado. El asistente generó el texto a partir de la instrucción (prompt) y del contexto del repositorio; ninguna de estas características garantiza que la consulta resultante preserve los límites de aislamiento entre tenants de la aplicación.
La ruta relevante atraviesa varios límites. El parche del asistente, la versión del paquete sugerida y cualquier configuración generada ingresan al repositorio como artefactos no verificados. El sistema de CI examina el cambio propuesto, pero no determina automáticamente que la autorización sea correcta. En producción se ejecuta únicamente el artefacto fusionado, donde la ausencia del filtro provoca que los datos de un cliente queden expuestos a otro tenant. El siguiente mapa de límites distingue claramente dichos artefactos:
El mapa de límites muestra por qué el curso utiliza un contrato de seguridad único. Trate cualquier artefacto generado por IA como no confiable hasta que una revisión humana independiente y las comprobaciones automatizadas requeridas acepten el cambio. El modelo nunca es el punto de aplicación de las normas de seguridad. Un prompt que solicita aislamiento de inquilinos (tenant isolation) representa una preferencia transmitida por el mismo canal que el código sugerido, no un control que bloquee una fusión (merge) insegura.
Para el parche de búsqueda de clientes, el revisor de la solicitud de extracción (pull request) verifica si la consulta sigue aplicando los derechos de acceso al inquilino correspondientes al usuario autenticado. El sistema de integración continua (CI) examina diferentes evidencias: el análisis del código fuente inspecciona los patrones de implementación, el análisis de dependencias revisa el paquete recién añadido y el escaneo de secretos busca credenciales en el código y la configuración modificados. La protección de ramas del repositorio hace cumplir la decisión de fusión al exigir dichas comprobaciones y aprobaciones. Ningún control debe basarse únicamente en la afirmación del asistente de que el parche es seguro.
Regla del examen
El código generado por IA solo se acepta cuando una revisión independiente y los controles de seguridad (security gates) requeridos generan evidencia registrada. La salida del modelo y la redacción del prompt no garantizan el control de acceso.
Cada control tiene limitaciones. Una revisión humana puede pasar por alto un error sutil en el flujo de datos, por lo que las comprobaciones automatizadas aportan información adicional. Un escáner puede no detectar lógica de autorización que requiera contexto de la aplicación, por lo que la revisión cualificada sigue siendo obligatoria. Que una canalización (pipeline) se complete con éxito no demuestra la ausencia de vulnerabilidades; demuestra que existe la evidencia requerida por los controles definidos para esa revisión. Cuando un control obligatorio falla, el repositorio registra el hallazgo, bloquea la fusión según la política establecida y conserva un registro de auditoría para la decisión de aceptación o excepción.
El artefacto en cuestión es una solicitud de extracción que añade un endpoint GET /search?q=... a un servicio web multiinquilino e incorpora una dependencia para búsqueda de texto. La solicitud del usuario se considera una entrada no confiable. El controlador recibe la identidad del usuario autenticado, construye una consulta a la base de datos y debe aplicar los derechos de acceso al inquilino correspondientes a dicho usuario antes de que la base de datos devuelva resultados. La operación de base de datos se ejecuta bajo la identidad de servicio de la aplicación, mientras que la capa de consulta o de políticas controla lo que el usuario final puede ver. Si el nuevo endpoint acepta un tenantId de la solicitud sin compararlo con los derechos de acceso autenticados, el alcance del impacto potencial abarca todos los registros accesibles a través de esa identidad de servicio.
La propia solicitud de extracción (pull request) tampoco es de confianza. Su diferencia (diff) podría eliminar el predicado del inquilino (tenant), su manifiesto de dependencias podría introducir un paquete vulnerable o inapropiado, y su configuración generada podría contener un secreto expuesto. La explicación del asistente no puede resolver ninguna de estas cuestiones. Las pruebas provienen de la diferencia, el manifiesto de dependencias modificado, las categorías del escáner, la aprobación del revisor y el registro de fusión (merge).
Una prueba estática de seguridad de aplicaciones analiza el código fuente y el flujo de datos a nivel de código en busca de patrones de vulnerabilidad conocidos. El análisis de composición de software examina las dependencias y los metadatos de los componentes para detectar condiciones relacionadas con la cadena de suministro. El escaneo de secretos busca credenciales o tokens en los artefactos modificados del repositorio que no deberían confirmarse (commit). Estas comprobaciones inspeccionan artefactos diferentes, por lo que un resultado positivo en una no puede sustituir a otra. La ruta de la solicitud y la ruta de CI muestran dónde se originan las sugerencias y dónde la verificación genera pruebas de aceptación: