
Exemplo do Seal Security — aplicativo Maven vulnerável (SnakeYAML CVE-2022-1471) corrigido para versões lacradas; integração com GitHub Actions + Jenkins
Uma aplicação Spring Boot mínima e intencionalmente vulnerável usada para demonstrar, de ponta a ponta, como a Seal Security corrige um CVE conhecido substituindo uma dependência vulnerável por uma versão selada (backportada, substituível) — sem alterar suas coordenadas declaradas ou seu código.
Foi projetado como um teste de fumaça completo para o Seal CLI em CI/CD: execute o aplicativo, acione um exploit real, execute o Seal e veja o mesmo exploit ser bloqueado.
| Ecossistema | Java / Maven |
| Pacote vulnerável | org.yaml:snakeyaml:1.33 |
| CVE | CVE‑2022‑1471 — Desserialização do Constructor do SnakeYAML → Execução Remota de Código (CVSS 9.8) |
| Versão selada (corrigida) | snakeyaml 1.33+sp1 do registro Maven da Seal |
| Integração | Seal CLI como uma etapa de construção — mostrado para GitHub Actions e Jenkins |
O projeto também declara outras dependências vulneráveis conhecidas (jackson-databind 2.13.1, commons-text 1.9, spring-core/web 5.3.26, json-smart 2.4.8, commons-lang3 3.12.0, spring-boot 2.7.18), cada uma das quais o Seal também corrige para uma versão selada.
A página de boas-vindas recebe um name e o analisa através do construtor padrão do SnakeYAML:
Yaml yaml = new Yaml();
Object parsed = yaml.load(name); // SnakeYAML 1.33 — CVE-2022-1471
O Constructor padrão do SnakeYAML instanciará tipos Java arbitrários mencionados no YAML — a primitiva de injeção de objeto por trás do CVE‑2022‑1471. Um payload nomeando javax.script.ScriptEngineManager (o ponto de entrada da cadeia de gadgets RCE clássica) é suficiente para provar que o analisador construirá qualquer classe que um atacante nomear.
Requisição normal
/?name=alice → Welcome, alice!
Requisição de exploit
/?name=!!javax.script.ScriptEngineManager []
O SnakeYAML vulnerável instancia a classe nomeada pelo atacante, o aplicativo mostra uma página “Você foi hackeado” e o servidor é então encerrado (alguns segundos depois, para que a página seja exibida primeiro). Recarregue e o aplicativo desaparece — pelo ngrok você verá uma página “endpoint offline”. Esta é a primitiva de injeção de objeto; um exploit completo a encadeia (via URLClassLoader) para carregar e executar código remoto.
.
├── pom.xml # declara as dependências vulneráveis
├── src/main/java/… # aplicação Spring Boot (HelloController, DataService)
├── .seal-actions.yml # mapeamento opcional de modo de correção local (vulnerável → selado)
├── Jenkinsfile # pipeline de exemplo Jenkins (Groovy) com a etapa Seal
└── .github/workflows/
├── build-and-run.yml # compila + expõe o aplicativo para teste no navegador
└── seal-security.yml # executa a correção Seal, depois inicia o aplicativo
O Seal é SaaS, hospedado pela Seal — nada é instalado em seu ambiente, e todo o tráfego é HTTPS de saída na porta TCP 443 apenas. Para executar a correção, você precisa de:
| Segredo/credencial |
|---|
Configure-os em Settings → Secrets and variables → Actions (GitHub) ou Manage Jenkins → Credentials (Jenkins). Nunca faça commit de tokens no repositório.
Coloque na lista de permissões estes hosts do Seal para saída na porta 443: app.sealsecurity.io, authorization.sealsecurity.io, cli.sealsecurity.io e — para artefatos Maven selados — maven.sealsecurity.io. O binário do CLI é baixado de github.com / objects.githubusercontent.com.
mvn clean package -DskipTests
java -jar target/java-example-1.0.0.jar # → http://localhost:8080
Abra http://localhost:8080/?name=alice (funciona), depois http://localhost:8080/?name=!!javax.script.ScriptEngineManager [] — o aplicativo mostra "Você foi hackeado" e o servidor é encerrado alguns segundos depois.
O Seal CLI é executado como uma etapa extra, após a resolução das dependências e antes do empacotamento. Ele escaneia as dependências resolvidas e reescreve as vulneráveis para suas versões seladas, usando o modo de correção remota (a política é gerenciada centralmente na interface do Seal).
Usa seal-community/cli-action:
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: pom.xml # the manifest for this ecosystem
Execute-o via Actions → “Seal Security Remediation” → Run workflow. Veja .github/workflows/seal-security.yml.
Uma única etapa adicionada, após a resolução de dependências e antes do empacotamento. Veja Jenkinsfile:
stage('Seal') {
steps {
sh '''
curl -fsSL https://github.com/seal-community/cli/releases/download/latest/seal-linux-amd64-latest -o seal
chmod +x seal
./seal fix --mode remote "$SEAL_MANIFEST" # SEAL_MANIFEST=pom.xml
'''
}
}
SEAL_TOKEN vem da credencial seal-token do Jenkins; defina SEAL_PROJECT para o ID do seu Projeto Seal.
Após seal fix, as dependências vulneráveis são resolvidas para builds selados do registro Maven do Seal — mesmas coordenadas, correção de segurança backportada:
Uma versão selada é o mesmo artefato com a correção de segurança backportada — uma substituição direta, sem alterações de código e sem atualização de versão principal.
Execute novamente o exploit contra o aplicativo corrigido. O snakeyaml selado se recusa a instanciar os tipos globais maliciosos, então o payload não carrega mais o JAR remoto — a execução remota de código é bloqueada.
seal fix para o manifesto específico — pom.xml para Maven. Para um build com múltiplos módulos,
execute um seal fix por manifesto.Essa é toda a integração — uma etapa, apenas saída, sem alterações no código da aplicação.
| Usado para |
|---|
| Onde vai |
|---|
| Token do Seal | Autenticar o Seal CLI | Segredo do GitHub Actions SEAL_TOKEN / Credencial "Secret text" do Jenkins seal-token |
| Token ngrok (opcional) | Expor o aplicativo em execução a um navegador para teste | Segredo do GitHub Actions NGROK_TOKEN |
| Dependência | Antes | Depois (selado) |
|---|
| org.yaml:snakeyaml | 1.33 | 1.33+sp1 |
| com.fasterxml.jackson.core:jackson-databind | 2.13.1 | 2.13.1+sp1 |
| org.apache.commons:commons-text | 1.9 | 1.9+sp1 |
| org.springframework:spring-core / spring-web | 5.3.26 | 5.3.26+sp1 |
| net.minidev:json-smart | 2.4.8 | 2.4.8+sp1 |
| org.apache.commons:commons-lang3 | 3.12.0 | 3.12.0+sp1 |
| org.springframework.boot:spring-boot | 2.7.18 | 2.7.18+sp1 |