Skip to main content

Remover dados confidenciais de um repositório

Dados confidenciais poderão ser removidos do histórico de um repositório se você puder coordenar cuidadosamente com todos que o clonaram e estiver disposto a gerenciar os efeitos colaterais.

Sobre a remoção de dados confidenciais de um repositório

Ao alterar o histórico do repositório usando ferramentas como , é fundamental entender as implicações. É necessário coordenar cuidadosamente com os colaboradores o processo de reescrever o histórico para que ele seja executado com êxito, e há uma série de efeitos colaterais que devem ser gerenciados.

É importante observar que, se os dados confidenciais que você precisa remover forem um segredo (por exemplo, senha/token/credencial), como costuma ser o caso, a primeira etapa será revogar e/ou alterar esse segredo. Após o segredo ser revogado ou alternado, ele não poderá mais ser usado para acesso, e isso pode ser suficiente para resolver o seu problema. Pode não ser necessário realizar as etapas extras de reescrever o histórico e remover o segredo.

Efeitos colaterais de reescrever o histórico

Reescrever o histórico traz alguns efeitos colaterais, que incluem:

  • Alto risco de recontaminação: infelizmente, é fácil voltar a efetuar push dos dados confidenciais para o repositório e fazer uma bagunça ainda maior. Se um colega desenvolvedor tiver um clone anterior à reescrita e, depois da reescrita, executar seguido de , os dados confidenciais retornarão. Eles precisam descartar o clone e clonar novamente ou seguir cuidadosamente várias etapas para limpar o clone deles primeiro.
  • Risco de perder o trabalho de outros desenvolvedores: se outros desenvolvedores continuarem atualizando branches que contêm os dados confidenciais enquanto você estiver tentando limpá-los, você precisará refazer a limpeza ou descartar o trabalho deles.
  • Hashes de commit alterados: reescrever o histórico vai alterar os hashes dos commits que introduziram os dados confidenciais e de todos os commits que vieram depois. Qualquer ferramenta ou automação que exigir que hashes de commit não sejam alterados será interrompida ou terá problemas.
  • Desafios de proteção de ramificação: se você tiver proteções de ramificação que impedem pushes forçados, elas precisarão ser desativadas (pelo menos temporariamente) para que os dados confidenciais sejam removidos.
  • Exibição de comparação interrompida para solicitações de pull fechadas: a remoção dos dados confidenciais exigirá a remoção das referências internas usadas para mostrar a exibição de comparação em solicitações de pull. Portanto, você não poderá mais ver essas comparações. Isso vale não apenas para a PR que introduziu os dados confidenciais, mas para qualquer PR baseada em uma versão do histórico posterior à mesclagem da PR com dados confidenciais (mesmo que essas PRs posteriores não tenham adicionado nem modificado nenhum arquivo com dados confidenciais).
  • Interação insatisfatória com solicitações de pull abertas: os SHAs de commits alterados resultarão em uma comparação de PR diferente, e os comentários sobre a comparação de PR antiga poderão ser invalidados e perdidos, o que poderá causar confusão para autores e revisores. Recomendamos mesclar ou fechar todas as solicitações de pull abertas antes de remover arquivos do repositório.
  • Perda de assinaturas em commits e tags: as assinaturas de commits ou tags dependem dos hashes de commit. Como esses hashes são modificados por reescritas de histórico, as assinaturas deixarão de ser válidas, e muitas ferramentas de reescrita de histórico (incluindo o ) simplesmente as removerão. Na verdade, também serão removidas assinaturas de commit e de tag para commits anteriores à remoção dos dados confidenciais. (Tecnicamente, é possível contornar isso com a opção apropriada, se necessário, mas nesse caso você precisará especificar todas as referências que contêm dados confidenciais em seu histórico e que incluem os commits que introduziram esses dados confidenciais no seu intervalo).
  • Direcionamento de outras pessoas para os dados confidenciais: o Git foi criado com verificações de criptografia incorporadas nos identificadores de commit, de modo que pessoas mal-intencionadas não pudessem invadir um servidor e modificar o histórico sem serem detectadas. Isso é útil da perspectiva de segurança, mas da perspectiva de dados confidenciais significa que expurgar esses dados é um processo de coordenação muito elaborado. Significa ainda que, quando você modifica o histórico, usuários atentos com um clone existente observarão a divergência de históricos e poderão usar isso para localizar com rapidez e facilidade os dados confidenciais que ainda estão no clone que você removeu do repositório central.

Sobre a exposição de dados confidenciais

A remoção de dados confidenciais de um repositório envolve quatro etapas gerais:

  • Reescrever o repositório localmente usando git-filter-repo
  • Atualize o repositório em GitHub usando seu histórico reescrito localmente
  • Coordenar com colegas para limpar outros clones existentes
  • Impedir repetições e evitar futuros vazamentos de dados confidenciais

Se você apenas reescrever o histórico e forçar o push, commits com dados confidenciais ainda poderão ser acessados em outros lugares:

  • Em quaisquer clones ou forks do seu repositório
  • Diretamente por meio de seus hashes SHA-1 em visualizações em cache no GitHub
  • Por meio de quaisquer solicitações de pull que façam referências a eles

Não é possível remover dados confidenciais de clones de outros usuários do seu repositório; Você precisará enviar a eles as instruções da seção "Garantir que outras cópias sejam limpas: clones de colegas" no manual para que façam isso por conta própria. No entanto, você pode remover permanentemente as exibições armazenadas em cache e as referências aos dados confidenciais em pull requests no GitHub entrando em contato com o conosco por meio do Portal de suporte do GitHub.

Importante

O Suporte do GitHub não remove dados não confidenciais e só ajuda na remoção de dados confidenciais nos casos em que determinarmos que o risco não pode ser mitigado pela rotação das credenciais afetadas.

Se a confirmação que introduziu os dados confidenciais existir em qualquer fork, ela continuará acessível lá. Você precisará coordenar com os proprietários dos forks, pedindo-lhes para remover os dados confidenciais ou excluir o fork completamente. GitHub não é capaz de fornecer informações de contato para esses proprietários.

Considere essas limitações e desafios ao tomar a decisão de reescrever a história do repositório.

Como limpar um arquivo do histórico do repositório local usando o git-filter-repo

  1. Instale a última versão da ferramenta . É preciso ter uma versão com o sinalizador , o que significa, no mínimo, a versão 2.47. Você pode instalar o manualmente ou usando um gerenciador de pacotes. Por exemplo, para instalar a ferramenta com HomeBrew, use o comando .

    brew install git-filter-repo
    

    Para obter mais informações, confira INSTALL.md no repositório .

  2. Clone o repositório no computador local. Consulte AUTOTITLE

    git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
    
  3. Navegue até o diretório de trabalho do repositório.

    cd YOUR-REPOSITORY
    
  4. Execute um comando para limpar os dados confidenciais.

    Se quiser excluir um arquivo específico de todos os branches/tags/referências, execute o seguinte comando substituindo pelo caminho do Git para o arquivo que você deseja remover, não apenas o nome de arquivo (por exemplo, ):

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

    Importante

    Se o arquivo com os dados confidenciais existia em qualquer outro caminho (devido a ter sido movido ou renomeado), adicione um argumento extra para esse arquivo ou execute esse comando uma segunda vez nomeando o caminho alternativo.

    Se você quiser substituir todo o texto listado em em todos os arquivos não binários encontrados em qualquer lugar do histórico do repositório, execute o seguinte comando:

    git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt
    
  5. Verifique se você removeu tudo o que queria do histórico do repositório.

  6. Descubra quantas pull requests serão afetadas negativamente por essa reescrita de histórico. Você precisará dessas informações abaixo.

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

    Remova o para ver quais solicitações de pull são afetadas:

    $ 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
    

    Essa saída inclui o número da solicitação de pull entre a segunda e a terceira barra. Se o número de solicitações de pull afetadas for maior do que o esperado, descarte esse clone sem efeitos nocivos e refaça a reescrita ou suspenda a remoção dos dados confidenciais. Depois que você passar para a próxima etapa, a reescrita se tornará irreversível.

  7. Quando estiver satisfeito com o estado do repositório, faça um push forçado das alterações locais para sobrescrever seu repositório em GitHub.com. Embora esteja implícito por , nós o incluímos abaixo como um lembrete de que você está atualizando forçadamente todas as ramificações, tags e referências e descartando as alterações que outras pessoas possam ter feito a essas referências durante a limpeza do repositório.

    git push --force --mirror origin
    

    Esse comando não efetuará push de nenhuma referência que começa com , pois o GitHub marca as referências como somente leitura. Essas falhas de push serão abordadas na próxima seção. Em caso de falha no push de outras referências, é provável que você tenha a proteção de ramificação ativada para a ramificação em questão. Além disso, será necessário desativá-la temporariamente e refazer o push. Repita esta etapa até que as únicas falhas de atualização sejam as refs que começam com .

Remover completamente os dados do GitHub

Depois de usar para remover os dados confidenciais e efetuar push das alterações para o GitHub, você precisa executar mais algumas etapas para remover por completo os dados do GitHub.

  1. Entre em contato com o conosco por meio do Portal de suporte do GitHub e informe o seguinte:

    • O nome do proprietário e do repositório em questão (por exemplo, YOUR-USERNAME/YOUR-REPOSITORY).
    • O número de pull requests afetadas, encontradas na etapa anterior. Isso é usado pelo Suporte para verificar se você está ciente do quanto será afetado.
    • Os Primeiros Commits Alterados relatados pelo (procure na saída).
    • Se aparecer na saída do git-filter-repo (logo após o Primeiro Commit Alterado), mencione que você tinha objetos LFS órfãos e carregue o arquivo nomeado no tíquete também.

    Se você tiver limpado com êxito todas as referências que não sejam PRs e nenhum fork tiver referência aos dados confidenciais, o Suporte vai:

    • Desreferenciar ou excluir as PRs afetadas no GitHub.

    • Realizar uma coleta de lixo no servidor para remover definitivamente os dados confidenciais do armazenamento.

    • Remover as exibições armazenadas em cache.

    • Se objetos LFS estiverem envolvidos, exclua e/ou limpe os objetos LFS órfãos.

  2. Os colaboradores precisam trocar a base, não fazer a mesclagem, das ramificações que criaram fora do histórico do repositório antigo (afetado). Um commit de merge poderia reintroduzir o histórico antigo completo (ou parte dele) que você acabou de se dar ao trabalho de corrigir. Talvez eles também precisem realizar etapas adicionais; consulte "Certifique-se de que as outras cópias foram removidas: clones de colegas", conforme indicado no manual.

Evitar commits acidentais no futuro

Impedir que colaboradores façam commits acidentais pode ajudar a evitar que informações confidenciais sejam expostas. Para saber mais, confira AUTOTITLE.

Você pode realizar algumas ações para evitar commits ou pushes de itens que não devem ser compartilhados:

  • Se houver probabilidades de os dados confidenciais serem encontrados em um arquivo que não deve ser rastreado pelo git, adicione esse nome de arquivo a (e faça commit e push dessa alteração para para que outros desenvolvedores sejam protegidos).
  • Evite embutir segredos em código. Use variáveis de ambiente ou serviços de gerenciamento de segredos como Azure Key Vault, AWS Secrets Manager ou HashiCorp Vault para gerenciar e injetar segredos em runtime.
  • Crie um gancho de pré-commit para verificar dados confidenciais antes de serem commitados ou enviados a qualquer repositório, ou utilize uma ferramenta conhecida em um gancho de pré-commit, como git-secrets ou gitleaks. (Peça a cada colaborador que configure o gancho pré-commit que você escolher.)
  • Use um programa visual como GitHub Desktop ou gitk para realizar o commit das alterações. Nos programas visuais, geralmente é mais fácil ver exatamente quais arquivos serão adicionados, excluídos e modificados em cada commit.
  • Evite os comandos catch-all e na linha de comando: use e para preparar os arquivos individualmente.
  • Use para revisar e preparar alterações individualmente em cada arquivo.
  • Use para revisar as alterações que você preparou para commit. Essa é a comparação exata que produzirá, desde que você não use o sinalizador .
  • Habilite a proteção por push para seu repositório para detectar e impedir que envios por push contendo segredos codificados sejam confirmados na sua base de código. Para saber mais, confira AUTOTITLE.

Leitura adicional

  • Página de manual do , especialmente a subseção “Remoção de dados confidenciais” da seção “DISCUSSÃO”.
  • Pro Git: Ferramentas do Git – Reescrita do histórico
  • AUTOTITLE