Skip to main content

Eliminación de datos confidenciales de un repositorio

Los datos confidenciales se pueden quitar del historial de un repositorio si puedes coordinarte cuidadosamente con todos los usuarios que los han clonado y estás dispuesto a administrar los efectos secundarios.

Acerca de eliminar datos confidenciales de un repositorio

Al modificar el historial del repositorio mediante herramientas como git filter-repo, es fundamental comprender las implicaciones. La reescritura del historial requiere una coordinación cuidadosa con los colaboradores para ejecutarse correctamente y conlleva una serie de efectos secundarios que se deben administrar.

Es importante tener en cuenta que si la información confidencial que necesitas quitar es un secreto (por ejemplo, contraseña, token o credencial), como suele ser el caso, como primer paso debes revocar o rotar ese secreto. Una vez revocado o rotado el secreto, ya no se puede usar para el acceso y puede que esta acción sea suficiente para resolver el problema. Es posible que no esté justificado dar los pasos adicionales para reescribir el historial y quitar el secreto.

Efectos secundarios de la reescritura del historial

Hay muchos efectos secundarios que se derivan de la reescritura del historial, entre los que se incluyen los siguientes:

  • Alto riesgo de volver a contaminarlo: desafortunadamente, es fácil volver a insertar los datos confidenciales en el repositorio y que el desastre sea mayor. Si un desarrollador asociado tiene un clon antes de la reescritura y, después de la reescritura, solo ejecuta git pull seguido de git push, se devolverán los datos confidenciales. Deben descartar su clon y volverlo a clonar, o bien seguir con atención varios pasos para limpiar primero su clon.
  • Riesgo de perder el trabajo de otros desarrolladores: si otros desarrolladores siguen actualizando ramas que contienen los datos confidenciales mientras intentas limpiar, se te obligará a rehacer la limpieza o a descartar su trabajo.
  • Hashes de confirmación modificados: la reescritura del historial cambiará los hashes de las confirmaciones que introdujeron los datos confidenciales _y_todas las confirmaciones posteriores. Cualquier herramienta o automatización que dependa de los hashes de confirmación que no cambie se interrumpirá o tendrá problemas.
  • Desafíos de protección de rama: si tienes protecciones de rama que impidan inserciones forzadas, esas protecciones tendrán que desactivarse (al menos temporalmente) para que se quiten los datos confidenciales.
  • Vista de diferencias interrumpida para las solicitudes de incorporación de cambios cerradas: la eliminación de los datos confidenciales requerirá quitar las referencias internas usadas para mostrar la vista de diferencias en las solicitudes de incorporación de cambios, por lo que ya no podrás ver estas diferencias. Esto es cierto no solo para la solicitud de incorporación de cambios que introdujo los datos confidenciales, sino para cualquier solicitud de incorporación de cambios que se basa en una versión del historial posterior a la combinación de la solicitud de incorporación de cambios de datos confidenciales (incluso si esas solicitudes de incorporación de cambios posteriores no agregaron ni modificaron ningún archivo con datos confidenciales).
  • Mala interacción con las solicitudes de incorporación de cambios abiertas: los SHA de confirmación modificadas darán lugar a una diferencia de solicitud de cambios diferente y los comentarios sobre la antigua diferencia de solicitud de cambios se pueden invalidar y perder, lo que puede provocar confusión para los autores y revisores. Se recomienda combinar o cerrar todas las solicitudes de incorporación de cambios abiertas antes de quitar archivos del repositorio.
  • Firmas perdidas en confirmaciones y etiquetas: las firmas para confirmaciones o etiquetas dependen de hashes de confirmación; dado que los hash de confirmación se modifican mediante reescrituras del historial, las firmas ya no serían válidas y muchas herramientas de reescritura del historial (incluidas git filter-repo) simplemente quitarán las firmas. De hecho, git filter-repo también quitará las firmas de confirmación y las firmas de etiquetas para las confirmaciones anteriores a la eliminación de datos confidenciales. (Técnicamente, se puede solucionar con la opción --refs de git filter-repo si es necesario, pero deberás tener cuidado de asegurarte de especificar todas las referencias que tengan datos confidenciales en su historial y que incluyan las confirmaciones que introdujeron los datos confidenciales en el intervalo).
  • Dirigir a otros usuarios directamente a los datos confidenciales: Git se diseñó con comprobaciones criptográficas integradas en identificadores de confirmación para que las personas malvadas no pudieran entrar en un servidor y modificar el historial sin que se note. Esto resulta útil desde una perspectiva de seguridad, pero desde una perspectiva de datos confidenciales significa que la supresión de datos confidenciales es un proceso de coordinación muy complejo; además, significa que cuando se modifica el historial, los usuarios astutos con un clon existente observarán la divergencia del historial y pueden usarlo para encontrar rápidamente y fácilmente los datos confidenciales todavía en su clon que quitaste del repositorio central.

Acerca de la exposición de datos confidenciales

La eliminación de datos confidenciales de un repositorio implica cuatro pasos generales:

  • Volver a escribir el repositorio localmente mediante git-filter-repo.
  • Actualizar el repositorio en GitHub mediante el historial reescrito localmente.
  • Coordinarte con compañeros para limpiar otros clones que existan
  • Evitar repeticiones y futuros desbordamientos de datos confidenciales.

Si solo reescribes el historial y fuerzas su inserción, es posible que las confirmaciones con datos confidenciales sigan siendo accesibles en otro lugar:

  • En los clones o bifurcaciones de su repositorio
  • Directamente a través de sus hash SHA-1 en vistas almacenadas en caché en GitHub Enterprise Server
  • A través de las solicitudes de cambios que hacen referencia a ellas

No puede quitar datos confidenciales de los clones de otros usuarios del repositorio; tendrá que enviarles las instrucciones de Asegúrese de que se limpian otras copias: clones de compañeros en el manual de git filter-repo para que lo hagan ellos mismos. Sin embargo, puede quitar permanentemente las vistas almacenadas en caché y las referencias a los datos confidenciales en las solicitudes de incorporación de cambios en lGitHub Enterprise Server poniéndose en contacto con el administrador del sitio.

Si la confirmación que introdujo los datos confidenciales existe en cualquier bifurcación, seguirá siendo accesible allí. Deberá coordinarse con los propietarios de las bifurcaciones, pidiéndoles que eliminen los datos confidenciales o eliminen la bifurcación por completo.

Considera estas limitaciones y dificultades a la hora de tomar la decisión de reescribir el historial de tu repositorio.

Purga de un archivo del historial del repositorio local mediante git-filter-repo

  1. Instala la versión más reciente de la herramienta git filter-repo. Necesitas una versión con la marca --sensitive-data-removal, es decir, al menos la versión 2.47. Puede instalar git filter-repo manualmente o mediante un administrador de paquetes. Por ejemplo, para instalar la herramienta con HomeBrew, use el comando brew install.

    brew install git-filter-repo
    

    Para más información, vea INSTALL.md en el repositorio newren/git-filter-repo.

  2. Clona el repositorio en el equipo local. Consulta Clonar un repositorio.

    git clone https://HOSTNAME/YOUR-USERNAME/YOUR-REPOSITORY
    
  3. Vaya al directorio de trabajo del repositorio.

    cd YOUR-REPOSITORY
    
  4. Ejecuta un comando git filter-repo para limpiar los datos confidenciales.

    Si deseas eliminar un archivo específico de todas las ramas, etiquetas/refs, ejecuta el siguiente comando reemplazando PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA por la ruta de acceso de Git al archivo que deseas quitar, no solo su nombre de archivo (por ejemplo, src/module/phone-numbers.txt):

    git filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
    

    Important

    Si el archivo con datos confidenciales ya existía en alguna otra ruta (porque se movió o cambió de nombre), debes agregar un argumento --path extra para ese archivo, o ejecutar este comando una segunda vez nombrando la ruta alternativa.

    Si deseas reemplazar todo el texto que aparece en ../passwords.txt de cualquier archivo no binario que se encuentre en cualquier parte del historial del repositorio, ejecuta el siguiente comando:

    git filter-repo --sensitive-data-removal --replace-text ../passwords.txt
    
  5. Comprueba que has quitado todo lo que querías del historial del repositorio.

  6. Averigua cuántas solicitudes de incorporación de cambios se verán afectadas negativamente por esta reescritura del historial. Necesitarás esta información a continuación.

    $ grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs
    4
    

    Puedes quitar el -c para ver qué solicitudes de incorporación de cambios se ven afectadas:

    $ grep '^refs/pull/.*/head$' .git/filter-repo/changed-refs
    refs/pull/589/head
    refs/pull/602/head
    refs/pull/604/head
    refs/pull/605/head
    

    Esta salida incluye el número de solicitud de incorporación de cambios entre las barras diagonales segunda y tercera. Si el número de solicitudes de incorporación de cambios afectadas es mayor de lo esperado, puedes descartar este clon sin efectos negativos y rehacer la reescritura o abandonar la eliminación de datos confidenciales. Una vez que pases al paso siguiente, la reescritura se vuelve irreversible.

  7. Una vez que estés satisfecho con el estado del repositorio, inserta los cambios locales para sobrescribir el repositorio en tu instancia de GitHub Enterprise Server. Aunque --force está implícito en --mirror, lo incluimos a continuación como recordatorio de que estás actualizando forzosamente todas las ramas, etiquetas y referencias, y estás descartando los cambios que otros usuarios puedan haber realizado en esas referencias mientras estabas limpiando el repositorio.

    git push --force --mirror origin
    

    Este comando no podrá insertar ninguna referencia a partir de refs/pull/, ya queGitHub Enterprise Server las marca como de solo lectura. Esos errores de inserción se controlarán en la sección siguiente. Si alguna de las otras referencias no se puede insertar, es probable que tengas la protección de rama habilitada para esa rama y tendrás que deshabilitarla temporalmente y volver a hacer la inserción. Repite hasta que los únicos fallos a actualizar sean refs que empiecen por refs/pull/.

Eliminar los datos de GitHub

por completo

Después de usar git filter-repo para quitar los datos confidenciales e insertar los cambios en GitHub Enterprise Server, debes realizar algunos pasos adicionales para eliminar totalmente los datos de GitHub Enterprise Server.

  1. Ponte en contacto con el administrador del sitioy proporciona la siguiente información:

    • El nombre del propietario y del repositorio en cuestión (por ejemplo, YOUR-USERNAME/YOUR-REPOSITORY).
    • El número de solicitudes de incorporación de cambios afectadas, que se encuentra en el paso anterior. Esto lo usa el soporte técnico para comprobar que comprendes cuánto te verás afectado.
    • Las primeras confirmaciones modificadas notificadas por git filter-repo (busca NOTE: First Changed Commit(s) en tu salida).
    • Si NOTE: There were LFS Objects Orphaned by this rewrite aparece en la salida del repositorio git-filter-repo (justo después de la primera confirmación modificada), menciona que tenía objetos LFS huérfanos y carga también el archivo con nombre en el vale.

    Si has limpiado correctamente todas las referencias que no sean solicitudes de incorporación de cambios y ninguna bifurcación tiene referencias a los datos confidenciales, el soporte técnico hará lo siguiente:

    • Desreferencia o elimina las solicitudes de incorporación de cambios afectadas en GitHub Enterprise Server
    • Ejecuta una recolección de elementos no utilizados en el servidor para eliminar los datos confidenciales del almacenamiento.
    • Quita las vistas almacenadas en caché.
    • Si los objetos LFS están implicados, elimina o purga los objetos LFS huérfanos.

    Para obtener más información sobre cómo los administradores del sitio pueden quitar objetos git inaccesibles, consulta Utilidades de la ea de comandos. Para obtener más información sobre cómo los administradores del sitio pueden identificar confirmaciones accesibles, consulte "Identificación de confirmaciones accesibles".

  2. Los colaboradores deben fusionar mediante cambio de base, no combinar, todas las ramas que hayan creado fuera del historial de repositorios antiguo (contaminado). Una confirmación de fusión podría volver a introducir algo o todo el historial contaminado sobre el que acabas de tomarte el trabajo de purgar. Es posible que también necesiten realizar pasos adicionales; consulta Asegurarse de que se limpian otras copias: clones de compañeros en el manual de git filter-repo.

Identificación de confirmaciones accesibles

Para eliminar completamente datos no deseados o confidenciales de un repositorio, la confirmación que introdujo primero los datos no debe tener ninguna referencia en ramas, etiquetas, solicitudes de cambios y bifurcaciones. Una sola referencia en cualquier lugar impedirá que la recolección de elementos no utilizados pueda purgar completamente los datos.

Puede comprobar si hay referencias existentes mediante los siguientes comandos cuando se conecta al dispositivo a través de SSH. Necesitará el SHA de la confirmación que introdujo originalmente los datos confidenciales.

ghe-repo OWNER/REPOSITORY -c 'git ref-contains COMMIT_SHA_NUMBER'
ghe-repo OWNER/REPOSITORY -c 'cd ../network.git && git ref-contains COMMIT_SHA_NUMBER'

Si alguno de esos comandos devuelve resultados, deberá eliminar esas referencias para que la confirmación se pueda recopilar correctamente. El segundo comando identificará las referencias que existen en bifurcaciones del repositorio (si el repositorio no tiene bifurcaciones, puede omitir su ejecución).

  • Los resultados que comienzan por refs/heads/ o refs/tags/ indican ramas y etiquetas, respectivamente, que todavía contienen referencias a la confirmación infractora, lo que sugiere que la confirmación no se ha eliminado por completo del repositorio modificado o que no se ha insertado a la fuerza.
  • Los resultados que comienzan por refs/pull/ o refs/__gh__/pull indican solicitudes de cambios que hacen referencia a la confirmación infractora. Estas solicitudes de cambios deben eliminarse para permitir que la recolección de elementos no utilizados recopile la confirmación. Una solicitud de cambios se puede eliminar en el panel de administración del sitio en https://HOSTNAME/stafftools/repositories/OWNER/REPOSITORY/PULL_REQUESTS/<PULL-REQUEST-NUMBER>; <PULL-REQUEST-NUMBER> se debe reemplazar por el número de solicitud de cambios.

Si las referencias se encuentran en cualquier bifurcación, los resultados tendrán un aspecto similar, pero comenzarán por refs/remotes/NWO/. Para identificar la bifurcación por nombre, puede ejecutar el siguiente comando.

ghe-nwo NWO

Los datos confidenciales se pueden quitar de las bifurcaciones de un repositorio; para ello, ve a un clon de uno, captura del repositorio limpiado y cambia de base todas las ramas y etiquetas que contienen los datos confidenciales sobre la rama o etiqueta pertinentes del repositorio limpiado. Como alternativa, las bifurcaciones se pueden eliminar por completo y, si es necesario, el repositorio se puede volver a bifurcar una vez completada la limpieza del repositorio raíz.

Una vez que haya eliminado las referencias de la confirmación, vuelva a ejecutar los comandos para comprobarlo.

Si no hay resultados de ninguno de los comandos ref-contains, puede ejecutar la recolección de elementos no utilizados con la marca --prune para eliminar las confirmaciones sin referencia ejecutando el comando siguiente.

ghe-repo-gc -v --prune OWNER/REPOSITORY

Una vez que la recolección de elementos no utilizados haya eliminado correctamente la confirmación, vaya al panel de administración del sitio del repositorio en https://HOSTNAME/stafftools/repositories/OWNER/REPOSITORY, seleccione Red y, a continuación, haga clic en Invalidar caché de Git para eliminar los datos almacenados en caché.

Evitar confirmaciones accidentales en el futuro

Impedir que los colaboradores realicen confirmaciones accidentales puede ayudarte a evitar que se exponga información confidencial. Para obtener más información, consulta Procedimientos recomendados para evitar la pérdida de datos en la organización.

Hay algunas cosas que puedes hacer para evitar la confirmación o la inserción de cosas que no deben compartirse:

  • Si es probable que los datos confidenciales se encuentren en un archivo al que Git no debe realizar el seguimiento, agrega ese nombre de archivo a .gitignore (y asegúrate de confirmar e insertar ese cambio en .gitignore para que otros desarrolladores estén protegidos).
  • Evita secretos codificados de forma rígida en el código. Usa variables de entorno o servicios de administración de secretos como Azure Key Vault, AWS Secrets Manager o HashiCorp Vault para administrar e insertar secretos en tiempo de ejecución.
  • Crea un enlace de confirmación previa para comprobar si hay datos confidenciales antes de confirmarlos o insertarlos en cualquier lugar, o bien usa una herramienta conocida en un enlace de confirmación previa, como git-secrets o githunter. (Asegúrate de pedir a cada colaborador que configure el enlace de confirmación previa que has elegido).
  • Use un programa visual como GitHub Desktop o gitk para confirmar los cambios. Los programas visuales suelen hacer que sea más sencillo ver exactamente qué archivos se agregarán, eliminarán y modificarán con cada confirmación.
  • Evite los comandos generales git add . y git commit -a en la línea de comandos; en su lugar use git add filename y git rm filename para agregar al "stage" los archivos de manera individual.
  • Use git add --interactive para revisar y agregar al "stage" los cambios en cada archivo.
  • Use git diff --cached a fin de revisar los cambios que ha agregado al "stage" para la confirmación. Esta es la diferencia exacta que producirá git commit siempre que no use la marca -a.
  • Habilita la protección de inserción para que el repositorio detecte e impida que las inserciones que contienen secretos codificados de forma rígida se confirmen en el código base. Para más información, consulta Acerca de la protección de inserción.

Información adicional