Mobile Security no CI/CD com GitHub Actions
Avalie o pacote Android ou iOS que o seu build produz dentro do seu pipeline do GitHub Actions com o WASViking Sentinel. Envia o artefato por HTTPS, executa a avaliação estática com base no OWASP MASVS e no MASTG, faz o build falhar quando há novos achados usando um diff de baseline e publica os resultados na aba Security do GitHub.
Esta integração envia o pacote do aplicativo móvel que o seu build produz para o WASViking® Mobile Security Assessment, de dentro do seu runner do GitHub Actions, e faz o pipeline falhar quando a release traz achados que importam para você. O pacote é analisado estaticamente com base no OWASP Mobile Application Security Verification Standard (MASVS) e no Mobile Application Security Testing Guide (MASTG). Nada é instalado em um dispositivo e nada é executado.
Diferentemente do fluxo de DAST, não há túnel mTLS nem aplicação em execução para alcançar: o artefato é um arquivo. O runner o envia direto para um armazenamento de objetos seguro, com uma autorização de propósito único, de modo que os bytes nunca passam pela API, e a avaliação roda no mesmo motor que o portal usa.
A configuração é curta. Você precisa de uma coisa no portal (uma chave de
API com o escopo mobile:scan) e de uma coisa no GitHub Actions (essa chave
como secret). A mesma chave instala o agente e executa a avaliação, então não
há um token de agente separado para gerenciar.
O que esta integração faz
- Avalia o
.apk,.aabou.ipaque o seu pipeline gera, a cada push ou pull request. - Faz o build falhar por severidade com
--fail-on, de modo que uma release que regride é bloqueada antes do merge. - Compara com a avaliação anterior do mesmo aplicativo usando
--baseline new, de modo que um build só falha pelos achados que ele introduz, não pela dívida preexistente. - Emite SARIF 2.1.0, consumido nativamente pelo GitHub Code Scanning, além de um resumo completo em JSON.
- Registra quem gerou o quê: o pipeline anota o provedor, o repositório, a branch, o commit e a execução, para que toda avaliação seja rastreável até um build.
- Desconta da sua franquia mensal de avaliações mobile em CI e lista cada execução no portal, marcada como um envio de pipeline.
Como funciona
- O runner instala o agente Sentinel usando a sua chave
mobile:scan. - O agente pede à API que autorize um upload e recebe uma autorização de curta duração e propósito único, válida para um objeto.
- O agente envia o pacote direto para o armazenamento de objetos seguro. Os bytes não passam pela API nem pela CDN.
- A API verifica o objeto armazenado, confirma que ele é um pacote de aplicativo real e enfileira a avaliação para a sua organização.
- O motor executa as suas verificações (configuração, segurança de transporte, criptografia, armazenamento local, interação com a plataforma, hardening do binário, componentes de terceiros, credenciais embutidas e SDKs de rastreamento) e pontua o resultado.
- O agente grava
wasviking-mobile.sarifewasviking-mobile.json, e o workflow envia o SARIF para o GitHub Code Scanning.
Postura de acesso
- Apenas o pacote do aplicativo que você indica com
--fileé enviado. Nenhum código-fonte, nenhuma variável de ambiente do runner além da chave que você passa e nenhum arquivo fora do diretório de trabalho são coletados. - A autorização de upload é de propósito único e curta duração, e fixa o objeto exato; uma autorização adulterada é recusada.
- O envio é feito por HTTPS com uma chave de API. A WASViking autentica com o
header
Authorization: ApiKey <key>, não comBearer. - Revogue o acesso a qualquer momento revogando a chave de API no portal.
Pré-requisitos
| Requisito | Detalhe |
|---|---|
| Módulo WASViking | Mobile Security Assessment habilitado para a sua organização, com uma franquia de avaliações em CI provisionada. É um add-on; fale com o seu contato de conta ou parceiro se ele ainda não estiver habilitado. |
| Papel no portal | Admin ou Manager, para emitir chaves de API. |
| Repositório no GitHub | Permissão para criar secrets do Actions e arquivos em .github/. |
| Permissões do workflow | contents: read e security-events: write (para o upload do SARIF). |
| Artefato de build | Um .apk, .aab, .xapk, .apks ou .ipa produzido por um passo anterior do job. |
| Runner | Hospedado pelo GitHub (ubuntu-latest recomendado) ou self-hosted Linux x86_64. |
| Saída de rede | HTTPS para api.wasviking.com, para o endpoint de armazenamento de objetos que ela retorna e para github.com na porta 443. Nenhuma conexão de entrada é necessária. |
Não usa GitHub Actions? O mesmo gate roda em qualquer sistema de CI em que o binário
wasviking-sentinelpossa ser executado. Veja wasviking-sentinel mobile.
Passo 1: Crie uma chave de API com o escopo mobile:scan (portal)
Esta única chave tanto baixa o agente quanto executa a avaliação.
Vá em Settings → System Settings → API Keys e clique em + New Key (nova chave).
| Campo | Valor |
|---|---|
| Label | Algo identificável, por exemplo GitHub Actions mobile pipeline. Use uma chave por repositório para poder revogá-la sem afetar outros pipelines. |
| Scopes | Selecione apenas mobile:scan (Submit mobile app packages (APK/IPA) for assessment from a CI/CD pipeline). Menor privilégio: não adicione escopos de que o pipeline não precisa. |
| Expiration | 90 dias é um padrão sensato; faça a rotação nessa cadência. |
Salve e copie a chave uma única vez. Você vai colá-la no GitHub no Passo 2 como
WASV_MOBILE_API_KEY.
Você pode revisar ou ajustar os escopos de uma chave depois, em Edit, na linha da chave. Editar os escopos mantém o mesmo valor da chave, então o pipeline continua funcionando sem que o secret precise ser emitido de novo.
Passo 2: Adicione o secret no GitHub
Nunca faça commit de uma chave no repositório. Guarde-a como um secret criptografado do Actions.
No GitHub, vá em Settings → Secrets and variables → Actions → Secrets do repositório e adicione:
| Nome | Valor |
|---|---|
WASV_MOBILE_API_KEY |
A chave de API do Passo 1. |
Use Secrets (criptografados), nunca Variables, para a chave. Para vários ambientes (staging, produção), prefira Environment secrets com revisores obrigatórios e regras de proteção de implantação.
Passo 3: Adicione o workflow
Crie .github/workflows/wasviking-mobile.yml. O exemplo gera um
APK Android; substitua o passo Build the app pela forma como o seu projeto
produz o pacote e aponte --file para o artefato.
name: WASViking Mobile Security
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
security-events: write
actions: read
jobs:
mobile-assessment:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4
# Replace with your own build. The result must be an .apk, .aab,
# .xapk, .apks, or .ipa on disk.
- name: Build the app
run: ./gradlew assembleRelease
- name: Install WASViking Sentinel
env:
WASV_MOBILE_API_KEY: ${{ secrets.WASV_MOBILE_API_KEY }}
run: |
curl -sSL -H "Authorization: ApiKey $WASV_MOBILE_API_KEY" \
https://api.wasviking.com/api/v1/sentinel/install.sh | sh
- name: Run WASViking mobile assessment
env:
WASV_API_KEY: ${{ secrets.WASV_MOBILE_API_KEY }}
run: |
mkdir -p wasviking-reports
./.wasviking/wasviking-sentinel mobile \
--file app/build/outputs/apk/release/app-release.apk \
--label "${{ github.repository }}@${{ github.sha }}" \
--fail-on high \
--baseline new \
--out ./wasviking-reports
- name: Upload SARIF to GitHub code scanning
if: always() && hashFiles('wasviking-reports/wasviking-mobile.sarif') != ''
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: wasviking-reports/wasviking-mobile.sarif
category: wasviking-mobile
- name: Upload raw reports as artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: wasviking-mobile-reports
path: wasviking-reports/
O comando de avaliação lê a chave de
WASV_API_KEY, então você não precisa repetir--api-keyna linha de comando. O upload para o Code Scanning (o passo do SARIF) exige o GitHub Advanced Security em repositórios privados. Se você não tem esse recurso, remova esse passo e use o artefato enviado e o portal no lugar dele.
Passo 4: Flags do comando
wasviking-sentinel mobile [flags]
| Flag | Obrigatória | Descrição |
|---|---|---|
--file |
Sim | Caminho para o pacote do aplicativo (.apk, .aab, .xapk, .apks, .ipa). |
--api-key |
Sim | Chave de API com o escopo mobile:scan. Prefira a variável de ambiente WASV_API_KEY, para que a chave nunca apareça no argv do processo nem nos logs do CI. |
--label |
Não | Um rótulo armazenado com a avaliação, por exemplo o nome da release ou o commit. |
--fail-on |
Não | Limite único: critical, high, medium, low ou none. Lógica de "igual ou acima": --fail-on high falha com severidade alta e crítica. Padrão: critical. |
--baseline |
Não | new (só contam os achados ausentes da avaliação anterior do mesmo aplicativo) ou all (postura total). Padrão: all. |
--out |
Não | Diretório de saída para o SARIF e o JSON. Padrão: diretório atual. |
--timeout |
Não | Tempo total disponível para o upload mais a análise. Padrão: 40m. |
--api |
Não | URL base da API. Padrão: https://api.wasviking.com. Também lida de WASV_API. |
Dois arquivos são produzidos:
wasviking-mobile.sarif: SARIF 2.1.0 (GitHub Code Scanning, GitLab e outros).wasviking-mobile.json: o resumo da execução, com contagens por severidade, pontuação de risco e procedência.
Exit codes
| Código | Significado |
|---|---|
0 |
Sucesso. Nada igual ou acima do limite do --fail-on (considerando a baseline escolhida). |
1 |
Os achados excedem o limite. Bloqueia o merge. |
2 |
Erro operacional (pacote ausente, argumentos inválidos, falha de autenticação ou de upload). |
Política de fail-on
--fail-on define a menor severidade que faz o build falhar, e tudo o que
está acima dela também falha.
| Configuração | Comportamento |
|---|---|
--fail-on none |
Nunca falha. Apenas relatório. |
--fail-on critical |
Falha apenas com severidade crítica. |
--fail-on high |
Falha com severidade alta e crítica. Um bom padrão para pull requests. |
--fail-on medium |
Falha com severidade média e acima. Mais rigoroso, mais atrito. |
Um rollout prático: comece em critical para manter o atrito inicial baixo e
depois aperte para high quando a sua baseline estiver limpa.
Diff de baseline
--baseline controla o que conta para a política de fail-on. A baseline é
a avaliação concluída anterior do mesmo aplicativo (mesma plataforma
e mesmo identificador de pacote), quer essa execução anterior tenha vindo de um
pipeline, quer de um upload manual no portal. A comparação é feita pela identidade
do achado, então um aumento de versão não a reinicia.
| Modo | Comportamento |
|---|---|
all (padrão) |
Todo achado conta. Use em branches de release e auditorias, para aplicar o gate sobre a postura total. |
new |
Só contam os achados ausentes da avaliação anterior. Use nos pull requests do dia a dia, para que um build falhe pelo que ele introduz, não pela dívida que herdou. |
Na primeira avaliação de um aplicativo não há nada com que
comparar, então new aplica o gate sobre o conjunto completo nessa execução e
estabelece a baseline para a próxima. O SARIF marca cada resultado como novo,
existente ou corrigido e lista o que uma release reparou desde a baseline.
Procedência do build
O pipeline lê as variáveis de ambiente padrão do CI e registra, junto com a avaliação, o provedor, o repositório, a branch, o commit, o identificador da execução e o autor, sem flags adicionais. O portal mostra isso ao lado da execução, e o mesmo contexto segue no documento SARIF, de modo que um achado em um pull request é rastreável até o build exato que o produziu. GitHub Actions, GitLab CI, Bitbucket Pipelines e CircleCI são reconhecidos automaticamente.
O que é e o que não é coletado
A WASViking não coleta o código-fonte do seu repositório, variáveis de ambiente do runner além da chave que você passa, conteúdo do sistema de arquivos do runner fora do diretório de trabalho nem qualquer dado de produção. Apenas o pacote do aplicativo que você indica é enviado. Os valores de secrets embutidos encontrados durante a análise são armazenados mascarados, nunca em texto claro. Os dados são processados na região dos Estados Unidos, criptografados em trânsito (TLS 1.2+) e em repouso (AES-256), com retenção definida pelo seu plano. Um DPA e a residência de dados na União Europeia estão disponíveis sob solicitação; veja o Trust Center para o mapeamento completo de conformidade (ISO 27001, SOC 2, LGPD, GDPR, OWASP MASVS, OWASP MASTG, NIST SSDF, OWASP DSOMM).
Problemas comuns
| Problema | Causa provável |
|---|---|
HTTP 401 Unauthorized |
Chave de API revogada, expirada ou sem o escopo mobile:scan. A WASViking usa Authorization: ApiKey <key>, não Bearer. |
HTTP 403 feature_not_in_plan |
O Mobile Security Assessment não está habilitado para a sua organização. É um add-on; peça ao seu contato de conta ou parceiro para habilitá-lo. |
HTTP 402 quota_exhausted |
A sua franquia mensal de avaliações mobile em CI se esgotou. Aguarde a virada do ciclo ou aumente a franquia. |
HTTP 402 quota_not_provisioned |
O módulo está ligado, mas ainda não há uma franquia de avaliações em CI definida. Provisione uma no portal. |
HTTP 400 unsupported_extension / unsupported_format |
O arquivo não é um pacote de aplicativo reconhecido. Aponte --file para o .apk/.aab/.ipa real, não para um wrapper ou uma página HTML de download. |
HTTP 413 file_too_large |
O pacote está acima do limite de upload da sua organização. |
HTTP 409 assessment is still running |
O SARIF foi solicitado antes de a análise terminar. A CLI trata isso aguardando; você só vê esse erro se chamar o endpoint diretamente. |
| Assessment finished with status=failed | O motor não conseguiu analisar o pacote. A saída em JSON traz o motivo. |
Erro no download do install.sh |
Política de rede bloqueando api.wasviking.com ou o bucket de releases. |
Onde isto se encaixa na plataforma
- As avaliações de pipeline aparecem ao lado dos uploads manuais em Mobile Security → Assessments, marcadas com um selo CI.
- A capacidade em si está documentada em Mobile Security Assessment.
- O equivalente para DAST é DAST no CI/CD com GitHub Actions; o equivalente para dependências e secrets é SCA, SBOM e secrets no CI/CD.
