Auditar app Android na mão não escala mais

Agente de segurança com IA que encontra vulnerabilidade real ainda era promessa até outro dia. Agora o GitHub Security Lab mostrou um caso concreto que muda a conversa. Com taskflows abertos de auditoria, um pesquisador relatou 24 vulnerabilidades em aplicativos Android, incluindo três falhas no OsmAnd, aquele app de navegação com mais de 10 milhões de downloads na Play Store. Uma delas permitia rastrear usuários de um jeito que ninguém tinha mapeado. O ponto aqui não é o número. É o método. Em vez de jogar o repo inteiro para o modelo e torcer, ele quebrou a auditoria em etapas pequenas, guiou o modelo para entry points mobile e forçou checagem de classes de falha que LLM costuma ignorar. Para quem mantém app em produção, isso acende um alerta prático. Se um agente aberto faz isso em uma ou duas horas, o atacante também vai fazer.

O fato

O time do GitHub Security Lab criou o Taskflow Agent, um agente open source para automatizar, empacotar e compartilhar prompts e fluxos de auditoria. A ideia é simples e direta. Pesquisador de segurança testa um fluxo que funciona, salva como taskflow em YAML e outra pessoa consegue rodar o mesmo raciocínio no próprio repo. Nesse caso, o pesquisador criou dois ajustes focados em mobile e rodou em apps Android reais. O resultado foi o reporte de mais de 20 vulnerabilidades, com 24 já contabilizadas até a publicação, todas passando por disclosure responsável e aparecendo aos poucos na página de advisories. Os exemplos já revelados incluem falhas de rastreamento via OsmAnd e problemas clássicos de Android que continuam passando em review manual. Para rodar, você abre o repositório seclab-taskflows em um codespace, espera inicializar e executa um script do tipo ./scripts/audit/run_mobile.sh com o seu org e repo. Precisa de licença do GitHub Copilot porque os prompts usam premium requests e fazem muitas chamadas de ferramenta, o que consome bastante token.

Por que Android exigiu um fluxo próprio

Taskflows genéricos de auditoria já funcionavam, mas Android tem uma superfície de ataque própria que confunde modelo generalista. Intent explícita e implícita, deep link, content provider, broadcast receiver, service exportado, WebView com bridge para JavaScript, armazenamento externo, tudo isso cria caminhos que não existem em backend web. Sem guiar, o modelo se perde entre código Kotlin, Java, XML de manifest e Gradle, e deixa passar justamente a ligação entre componentes. Foi para resolver isso que surgiram os dois arquivos novos. E é aí que a abordagem fica interessante para quem opera.

Como funciona na visão de quem opera

O primeiro arquivo é o gather_mobile_entry_point_info.yaml. Pense nele como triagem de superfície. Ele varre o repo, lista onde dado controlado por atacante pode entrar e separa o que é entry point mobile do que não é. Isso importa porque muito repo Android não é só app. Tem servidor, script, módulo desktop junto. Sem essa separação, o agente perde tempo auditando API interna como se fosse componente exportado. Com a separação, ele entende que precisa focar em Activity exportada, receiver com intent-filter, provider com grantUriPermissions e por aí vai. Na prática, é um filtro de atenção que economiza token e reduz ruído.

O segundo é o classify_application_local.yaml ajustado. Aqui o truque é forçar cobertura. Como LLM é não determinístico e vulnerabilidade mobile é menos representada no treino, o prompt entrega uma lista de classes populares e pede para avaliar cada entry point e componente contra aquela lista. Se o passo anterior marcou um entry point baseado em intent, o modelo é obrigado a checar confused deputy, broadcast inseguro, hijacking de intent, vazamento via intent implícita e redirecionamento. É uma checagem dirigida, quase como um checklist que não deixa ele pular etapa por preguiça estatística. A sacada operacional está em combinar os dois estilos em múltiplas execuções. O prompt restrito com repetição garante que o óbvio não escape. O prompt amplo deixa o modelo usar criatividade para encadear componentes e montar o threat model completo.

Em termos de arquitetura, dá para inferir o desenho sem ter visto cada linha. É um agente em loop com ferramentas de leitura de repo, busca semântica e execução de prompts encadeados, provavelmente rodando sobre a API do Copilot com contexto de codespace. Cada rodada gera registros em SQLite, na tabela audit_results, com uma flag has_vulnerability para triagem. O custo real está nas tool calls. Em repo médio, o relato fala em uma a duas horas de execução. Isso sugere dezenas a centenas de chamadas, facilmente dezenas de milhares de tokens por run se o contexto incluir manifest, código fonte e grafos de chamada. Latência não é problema para auditoria offline, mas custo é. Rode isso em dez repos toda semana sem filtro e a conta de premium requests pesa. Também pesa o tempo de triagem humana, porque agente bom em recall costuma gerar falso positivo.

O que isso muda na prática

Quem ganha primeiro é time pequeno que nunca teve security champion. Antes, auditar intents exportadas exigia especialista Android que conhece manifest de cor. Agora dá para rodar um ponto de partida automatizado e chegar na revisão com uma lista priorizada. Quem mantém SDK, app bancário, saúde, logística ou qualquer app com localização e arquivos locais ganha ainda mais, porque são justamente os alvos onde confused deputy e provider mal configurado viram vazamento de dados. Quem perde é quem confia em checklist de loja e acha que estar na Play Store significa estar seguro. E perde também quem shipa WebView com addJavascriptInterface sem validação ou exporta componente por conveniência para resolver deep link rápido.

Se você shipa Android hoje, faça uma ação prática ainda nesta semana. Suba um codespace isolado com cópia do seu app, rode o run_mobile.sh no branch principal e abra o SQLite viewer na tabela audit_results filtrando por has_vulnerability marcado. Não tente corrigir tudo. Pegue os três primeiros com entry point exportado e valide na mão se o componente é realmente alcançável por app de terceiro. Olhe principalmente para estes pontos.

  • Activity, service, receiver e provider com exported true ou com intent-filter sem permissão restritiva
  • Broadcast sem restrição, intent implícita com dado sensível e retorno de resultado sem checagem de chamador
  • Deep link que carrega URL externa em WebView, carrega arquivo ou repassa token

Esse mini processo já vale o esforço. Mesmo que metade seja falso positivo, você mapeia sua superfície exportada de verdade, coisa que muito time não tem documentada. E documente o que o agente marcou como limpo, porque na próxima release você compara o diff e roda de novo só no que mudou. Assim você transforma auditoria pesada em gate leve de CI, em vez de mutirão anual.

A tensão que ninguém quer admitir

Funciona, mas escala com qual custo e com qual ruído. Essa é minha dúvida real depois de ver o fluxo. Forçar checklist ajuda o recall, só que também empurra o modelo a ver vulnerabilidade onde não há. Em Android isso é traiçoeiro, porque muito componente parece exportado no manifest e na prática está protegido por permissão custom, por validação no código nativo ou por fluxo que exige interação. O agente não tem runtime, não roda o app, não confirma exploitabilidade de ponta a ponta. Então ele move o gargalo em vez de eliminar. Antes o gargalo era achar onde olhar. Agora o gargalo passa a ser triar dezenas de achados com contexto incompleto, decidir o que é explorável e escrever prova de conceito sem quebrar o sprint. Para empresa com AppSec maduro, ótimo, é pipeline. Para time sem ninguém para triar, vira backlog assustador que ninguém prioriza.

Tem outro ponto. Repetir runs para aumentar cobertura multiplica token e tempo. Uma a duas horas para repo médio é aceitável uma vez. Para monorepo com vários flavors, build types e módulos, pode virar noite inteira de execução. Se cada run usa premium requests do Copilot, o gestor vai perguntar rapidinho qual é o custo por vulnerabilidade verdadeira confirmada, não por flag no SQLite. Minha leitura é que o valor está menos no achado automático e mais na padronização do raciocínio. O taskflow em YAML vira conhecimento versionado. Você ajusta, compartilha, melhora. Isso é mais poderoso que o agente em si, porque tira a auditoria da cabeça de uma pessoa e coloca em artefato auditável.

Conclusão

No fim, o recado é direto. Auditoria com IA deixou de ser demo e virou ferramenta replicável para Android, com 24 falhas reportadas para provar. Vale rodar no seu app, mapear exports e corrigir o básico antes que alguém rode contra você. A pergunta que fica é simples. Quando qualquer pessoa consegue caçar falha de intent em escala, quanto tempo seu manifest atual sobrevive sem revisão.