"Segurança no Replit" são duas coisas que convém separar. A primeira é o Repl e o seu deploy: onde vivem os segredos, quem vê os teus ficheiros, que URL é público e que porta está exposta. A segunda é o código que o Replit Agent gera, normalmente um servidor Express com React e uma base de dados Postgres, que traz as falhas clássicas de um backend escrito à pressa. Este guia cobre as duas, com um bloco para o ficheiro que o Agent lê em cada pedido, um prompt de revisão antes do deploy e as verificações de fora.
Parte 1: proteger o teu Repl e o teu deploy
Segredos: o separador Secrets, não o código
O Replit tem um gestor de segredos que guarda as variáveis cifradas e as expõe ao processo como variáveis de ambiente, sem aparecerem em nenhum ficheiro. É o único sítio correto para chaves de API, a string de ligação da base de dados e o segredo de sessão. O erro habitual é o Agent, ou tu com pressa, escrevê-las num .env, num config.json ou diretamente no código. Esses ficheiros fazem parte do Repl: veem-se num Repl público, copiam-se ao fazer fork e são publicados no deploy.
Repls públicos e o URL de desenvolvimento
Um Repl público mostra todos os seus ficheiros a qualquer pessoa, incluindo os que esqueceste: cópias de segurança, um .env antigo, exportações de dados. Antes de o tornares público, revê a árvore completa. E enquanto o Repl está a correr, o URL de desenvolvimento .replit.dev responde a quem o tiver; não é um ambiente privado, é um servidor na internet com os teus dados de teste.
Deploys
O deploy publica a app num subdomínio .replit.app ou no teu domínio, com TLS automático. As variáveis de ambiente do deploy configuram-se à parte das de desenvolvimento, por isso confirma que as de produção não apontam para a base de dados de testes. Só a porta que declaras fica exposta, mas tudo o que essa porta serve é público: rotas de API, ficheiros estáticos e o que o servidor devolver por engano. O Replit não acrescenta cabeçalhos de segurança; é o teu servidor que os põe.
Base de dados e autenticação integradas
A base de dados Postgres integrada entrega a sua string de ligação como segredo; nunca a copies para um ficheiro. Se usas Replit Auth, a sessão é gerida pelo Replit e o teu código recebe o utilizador já identificado, mas cada rota continua a ter de verificar que há sessão e que esse utilizador pode fazer o que pede.
Parte 2: as falhas que o Agent mete no teu código
- Segredos em ficheiros. A chave da OpenAI ou a string do Postgres no
.env, numa constante ou numconfig.jsonservido como estático. - Rotas de API sem autenticação. O painel verifica a sessão no React;
/api/usersresponde a qualquer pessoa. - Pastas estáticas demasiado amplas.
express.statica apontar para a raiz do projeto servepackage.json,.replit, o código do servidor e qualquer ficheiro esquecido. E semindex.html, alguns servidores listam o diretório. - Rotas de depuração e seed.
/api/debug,/api/seed,/api/resetcriadas para testar e publicadas. - CORS aberto com credenciais.
cors()sem opções mais cookies de sessão: qualquer site age em nome dos teus utilizadores. - Consultas SQL por concatenação. Uma string construída com o que chega do formulário em vez de parâmetros.
- Uploads de ficheiros para disco servidos tal e qual. Qualquer utilizador carrega um ficheiro e qualquer visitante o descarrega pelo nome.
- Sem limite de pedidos nem cabeçalhos. Um endpoint que chama um modelo pago sem teto, e nenhum cabeçalho de segurança.
Um bloco para o Agent aplicar sempre
O Replit Agent lê o ficheiro replit.md do teu projeto como contexto permanente. Acrescenta esta secção:
## Regras de segurança
- As chaves, a string da base de dados e o segredo de sessão leem-se de process.env e vivem no separador Secrets. Nunca em .env, config.json nem no código.
- Toda a rota de API que leia ou escreva dados verifica a sessão e as permissões do utilizador no servidor. As verificações no React não contam.
- express.static só serve a pasta de build do frontend ou public/, nunca a raiz do projeto.
- Sem rotas de depuração, seed ou reset em produção.
- CORS com uma lista explícita de origens; nunca o wildcard com credenciais.
- Todas as consultas SQL usam parâmetros. Toda a entrada de formulário é validada no servidor.
- Os ficheiros carregados guardam-se fora da pasta pública e só se servem depois de verificar permissões.
- Cabeçalhos de segurança com helmet e limite de pedidos nas rotas com custo.
E os cabeçalhos em Express, em duas linhas:
import helmet from 'helmet';
app.use(helmet());
app.use(helmet.hsts({ maxAge: 63072000, includeSubDomains: true, preload: true }));
Um prompt de revisão antes do deploy
Revê a segurança deste projeto e não mudes nada ainda. Responde com uma lista:
1. Chaves, strings de ligação ou segredos escritos em ficheiros ou no código, com ficheiro e linha.
2. Rotas de API que leiam ou escrevam dados sem verificar a sessão, e rotas de depuração, seed ou reset.
3. Pastas servidas como estáticas e que ficheiros expõem.
4. Configuração de CORS e de cookies de sessão.
5. Consultas SQL construídas por concatenação e entradas sem validar.
6. Onde se guardam os ficheiros carregados e como se servem.
7. Se existem cabeçalhos de segurança e limite de pedidos.
Para cada ponto, propõe a alteração exata e espera pela minha confirmação.
Verifica o resultado de fora
curl -sI https://oteudominio.com | grep -iE "strict-transport|x-frame|x-content-type|content-security"
for p in .env .replit package.json config.json .git/config server.js uploads/; do printf "%-14s " "$p"; curl -s -o /dev/null -w "%{http_code}\n" "https://oteudominio.com/$p"; done
curl -s -o /dev/null -w "%{http_code}\n" https://oteudominio.com/api/users
O esperado: cabeçalhos presentes, 404 em toda a lista de ficheiros e um 401 ou 403 na rota de API sem sessão. Um 200 em package.json ou .replit significa que estás a servir a raiz do projeto. O Scanaris faz estas verificações e cerca de quarenta mais em 30 segundos: procura ficheiros expostos e listagens de diretório, endpoints que respondam sem sessão, segredos no JavaScript, cabeçalhos, CORS, cookies e TLS, e dá-te um fix prompt por cada falha para colar no chat do Agent. E pode voltar a analisar todos os dias, porque uma regeneração pode trazer de volta uma falha que já tinhas corrigido.
Perguntas frequentes
Os segredos do separador Secrets veem-se num Repl público?
Não, os segredos não são mostrados nem copiados ao fazer fork. O que se vê é tudo o resto: ficheiros, código e qualquer chave que esteja escrita neles em vez de em Secrets.
O URL de desenvolvimento é privado?
Não. Enquanto o Repl corre, responde a qualquer pessoa que tenha o link. Não o uses com dados reais nem o partilhes a pensar que só tu o vês.
O Replit põe cabeçalhos de segurança nos deploys?
Não. Dá TLS e o domínio, mas os cabeçalhos são enviados pelo teu servidor. Com Express, o helmet acrescenta-os em duas linhas; com outras frameworks, o seu equivalente.