Anúncios incomodam? Ir Sem anúncios Hoje

Arquivos .env — 6 Erros que Colocam Seus Segredos no GitHub

Atualizado em

A maioria dos vazamentos de .env não vem de hackers — vêm de desenvolvedores que enviaram arquivos antes de o .gitignore ser configurado, enviaram .env.example com valores em produção ou permitiram que um framework empacote segredos de servidor em JavaScript do cliente. Aqui estão os 6 erros que realmente acontecem.

Arquivos .env — 6 Erros que Colocam Seus Segredos no GitHub 1
ANUNCIADO Remover?

O relatório 'Estado do Espalhamento de Segredos' de 2023 do GitGuardian descobriu mais de 12 milhões de segredos enviados para repositórios públicos do GitHub. A maioria não foi roubada — foram enviadas por desenvolvedores que realmente acreditavam terem tratado corretamente. Essas são as padrões responsáveis.

1. Adicionar .gitignore após o primeiro commit

.gitignore de serem adicionados. Se um arquivo já está no seu histórico do git, adicioná-lo a não faz nada. O git continua rastreando e ainda assim cometerá alterações nele. arquivos de não serem agendados. Uma vez que um arquivo é rastreado — mesmo que brevemente — ele está na história do git. Se você criou .env, executou git add . && git commit, então adicionou .env para .gitignore depois, o arquivo ainda está em todos os commits que antecederam essa mudança.

Verifique se já está na história:

git log --all -- .env

Se isso retornar commits, os segredos estão na história. Rotacione as credenciais primeiro. Em seguida, remova o arquivo da história usando git-filter-repo (a substituição recomendada para git filter-branch):

pip install git-filter-repo
git filter-repo --path .env --invert-paths

Força-push para todos os remotos e notifique os colegas para reclonar. Os commits existem em todos os clones feitos antes da limpeza — incluindo qualquer sistema CI automatizado que checkout o repositório.

2. Copiar .env para .env.example sem limpar os valores

O fluxo padrão: criar .env com valores reais, depois copiar para .env.example para mostrar aos colegas quais chaves o projeto precisa. A cópia é onde as coisas vão errado.

cp .env .env.example cópia tudo — chaves e valores. E .env.example é suposto ser commitado. Isso é o ponto inteiro. Valores reais em .env.example entram no repositório intencionalmente.

❌ O que acaba no git:

DATABASE_URL=postgres://admin:supersecretpassword@prod-db.example.com/appdb
STRIPE_SECRET_KEY=sk_live_51AbcDefGhiJklMnopQrstUvwx...
JWT_SECRET=my-actual-production-jwt-secret

✅ O que .env.example deveria parecer:

DATABASE_URL=postgres://user:password@localhost:5432/appdb
STRIPE_SECRET_KEY=sk_live_YOUR_KEY_HERE
JWT_SECRET=generate-a-random-secret-min-32-chars

Criar .env.example com valores de placeholder primeiro, comita, depois copie para .env e preencha as credenciais reais — não no sentido inverso.

3. Registrar process.env em manipuladores de erros

Este começa como uma 'verificação rápida' durante um incidente e nunca é removido. Ou ele vive em middleware genérico que parece inofensivo.

// Classic debug line that makes it to production
console.log('Starting with config:', process.env);

// Generic error handler that dumps everything
app.use((err, req, res, next) => {
  logger.error({ config: process.env, error: err.message });
  res.status(500).json({ error: 'Internal server error' });
});

process.env em tempo de execução contém todas as variáveis carregadas pelo dotenv, mais variáveis do sistema. Passar o objeto completo para um logger significa que ele chega ao seu agregador de logs, ao seu serviço de rastreamento de erros (Sentry, Datadog, Rollbar) e potencialmente em e-mails ou webhooks de notificação de erros. Muitos desses serviços encaminham para armazenamento de terceiros com seus próprios controles de acesso.

Registre apenas os valores específicos que precisar para diagnóstico:

logger.error({
  nodeEnv: process.env.NODE_ENV,
  appVersion: process.env.APP_VERSION,
  error: err.message,
  stack: err.stack
});

4. Incluir segredos em camadas de imagem Docker

Dois padrões que incorporam permanentemente segredos na história da imagem Docker:

# Pattern 1: COPY bakes the entire .env into a layer
COPY .env .

# Pattern 2: ARG/ENV burns values into build metadata
ARG DATABASE_URL
ENV DATABASE_URL=$DATABASE_URL

Mesmo que você exclua o arquivo em uma camada posterior (RUN rm .env), o valor ainda é legível na história da imagem. Qualquer pessoa com acesso de pull à imagem pode executar:

docker history --no-trunc your-image:tag

e recuperar os valores do ARG usados no momento da construção. Os segredos do Docker BuildKit são a ferramenta correta — eles montam segredos durante a construção sem escrevê-los em nenhuma camada:

# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=db_url     DATABASE_URL=$(cat /run/secrets/db_url) ./setup.sh

Para configuração em tempo de execução, injete variáveis de ambiente no início do container via docker run -e ou environment: no Docker Compose referenciando variáveis do host — nunca valores hardcoded, nunca COPY‘arquivos de segredo.

5. Usar placeholders fracos que são enviados para produção

JWT_SECRET=secret, SESSION_SECRET=keyboard cat, APP_KEY=changeme, ENCRYPTION_KEY=1234567890abcdef. Esses começam como placeholders de desenvolvimento e às vezes nunca são substituídos. Atacantes que brutamente forçam assinaturas JWT ativamente tentam essas strings — elas estão em listas de palavras especificamente porque aparecem em buscas no GitHub.

Um JWT assinado com HS256 e um segredo fraco pode ser quebrado offline com ferramentas como c-jwt-cracker. Um token válido interceptado é suficiente para forçar o segredo e gerar tokens arbitrários.

Segredos corretos devem ser criptograficamente aleatórios, com no mínimo 32 bytes. Gerá-los antes que você os precise — o Gerador de Segredos de Ambiente na IO Tools produzirá valores aleatórios corretos para segredos comuns (.env, chaves JWT, segredos de sessão, chaves API) sem exigir nenhuma configuração. Defina-os desde o início; não use um placeholder e planeje para 'corrigir antes da produção'.

6. Convenções de variáveis de ambiente de framework que expõem segredos ao cliente

Vários frameworks populares usam prefixos de nomes de variáveis para determinar visibilidade entre cliente e servidor. Fazer isso errado envia segredos no bundle JavaScript para todos os navegadores que carregam seu aplicativo — em texto claro.

  • Next.js: Qualquer diretório chamado NEXT_PUBLIC_-variáveis prefixadas são incluídas no lado do cliente. Mas segredos do lado do servidor vazam quando passados por getServerSideProps props — qualquer valor retornado em props é serializado na página HTML e é legível na fonte.
  • Vite: Variáveis prefixadas VITE_ são incluídas no JavaScript do cliente. Usar VITE_DATABASE_URL "para conveniência" é um erro que os desenvolvedores realmente cometem.
  • Create React App: Todos REACT_APP_ variáveis acabam no bundle do cliente, sem exceção. Não há runtime do lado do servidor do CRA — tudo que carrega vai para o navegador.

Verifique após a build ao procurar valores conhecidos de segredos no diretório de saída:

grep -r "sk_live_" ./dist
grep -r "sk_live_" ./.next/static

Se qualquer correspondência for retornada, esses segredos estão em todas as abas do navegador. Rotacione-os imediatamente e audite o que mais foi incluído.

Um hábito valioso para construir desde o início

Antes de criar qualquer arquivo que contenha segredos, configure .gitignore primeiro — não como uma consideração pós-fato. O primeiro commit de qualquer novo repositório deve ser .gitignore e .env.example com valores de placeholder. O .gitignore Generator gerará um arquivo de ignorar completo, específico do framework, em menos de um minuto.

Os seis erros acima são todos preveníveis antes que qualquer código seja escrito. A rotação é a única solução quando segredos são expostos — e isso significa rotacionar em todos os lugares: o provedor de serviço, todos os ambientes que tinham uma cópia e todos os sistemas que podem ter armazenado o valor em logs.

Quer eliminar anúncios? Fique sem anúncios hoje mesmo

Instale nossas extensões

Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida

Ao Extensão do Chrome Ao Extensão de Borda Ao Extensão Firefox Ao Extensão Opera

O placar chegou!

Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!

ANUNCIADO Remover?
ANUNCIADO Remover?
ANUNCIADO Remover?

Notícias com destaques técnicos

Envolver-se

Ajude-nos a continuar fornecendo ferramentas gratuitas valiosas

Compre-me um café
ANUNCIADO Remover?