Regras de Segurança para Mobile
Manuseio de segredos, armazenamento seguro, segurança de transporte e decisões de fixação de certificados para aplicativos Expo no SDK 57. Clientes móveis são ambientes não confiáveis - assuma que atacantes podem extrair valores empacotados, interceptar tráfego em dispositivos comprometidos e reproduzir tokens. Estas regras definem o nível mínimo antes da submissão para a loja.
- Complete o Nível 1 antes que o primeiro recurso de autenticação ou pagamento seja mesclado - refatorar o armazenamento seguro é doloroso e muitas vezes perde casos de ponta.
- Revise os Níveis 2–3 em qualquer PR que toque em variáveis de ambiente, armazenamento, rede ou chaves de SDK de terceiros.
- Execute o Nível 4 no checklist de lançamento -
expo config --type public e fluxos de logout são falhas comuns de auditoria.
- Exceções e omissões de fixação de certificados exigem um ADR com modelo de ameaça - não um atalho de fim de sprint.
- Emparelhe com a equipe de backend sobre tempos de vida de token e revogação - regras de cliente sozinhas não impedem o sequestro de sessão.
-
Nunca coloque segredos em EXPO_PUBLIC_* ou extra: Ambos são incorporados ao pacote do cliente - atacantes os extraem do IPA/APK ou bytecode Hermes.
- Somente público: IDs de cliente de análise destinados à exposição, URLs base de API públicas, chaves de flag de recurso projetadas para SDKs do lado do cliente.
- Servidor: Intenções de pagamento, tokens de administrador e segredos de assinatura permanecem no backend e no EAS Secrets apenas para hooks de compilação.
-
EAS Secrets para valores em tempo de compilação e CI: eas secret:create e variáveis com escopo de ambiente - não Slack, não .env.production commitado.
- Baixar localmente:
eas env:pull --environment development - .env.local permanece ignorado pelo git.
- OTA:
eas update --environment production usa variáveis de ambiente EAS (SDK 55+) - .env local é ignorado nos executores de atualização.
-
Audite a configuração pública antes de cada lançamento: npx expo config --type public - confirme que nenhum URL de staging, nomes de host internos ou chaves de depuração foram enviados para o perfil de produção.
- CI: O script falha no trabalho de lançamento se substrings proibidas aparecerem na saída de configuração pública.
- Rejeitar: "Removeremos o URL de staging em um PR de acompanhamento."
-
.env.example documenta chaves, não valores: Liste as variáveis EXPO_PUBLIC_* e APP_ENV necessárias com valores de placeholder - integração sem vazar segredos de produção.
- Rotacionar: Se um segredo foi comprometido alguma vez, rotacione imediatamente - o histórico do git o retém.
- Escanear: Habilite a verificação de segredos no GitHub para commits acidentais.
-
Sem segredos em logs de crash ou breadcrumbs de análise: Sentry e utilitários de log devem limpar tokens, e-mails e fragmentos de PAN antes do upload.
- Padrão: Redigir cabeçalhos
Authorization em breadcrumbs de rede.
- Testar: Dispare um crash de teste em staging e inspecione a carga do Sentry.
-
Chaves de SDK de terceiros revisadas para exposição no cliente: Chaves de mapas, análises e atribuição no pacote são consideradas públicas - restrinja por ID do pacote e plataforma no painel do fornecedor.
- Rejeitar: Usar um segredo Stripe somente para servidor no código React Native.
- ADR: Documente a coleta de dados de cada SDK de terceiros para alinhamento com a política de privacidade.
-
Tokens de atualização e acesso no expo-secure-store: Keystore com suporte de hardware em dispositivos compatíveis - não AsyncStorage, MMKV sem criptografia ou arquivos expo-file-system simples.
- Instalar:
npx expo install expo-secure-store.
- Limites de tamanho: O armazenamento seguro é para tokens e segredos pequenos - não para blobs JSON grandes.
-
AsyncStorage apenas para preferências não sensíveis: Tema, última aba, estado da UI de rascunho - nunca artefatos de autenticação ou caches de PII.
- Migração: Mover tokens do AsyncStorage para o armazenamento seguro requer uma migração única na atualização do aplicativo.
- Auditar: Use
grep para AsyncStorage.setItem com chaves semelhantes a tokens na revisão de PR.
-
Limpar armazenamento seguro ao sair: SecureStore.deleteItemAsync para todas as chaves de autenticação - emparelhado com a redefinição da pilha de navegação (veja Regras de Navegação e Roteamento).
- Testar: Sair → fechar o aplicativo → reabrir → nenhuma chamada de API autenticada.
- Rejeitar: Logout que apenas limpa o estado do React.
-
Tokens de acesso de curta duração com rotação de atualização: Clientes móveis devem atualizar proativamente - lidar com 401 com uma única tentativa, não loops infinitos.
- Em segundo plano: Atualizar em
AppState foreground se o token estiver perto da expiração.
- Revogação: Revogar no lado do servidor ao sair e alterar senha.
-
Gateway biométrico para ações sensíveis, não substituição de armazenamento: expo-local-authentication desbloqueia a UI ou confirma transações - não substitui o armazenamento seguro do enclave para tokens.
- UX: Solicitação biométrica opcional antes de exibir números completos de cartão ou exportar.
- Fallback: PIN ou reautenticação quando a biometria falhar.
-
Criptografar caches offline que contêm PII: Se MMKV ou SQLite armazenarem dados de saúde ou financeiros do usuário, use criptografia ou minimização do lado do servidor - MMKV padrão é rápido, não confidencial.
- Preferir: Buscar sob demanda; armazenar em cache apenas visualizações derivadas não sensíveis.
- ADR: Documentar o escopo de PII offline para revisores de conformidade.
-
Somente HTTPS para chamadas de API de produção: Rejeitar exceções de texto claro na configuração de produção app.config - android.usesCleartextTraffic é apenas para compilações de desenvolvimento local.
- Desenvolvimento:
http://localhost no perfil de desenvolvimento com APP_ENV=development.
- CI: Lint ou grep bloqueia
http:// em src/ fora de __tests__.
-
A fixação de certificados é uma decisão explícita do produto: Padrão para validação de certificado do sistema no SDK 57 - a fixação quebra proxies corporativos, complica a rotação e requer módulos nativos.
- Quando fixar: Aplicativos de alta ameaça (finanças, saúde) com equipe de segurança para operar runbooks de rotação.
- ADR exigido: Modelo de ameaça, procedimento de rotação e fallback quando os pins expirarem.
-
Se fixar, planeje a rotação antes da implementação: Fixe hashes SPKI com pins de backup - atualizações de loja demoram semanas; pins expirados travam o aplicativo.
- Nativo: Bibliotecas de fixação precisam de reconstruções do dev-client - não apenas OTA.
- Monitorar: Alerta 30 dias antes da renovação do certificado.
-
Validar TLS na camada do cliente de API: Wrapper fetch central rejeita não-HTTPS em compilações de produção - um ponto de estrangulamento para cabeçalhos e anexos de autenticação.
- Padrão:
api/client.ts anexa o bearer do armazenamento seguro; recursos nunca chamam fetch bruto para URLs arbitrários.
- Rejeitar:
fetch(process.env.EXPO_PUBLIC_API_URL + path) disperso sem validação.
-
Não desative a verificação SSL em produção: rejectUnauthorized: false e agentes fetch personalizados são apenas para depuração - grep CI os bloqueia em main.
- Staging: Use certificados de staging adequados, não verificação desativada.
- Proxy Charles: Documente a configuração de proxy apenas para desenvolvimento; nunca envie stores de confiança de proxy para produção.
-
OAuth e deep links usam parâmetros PKCE e state: expo-auth-session com redirecionamento seguro - valide state no retorno; nunca incorpore segredos do cliente em fluxos OAuth móveis.
- Redirecionamento: Esquemas registrados correspondem a
app.config - sem URIs de redirecionamento wildcard no console do provedor.
- Armazenamento: Tokens via armazenamento seguro após a troca de código.
-
Detecção de jailbreak/root é baseada em política, não em teatro de segurança: Se exigido pela conformidade, use um SDK mantido e documente limitações de bypass - não afirme "inviolável".
- Gracioso: Avisar ou limitar recursos; evitar crash duro que prenda usuários legítimos avançados.
- ADR: Citação do requisito de conformidade.
-
Política de captura de tela e gravação de tela para telas sensíveis: Flag segura UITextField do iOS ou overlay para entrada de CVV - equilibre UX com orientações PCI e HIPAA.
- Android:
FLAG_SECURE via plugin de configuração quando mandatório.
- Testar: Capture telas sensíveis na matriz de QA.
-
Permissões são mínimas e justificadas: Solicite câmera, localização e contatos apenas quando o recurso estiver ativo - a revisão do iOS/Android e a confiança do usuário dependem disso.
- Strings: Racional de permissão voltado para o usuário em
app.config e locales/ localizados.
- Rejeitar: Bombardeio de permissões antecipado no primeiro lançamento.
-
Auditoria de dependências antes da submissão para a loja: npm audit, expo-doctor e revisão de manifestos de privacidade de SDK nativos (Rótulos de Nutrição de Privacidade da Apple).
- Cadeia de suprimentos: Fixe lockfile; revise novos deps nativos em PRs sensíveis à segurança.
- Atualizações: Corrija CVEs críticos em deps JS via OTA quando nenhum bump nativo for necessário.
-
Flags de recursos não ignoram autorização do servidor: Flags do cliente ocultam a UI - o servidor deve impor os direitos em cada mutação.
- OTA: Um usuário mal-intencionado pode carregar bundles antigos - a API é a fonte da verdade.
- Veja: Regras de Lançamento e OTA para rollback de canal em flags ruins.
-
Runbook de incidentes para comprometimento de token e chave: Documente quem rotaciona EAS Secrets, revoga clientes OAuth e força o logout - líderes móveis conhecem os passos antes de um incidente.
- Forçar logout: Servidor invalida tokens de atualização; envie banner OTA se necessário.
- Postmortem: Atualize este checklist quando uma regra teria evitado o incidente.
- Nível 1 (1–6): Segredos e configuração - maior raio de explosão; corrija antes que qualquer código de rede seja enviado.
- Nível 2 (7–12): Armazenamento e sessões - evita roubo de token e bugs de logout.
- Nível 3 (13–18): Transporte - os padrões geralmente são suficientes; a fixação é a exceção com papelada.
- Nível 4 (19–24): Conformidade e operações - portão de submissão para a loja e prontidão para incidentes.
Posso colocar chaves de API em EXPO_PUBLIC_?
Somente se a chave for projetada para exposição no cliente (por exemplo, chave de cliente do Google Maps restrita por ID do pacote). Segredos de servidor, chaves secretas do Stripe e tokens de administrador nunca devem estar em EXPO_PUBLIC_*.
Secure store vs MMKV criptografado?
Use expo-secure-store por padrão para tokens no SDK 57. MMKV com criptografia é uma opção para dados estruturados maiores - ainda requer um ADR e uma história de gerenciamento de chaves; secure store é mais simples para artefatos de autenticação.
Devemos implementar fixação de certificados?
A maioria dos aplicativos não deve fixar inicialmente - TLS do sistema mais ciclo de vida adequado de certificados no servidor é suficiente. Fixe quando o modelo de ameaça e as operações de segurança puderem gerenciar a rotação; documente em um ADR.
Como EAS Secrets diferem de EXPO_PUBLIC_?
EAS Secrets e variáveis de ambiente são injetados no tempo de compilação/atualização nos workers EAS - eles não significam automaticamente que são seguros para pacotes do cliente. Apenas valores não sensíveis devem chegar ao JS via extra ou env público. Segredos verdadeiros permanecem no lado do servidor.
Expo Go é seguro para testar fluxos de autenticação?
Expo Go usa o ID do pacote do Expo - o redirecionamento OAuth e algumas restrições do SDK diferem da produção. Teste a autenticação em dev-client ou builds de preview com seu ID de pacote real antes do lançamento.
Como verificar se nenhum segredo vazou?
Execute npx expo config --type public com variáveis de ambiente de produção e inspecione a saída. Adicione grep CI para padrões como sk_live, BEGIN PRIVATE KEY e nomes de host internos.
O que é limpo no logout?
Chaves de autenticação do armazenamento seguro, estado de sessão em memória, caches de consulta com PII e pilha de navegação para autenticação - nessa ordem. Verifique com teste automatizado ou smoke test do Maestro.
Atualizações OTA podem corrigir um vazamento de segredo?
OTA pode remover uma chave vazada de novos pacotes - mas instalações existentes podem reter pacotes antigos até a atualização. Rotacione o segredo comprometido imediatamente no servidor; trate OTA como correção de distribuição, não rotação.
Precisamos de detecção de jailbreak?
Somente quando a política de conformidade ou de fraude exigir - entenda que é contornável. Documente as limitações em ADR; não confie nele para autorização principal.
Quanto tempo os tokens de acesso devem viver?
Curto (minutos a poucas dezenas de minutos) com rotação de atualização - aplicativos móveis são instalações de longa duração. Coordene a lógica de atualização com manipuladores de AppState em segundo plano.
Parâmetros de consulta de deep link são seguros para autenticação?
Não - trate parâmetros de URL como entrada não confiável. Nunca conceda privilégios de ?role=admin. Valide a sessão no lado do servidor.
E quanto ao armazenamento de imagens com PII?
Evite armazenar em cache imagens sensíveis em disco sem criptografia. Use URLs assinados expirados e limpe caches ao sair.
A Nova Arquitetura do React Native muda as regras de segurança?
Não - segredos ainda são enviados em pacotes, as APIs de armazenamento seguro não mudaram. Mantenha o mesmo checklist no RN 0.86.
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (expo ~57.0.4).