
Exemple de Seal Security — application Maven vulnérable (SnakeYAML CVE-2022-1471) remédiée aux versions scellées ; intégration GitHub Actions + Jenkins
Une application Spring Boot minimale et intentionnellement vulnérable, utilisée pour démontrer de bout en bout comment Seal Security corrige une CVE connue en remplaçant une dépendance vulnérable par une version scellée (rétroportée, prête à l'emploi) — sans modifier vos coordonnées déclarées ni votre code.
Elle est conçue comme un test de fumée de bout en bout pour le CLI Seal dans CI/CD : exécutez l'application, déclenchez une véritable exploitation, exécutez Seal, et observez la même exploitation bloquée.
| Écosystème | Java / Maven |
| Paquet vulnérable | org.yaml:snakeyaml:1.33 |
| CVE | CVE‑2022‑1471 — Désérialisation du Constructor SnakeYAML → Exécution de code à distance (CVSS 9.8) |
| Version scellée (corrigée) | snakeyaml 1.33+sp1 depuis le registre Maven de Seal |
| Intégration | CLI Seal comme étape de construction — présentée pour GitHub Actions et Jenkins |
Le projet déclare également d'autres dépendances vulnérables bien connues (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), que Seal corrige également en builds scellés.
La page d'accueil prend un name et l'analyse via le constructeur par défaut de SnakeYAML :
Yaml yaml = new Yaml();
Object parsed = yaml.load(name); // SnakeYAML 1.33 — CVE-2022-1471
Le Constructor par défaut de SnakeYAML instancie n'importe quel type Java nommé dans le YAML — la primitive d'injection d'objets derrière CVE‑2022‑1471. Une charge utile nommant javax.script.ScriptEngineManager (le point d'entrée de la chaîne de gadget RCE classique) suffit à prouver que l'analyseur construira toute classe qu'un attaquant nomme.
Requête normale
/?name=alice → Welcome, alice!
Requête d'exploit
/?name=!!javax.script.ScriptEngineManager []
Le SnakeYAML vulnérable instancie la classe nommée par l'attaquant, l'application affiche une page « Vous avez été piraté » et le serveur est ensuite tué (quelques secondes plus tard, pour que la page se charge d'abord). Rechargez et l'application a disparu — via ngrok, vous verrez une page « endpoint hors ligne ». C'est la primitive d'injection d'objets ; une exploitation complète la chaîne (via URLClassLoader) pour charger et exécuter du code à distance.
.
├── pom.xml # déclare les dépendances vulnérables
├── src/main/java/… # application Spring Boot (HelloController, DataService)
├── .seal-actions.yml # mappage facultatif en mode fixe local (vulnérable → scellé)
├── Jenkinsfile # exemple de pipeline Jenkins (Groovy) avec l'étape Seal
└── .github/workflows/
├── build-and-run.yml # build + exposition de l'application pour les tests navigateur
└── seal-security.yml # exécution de la correction Seal, puis démarrage de l'application
Seal est un SaaS hébergé par Seal — rien n'est installé dans votre environnement, et tout le trafic est sortant HTTPS sur TCP 443 uniquement. Pour exécuter la correction, vous avez besoin de :
Configurez-les dans Settings → Secrets and variables → Actions (GitHub) ou Manage Jenkins → Credentials (Jenkins). Ne committez jamais les jetons dans le dépôt.
Mettez sur liste blanche ces hôtes Seal pour le trafic sortant sur le port 443 : app.sealsecurity.io, authorization.sealsecurity.io, cli.sealsecurity.io, et — pour les artefacts Maven scellés — maven.sealsecurity.io. Le binaire CLI est téléchargé depuis github.com / objects.githubusercontent.com.
mvn clean package -DskipTests
java -jar target/java-example-1.0.0.jar # → http://localhost:8080
Ouvrez http://localhost:8080/?name=alice (fonctionne), puis http://localhost:8080/?name=!!javax.script.ScriptEngineManager [] — l'application affiche « Vous avez été piraté » et le serveur est tué quelques secondes plus tard.
Le CLI Seal s'exécute comme une étape supplémentaire, après la résolution des dépendances et avant l'empaquetage. Il analyse les dépendances résolues et réécrit les dépendances vulnérables vers leurs versions scellées, en utilisant le mode de correction à distance (la politique est gérée de manière centralisée dans l'interface utilisateur Seal).
Utilise seal-community/cli-action :
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: pom.xml # le manifest pour cet écosystème
Exécutez-le via Actions → « Seal Security Remediation » → Run workflow. Voir .github/workflows/seal-security.yml.
Une seule étape ajoutée, après la résolution des dépendances et avant l'empaquetage. Voir 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 provient de l'identifiant Jenkins seal-token ; définissez SEAL_PROJECT sur votre ID de projet Seal.
Après seal fix, les dépendances vulnérables sont résolues en builds scellés depuis le registre Maven de Seal — mêmes coordonnées, correctif de sécurité rétroporté :
Une version scellée est le même artefact avec le correctif de sécurité rétroporté — un remplacement direct, sans modification de code et sans mise à niveau de version majeure.
Réexécutez l'exploit contre l'application corrigée. Le snakeyaml scellé refuse d'instancier les types globaux malveillants, donc la charge utile ne charge plus le JAR distant — l'exécution de code à distance est bloquée.
seal fix vers le manifeste spécifique — pom.xml pour Maven. Pour un build multi-modules, exécutez un seal fix par manifeste.C'est toute l'intégration — une étape, sortant uniquement, aucune modification du code de l'application.
| Secret / identifiant |
|---|
| Utilisé pour |
|---|
| Où il va |
|---|
| Jeton Seal | Authentification du CLI Seal | Secret GitHub Actions SEAL_TOKEN / Identifiant « Secret text » Jenkins seal-token |
| Jeton ngrok (facultatif) | Exposition de l'application en cours d'exécution à un navigateur pour les tests | Secret GitHub Actions NGROK_TOKEN |
| Dépendance | Avant | Après (scellé) |
|---|
| 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 |