Cambios de propietario de repositorios: audita los accesos antes de la transición
Los cambios de propietario de un repositorio exigen algo más que mover un proyecto de Git. Audita personas, tokens, claves de despliegue, workflows, aplicaciones y acciones de agentes antes de que persistan los accesos.

Los cambios de propietario de un repositorio son eventos de seguridad, aunque la transferencia parezca una tarea administrativa rutinaria. El repositorio puede pasar a un equipo nuevo en una tarde, pero los permisos relacionados pueden seguir vinculados a mantenedores que ya se fueron, automatizaciones retiradas, cuentas antiguas de la nube y credenciales que nadie ha revisado en meses.
He visto equipos dar por terminada una transición después de cambiar el propietario del repositorio y eliminar a dos personas de la página de colaboradores. Después, un trabajo de despliegue olvidado sigue publicando con un token personal, una clave SSH huérfana todavía lee código privado o una aplicación antigua de Git hosting conserva autoridad para modificar pull requests. La página del repositorio parecía limpia. El plano de control real no lo estaba.
La regla práctica es sencilla: transfiere la propiedad solo cuando puedas nombrar cada identidad y servicio capaz de producir un efecto importante. «Importante» incluye leer código no público, subir commits, abrir o aprobar pull requests, cambiar definiciones de compilación, acceder a secretos, publicar paquetes, desplegar software y modificar los propios accesos.
Transferir un repositorio no transfiere la responsabilidad
El propietario de un repositorio es una etiqueta administrativa. La responsabilidad significa que una persona actual puede explicar a qué está conectado el repositorio, por qué existe cada conexión, quién la mantiene y cómo revocarla durante un incidente.
Son cosas distintas. Los permisos del servicio de Git describen el acceso dentro de un solo servicio. Los proyectos actuales también dependen de ejecutores de CI, registros de paquetes, roles de la nube, aplicaciones de análisis de código, bots de versiones, publicadores de documentación, notificaciones de chat, proveedores de DNS y almacenes de artefactos. Cada sistema tiene sus propias identidades y su propia memoria del proyecto.
La diferencia importa especialmente cuando un proyecto cambia de manos por una reorganización, una adquisición, una migración interna de plataforma o la salida de personal. El equipo receptor suele concentrarse en mantener la compilación en verde. El equipo saliente suele centrarse en eliminar sus nombres. Ninguna de las dos tareas demuestra que el control se haya transferido de forma segura.
Define por escrito el límite de propiedad antes de que nadie modifique los accesos. Debe identificar:
- al responsable técnico receptor que acepta la responsabilidad operativa
- al responsable de negocio que decide quién puede acceder al código y a las versiones publicadas
- al contacto para incidentes que puede autorizar una revocación urgente
- la fuente oficial de los miembros del repositorio y de las identidades de servicio
- la fecha en la que el equipo anterior pierde su autoridad
No uses un buzón compartido ni un nombre de equipo impreciso como propietario final. Un grupo puede recibir mensajes, pero no puede tomar una decisión a las dos de la madrugada. Identifica a personas concretas y revisa ese registro cuando cambie el equipo.
Hay otro punto incómodo: un proyecto sin propietario actual no debería conservar un acceso amplio a producción solo porque todavía se compile. Si nadie puede responder con seguridad por las credenciales de despliegue, pausa las versiones o reduce los permisos hasta que alguien pueda hacerlo. La disponibilidad no justifica conservar una autoridad desconocida.
Crea el inventario a partir de los efectos, no de la página del repositorio
Un inventario de accesos útil empieza por las acciones que pueden ocurrir y después retrocede hasta las identidades capaces de provocarlas. Empezar por la lista de colaboradores es más rápido, pero deja fuera demasiadas cosas.
Pregúntate qué puede ocurrirle a este proyecto sin que un desarrollador se siente en el sitio web del servicio de Git. Un bot puede enviar un commit. Un workflow de CI puede obtener un token de la nube. Un paquete puede publicarse cuando aparece una etiqueta. Un receptor de webhook puede activar un despliegue en producción. Una aplicación de revisión de código puede escribir comentarios o cambiar comprobaciones. Cada efecto apunta a un permiso que necesita un responsable.
Usa una tabla de trabajo con cinco columnas: capacidad, identidad, ubicación de la credencial, responsable actual y procedimiento de revocación. El procedimiento de revocación merece su propia columna porque «eliminar el token» a menudo no describe el proceso real. Puede que tengas que desinstalar una aplicación, eliminar una regla de confianza en la nube, borrar una clave de despliegue, invalidar un token del registro o cambiar un secreto del webhook en ambos extremos.
En una primera revisión, cubre estas categorías:
- Identidades humanas, incluidos colaboradores directos, equipos de la organización, colaboradores externos y administradores de la organización.
- Identidades no humanas, incluidos usuarios de máquina, cuentas de servicio, identidades de ejecutores de CI e instalaciones de aplicaciones.
- Credenciales, incluidas claves SSH de despliegue, tokens de acceso personales, claves privadas de aplicaciones, secretos de webhooks, tokens de registros y credenciales de la nube.
- Rutas de ejecución, incluidos archivos de workflows, referencias a workflows reutilizables, grupos de ejecutores, entornos de despliegue, scripts de versiones y trabajos programados.
- Salidas de datos, incluidos webhooks, publicación de paquetes, publicación de documentación, copias de seguridad, réplicas, integraciones de incidencias y servicios de notificaciones.
El inventario debe explicar en lenguaje sencillo para qué sirve cada credencial. «Token de CI» no basta. «Lee el código fuente y publica el paquete interno de línea de comandos cuando se sube una etiqueta de versión firmada» indica al siguiente responsable qué debe probar y qué riesgo aparece si algo falla.
Encontrarás entradas que nadie reconoce. No las mantengas activas solo porque el nombre parezca razonable. Pide pruebas: dónde está configurada, qué trabajo la usó recientemente, qué puede hacer y quién será su responsable después de la transferencia. Si la respuesta sigue siendo imprecisa, programa su eliminación. Las credenciales desconocidas suelen darse a conocer después de un incidente.
Las credenciales personales vuelven frágil una transición
Cualquier ruta de producción o publicación que dependa del token personal de un mantenedor debería haberse sustituido ya. El cambio de proyecto simplemente deja al descubierto la debilidad.
Las credenciales personales crean dos problemas. El primero es evidente: el antiguo mantenedor puede conservar el acceso después de dejar el proyecto. El segundo es más frecuente: su cuenta se desactiva o su token caduca y una ruta de publicación deja de funcionar justo cuando más la necesita el equipo receptor. A menudo los equipos piden al antiguo mantenedor que cree otro token. Eso resuelve el fallo inmediato y refuerza la dependencia.
Sustituye las credenciales personales por una identidad de servicio solo cuando el servicio necesite realmente una identidad duradera. Dale el conjunto mínimo de permisos para completar su tarea documentada. Un publicador de versiones puede necesitar permiso para publicar un paquete. No necesita administrar toda la organización ni acceder a todos los repositorios.
No confundas un usuario de máquina con una identidad de servicio bien gestionada. Un usuario de máquina es simplemente una cuenta que usa la automatización. Puede tener una contraseña desconocida, un correo personal de recuperación, pertenencia amplia y ningún responsable. Trátalo como una identidad normal, con un ciclo de vida: créalo de forma deliberada, documenta su propietario, revisa sus pertenencias y elimínalo cuando termine su función.
Aquí es donde falla el consejo popular de «usar una sola cuenta compartida para toda la automatización». Es popular porque pone la automatización en marcha rápidamente y evita el esfuerzo de entender cada integración. También concentra permisos que no tienen relación entre sí en una sola identidad. Cuando un proyecto cambia de equipo, nadie puede revocar su acceso sin poner en riesgo todos los demás proyectos que dependen de esa cuenta.
Separa las identidades por finalidad operativa. Un lector de compilaciones, un publicador de versiones y un responsable de despliegues en producción suelen necesitar privilegios y propietarios distintos. Esa separación hace que la revocación sea menos arriesgada y que la investigación de incidentes sea más clara.
Revisa también los tokens propiedad de usuarios fuera del servicio de Git. Un script de despliegue puede leer un token desde un secreto de CI, pero ese token puede pertenecer a la cuenta de nube de una persona que ya se fue. La ubicación del secreto no te dice qué autoridad tiene. Sigue el token hasta quien lo emitió y revisa allí sus permisos.
Las claves de despliegue y las instalaciones de aplicaciones necesitan revisiones separadas
Las claves de despliegue, las aplicaciones del servicio de Git y las integraciones OAuth proporcionan acceso al repositorio, pero fallan de maneras distintas. Tratarlas como una sola lista conduce a revocaciones descuidadas.
Una clave de despliegue suele ser una clave pública SSH vinculada a un repositorio. Puede conceder acceso de lectura o escritura, según cómo se haya configurado. Su ventaja es que está vinculada a un ámbito estrecho. Su debilidad es la identidad limitada: la clave dice poco sobre el sistema que contiene la parte privada. Si un comentario dice «servidor de compilación» y ese servidor ha cambiado de manos dos veces, el registro del repositorio no te ayudará.
Para cada clave de despliegue, verifica cuatro datos: dónde está la clave privada, qué proceso la usa, si necesita permisos de escritura y quién es responsable del equipo o almacén de secretos que la contiene. Quita los permisos de escritura a las claves que solo descargan código fuente. Elimina cualquier clave que no puedas vincular a un sistema activo y a un responsable identificado.
Una instalación de aplicación plantea el problema contrario. Normalmente tiene una identidad, unos permisos y un historial de eventos más claros, pero puede estar instalada en muchos repositorios. Eliminarla de un proyecto quizá no detenga un servicio relacionado en otro lugar. Revisa los permisos solicitados por la aplicación, el alcance de la instalación, el proceso de rotación de la clave privada, las URL de callback y la cuenta de la organización que puede modificar la instalación.
La documentación de GitHub separa las claves de despliegue de las GitHub Apps por una buena razón. Las claves de despliegue se vinculan a repositorios, mientras que una aplicación recibe permisos mediante una instalación y usa sus propias credenciales. No supongas que eliminar una clave de despliegue afecta al acceso de una aplicación ni que desinstalar una aplicación invalida una clave SSH. Son rutas de autoridad independientes.
Las integraciones OAuth merecen la misma cautela. Pueden actuar en nombre de un usuario en lugar de usar una identidad de aplicación específica. Durante una transferencia, determina si la autorización de la integración depende de un antiguo mantenedor. Si es así, pásala a una identidad de servicio compatible o elimínala. Esperar a que una persona deje la empresa no es un plan de revocación.
Los archivos de workflows pueden conceder más autoridad de la que sugieren sus nombres
Un workflow que parece ejecutar pruebas también puede obtener credenciales, invocar workflows reutilizables, escribir en el repositorio o activar sistemas de despliegue. Lee el archivo antes de decidir que su acceso es inofensivo.
Revisa toda la configuración ejecutable del repositorio, no solo el workflow que realiza las versiones. Esto incluye definiciones de CI, scripts llamados por esas definiciones, configuración de actualización de dependencias, manifiestos de despliegue, código de infraestructura, ajustes de publicación de paquetes y scripts activados por comentarios o pull requests.
Presta atención a los puntos en los que un trabajo cruza un límite de confianza. Algunos ejemplos habituales son un workflow que intercambia un token de identidad por un rol de nube, un trabajo que ejecuta código de un pull request con permiso de escritura en el repositorio o un workflow reutilizable obtenido de otro repositorio. El nombre del workflow puede decir «lint». Sus permisos cuentan la verdad.
La documentación de Actions de GitHub advierte que pull_request_target se ejecuta en el contexto del repositorio base y puede acceder a privilegios que un workflow normal de pull request no tiene. Ese evento no es automáticamente incorrecto. Lo incorrecto es combinarlo con código de un pull request no confiable o con scripts que una persona externa pueda influir. Durante una transición, localiza estos workflows y haz que el equipo receptor los acepte de forma explícita.
Una búsqueda sencilla en el repositorio detecta muchas referencias evidentes. Ejecútala localmente después de obtener todo el historial que necesites revisar:
git grep -nE '(AWS_|AZURE_|GCP_|TOKEN|SECRET|DEPLOY|PUBLISH|ssh |curl |webhook)' -- \\
'.github' '.gitlab-ci.yml' 'scripts' 'infra' 'package.json' 2\u003e/dev/null
Espera una salida con este formato:
.github/workflows/release.yml:42: id-token: write
scripts/publish.sh:18: curl -H "Authorization: Bearer $REGISTRY_TOKEN"
infra/deploy.sh:9: ssh -i "$DEPLOY_KEY" "$DEPLOY_HOST"
El comando no demuestra que exista un secreto ni que un trabajo sea peligroso. Te proporciona una lista para revisar. Sigue cada coincidencia hasta el emisor de la credencial, el alcance de sus permisos y la ruta de fallo. Busca también referencias a workflows que apunten fuera del repositorio, porque el código puede heredar autoridad mediante un workflow reutilizable que este repositorio no controla.
No concedas valores predeterminados amplios para que un workflow heredado funcione. Corrige los permisos declarados por el trabajo y prueba la única acción que debe realizar. Una transición es un buen momento para eliminar permisos que sobrevivieron solo porque nadie quería tocar una canalización antigua.
Revoca en un orden que conserve las pruebas y evite interrupciones
La revocación necesita un orden. Si eliminas todo primero, puedes perder las pruebas necesarias para identificar una dependencia activa. Si esperas a tener una documentación perfecta, los accesos antiguos pueden permanecer indefinidamente.
Congela los cambios discrecionales durante la revisión. El responsable receptor debe saber si aparece una nueva instalación de aplicación, una clave de despliegue o un administrador de la organización antes de completar la línea base. Esto no exige detener el desarrollo normal, pero sí hacer visibles los cambios.
Guarda una exportación o una instantánea registrada de las pertenencias, las listas de colaboradores externos, las claves de despliegue, las instalaciones de aplicaciones, los webhooks, los metadatos de los secretos de CI, las relaciones de confianza de la nube y los eventos de auditoría recientes. No guardes los valores de los secretos. Conserva sus identificadores, alcances, propietarios, contexto de creación si está disponible y la hora de la inspección.
Después aplica este orden:
- Elimina el acceso directo de los antiguos mantenedores y reduce los antiguos administradores de la organización cuando la transferencia lo requiera.
- Desactiva o desinstala las integraciones desconocidas y revoca las claves de despliegue sin un responsable activo.
- Sustituye las credenciales personales conocidas por identidades de servicio y prueba después la ruta exacta de compilación, publicación o despliegue.
- Rota los secretos compartidos, como secretos de webhooks, claves privadas de aplicaciones y credenciales de registros, después de que la sustitución funcione.
- Revisa los eventos de auditoría y los trabajos fallidos durante un periodo adecuado al ritmo de versiones del proyecto y elimina después las excepciones temporales.
Este orden separa la autoridad desconocida de las dependencias conocidas. Una clave de despliegue desconocida no proporciona ninguna función admitida, así que elimínala pronto. Una credencial de publicación conocida necesita una sustituta primero; de lo contrario, convertirás una corrección de seguridad en una interrupción evitable.
Define una vía de emergencia para una sustitución fallida. Debe indicar quién puede restaurar el servicio, cuánto dura la excepción y cómo la registrará el equipo. No restaures el token amplio de un antiguo mantenedor porque la versión se haya retrasado. Crea una credencial temporal y limitada bajo la responsabilidad actual, registra la excepción y elimínala después de solucionar el problema.
El acceso de los agentes debe seguir el mismo límite de propiedad
Los agentes autónomos de programación pueden editar código, llamar a APIs, usar SSH, publicar artefactos y afectar a la infraestructura mediante las herramientas que tienen conectadas. Una transferencia de repositorio que ignore el acceso de los agentes deja un vacío importante en la revisión.
No preguntes solo qué personas pueden ejecutar un agente. Pregunta qué procesos de agente pueden actuar en nombre del repositorio, qué herramientas pueden llamar, qué credenciales usan esas herramientas y si un revisor puede reconstruir después una acción concreta. Un agente que se ejecuta desde el shell de un desarrollador, un trabajo de CI o un ejecutor remoto puede tener una autoridad distinta aunque use el mismo modelo.
Mantén las credenciales de larga duración fuera del prompt y de los archivos de trabajo del agente. Pasar un secreto mediante variables de entorno o la salida de una herramienta lo hace accesible a registros, subprocesos, commits accidentales y al propio contexto del agente. Ocultar un valor en un visor de registros no convierte en seguro el límite entre procesos.
Para los equipos que usan Sallyport, la aplicación para Mac puede guardar las credenciales HTTP y SSH en su bóveda cifrada mientras un agente compatible con MCP solicita una acción mediante su shim local, sin recibir directamente la credencial. Sus diarios de sesión y actividad proporcionan al responsable receptor registros separados de las ejecuciones del agente y de las llamadas individuales, algo más útil que una transcripción cuando hay que revisar una transición.
Durante la transición, revoca las sesiones de agentes vinculadas a estaciones de trabajo o procesos antiguos y haz que el nuevo responsable apruebe las ejecuciones nuevas. Después revisa el uso de cada credencial: una descarga de código de solo lectura y un despliegue en producción no deberían tener la misma expectativa de aprobación. El objetivo no es volver doloroso cada comando. Es hacer visibles las llamadas con mayor impacto para quien responde por sus consecuencias.
El inventario escrito de agentes debe incluir el alcance del repositorio, el lugar de ejecución, los canales de herramientas, el propietario de la credencial, el responsable de la acción y la acción de revocación de emergencia. Si no puedes completar esos campos, el agente tiene un acceso que el proyecto no puede transferir de forma responsable.
Los registros de auditoría deben responder quién cambió el control
Un registro que diga «token utilizado» no basta después de un cambio de propietario. Debes poder responder de quién era el token, qué proceso lo usó, qué hizo, a qué repositorio se dirigió y si la acción estaba permitida bajo la nueva propiedad.
Conserva juntos los eventos de auditoría del repositorio, los registros de ejecución de CI, los registros de auditoría de la nube, los eventos del registro de paquetes y los registros de acciones de los agentes en el archivo de transferencia o en el sistema de incidentes. No tendrán el mismo formato, y no pasa nada. Lo importante es que compartan una referencia temporal y suficientes identificadores para seguir un evento entre sistemas.
Prueba los registros antes de declarar terminada la transferencia. Haz un cambio inocuo mediante cada ruta compatible: un push normal de un desarrollador, un evento de automatización de un pull request, un trabajo programado si existe, una publicación de paquete en un destino que no sea de producción si está disponible y una acción de agente que necesite aprobación. Confirma que el equipo receptor puede encontrar las pruebas sin llamar a los antiguos mantenedores.
Las pruebas contra manipulaciones son útiles, pero no sustituyen la retención ni el control de acceso. Un registro de solo adición te dice si alguien alteró un registro. No sirve si la fuente del evento nunca registró la llamada, si la retención expiró o si ninguna persona actual puede leerlo durante un incidente.
Establece una fecha de revisión después de la transferencia. La primera revisión detecta automatizaciones que solo se ejecutan semanal o mensualmente, y la segunda descubre a las personas que solicitan una excepción porque algo dejó de funcionar. Esas excepciones aportan información. Cada una revela una dependencia que el inventario inicial no detectó.
El equipo receptor debe poder eliminar todas las rutas de acceso
Una transición termina cuando el equipo receptor puede revocar todas las rutas de acceso importantes sin necesitar que el equipo anterior explique un secreto, localice una máquina o apruebe un cambio. Ese estándar es más exigente que el cuadro de diálogo de transferencia del repositorio y evita el fallo que se repite una y otra vez: la propiedad del código cambia sobre el papel mientras el control sigue disperso en otros lugares.
Empieza por el recurso menos atractivo, el inventario de accesos. Coloca un responsable y un procedimiento de revocación junto a cada servicio conectado. Después elimina las entradas que no tengan ninguno de los dos. El trabajo parece tedioso hasta la primera rotación urgente de credenciales. En ese momento, el inventario marca la diferencia entre una reparación contenida y una semana de conjeturas.
FAQ
¿Qué debe ocurrir cuando un repositorio de software cambia de propietario?
Trata la transición como una revisión de accesos, no como un simple cambio administrativo. Confirma quién controla el repositorio y luego inventaría todas las identidades y servicios conectados que puedan leerlo, escribir en él, desplegar, publicar o administrarlo.
¿Eliminar a los mantenedores antiguos revoca todos los accesos al repositorio?
No. Quitar a un usuario de un repositorio suele dejar intactas las claves de despliegue, los usuarios de máquina, las instalaciones de aplicaciones, los tokens de paquetes y las identidades de la nube. Cada uno tiene su propio proceso de revocación.
¿Es seguro transferir un repositorio sin auditar los accesos?
Solo si el nuevo equipo ha revisado antes todas las capacidades. Una transición aparentemente tranquila puede conservar automatizaciones desconocidas, privilegios heredados de la organización y credenciales pertenecientes a personas que ya no tienen responsabilidad operativa.
¿Qué servicios conectados debo revisar después de transferir un repositorio?
Empieza por los colaboradores directos, los equipos, los roles de la organización, las claves de despliegue, los tokens de acceso, las aplicaciones de Git hosting, las claves SSH, las identidades de CI, los roles de la nube, los registros de paquetes y los webhooks. Después añade cualquier sistema que reciba cambios del código fuente o pueda publicar una compilación.
¿Siguen siendo seguras las claves de despliegue después de que un proyecto cambie de equipo?
Puede serlo si la clave pertenece a una cuenta de servicio documentada, con una función limitada y un responsable activo. Una clave SSH cuyo propietario, alcance o propósito se desconozca debe eliminarse en lugar de conservarse por comodidad.
¿Todos los desarrolladores del nuevo equipo deberían ser administradores del repositorio?
No. Un administrador del repositorio normalmente puede cambiar las protecciones de ramas, modificar los workflows, añadir credenciales o conceder acceso a otras personas. Reserva la administración para quienes puedan responder por esas decisiones.
¿Cuál es el mejor orden para rotar las credenciales de un repositorio?
Enumera todas las credenciales, identidades de servicio y destinos de webhook antes de eliminar nada. Revoca primero las credenciales desconocidas o personales, rota después los secretos compartidos y prueba la automatización documentada con la nueva identidad.
¿Los registros de auditoría del repositorio sustituyen a los registros de CI y despliegue?
Necesitas ambos. Los eventos de auditoría del servicio de Git pueden explicar los cambios de permisos y configuración, mientras que los registros de CI explican qué se ejecutó después de un cambio. Consérvalos durante el tiempo suficiente para reconstruir un incidente que haya comenzado antes de la transición.
¿Cómo controlo los agentes de programación con IA durante un cambio de propietario?
Cada acción sensible debe estar vinculada a un responsable humano y a una ejecución concreta del agente. Una puerta de enlace que mantenga las credenciales fuera del agente puede registrar la llamada sin colocar secretos de larga duración en su contexto.
¿Cómo puedo demostrar que el equipo anterior ya no controla un repositorio?
Primero identifica los servicios que todavía pueden actuar sobre el repositorio después de que el equipo anterior se haya marchado. La propiedad debe quedar reflejada en los registros de acceso y credenciales, en la configuración de los workflows y en la lista de contactos para incidentes.