
Пример Seal Security — уязвимое приложение Maven (SnakeYAML CVE-2022-1471), исправленное до защищённых версий; интеграция GitHub Actions + Jenkins
Минимальное, намеренно уязвимое приложение Spring Boot, используемое для демонстрации сквозного процесса того, как Seal Security устраняет известную CVE, заменяя уязвимую зависимость на запечатанную (бэкпортированную, готовую к замене) версию — без изменений ваших объявленных координат или кода.
Оно предназначено для сквозного smoke-теста Seal CLI в CI/CD: запустите приложение, вызовите реальную эксплуатацию, запустите Seal и наблюдайте, как та же эксплуатация блокируется.
| Экосистема | Java / Maven |
| Уязвимый пакет | org.yaml:snakeyaml:1.33 |
| CVE | CVE‑2022‑1471 — Десериализация SnakeYAML Constructor → Удаленное выполнение кода (CVSS 9.8) |
| Запечатанная (исправленная) версия | snakeyaml 1.33+sp1 из реестра Maven от Seal |
| Интеграция | Seal CLI как один шаг сборки — показано для GitHub Actions и Jenkins |
Проект также объявляет другие известные уязвимые зависимости (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), каждую из которых Seal также устраняет до запечатанной сборки.
На странице приветствия принимается name и парсится через конструктор SnakeYAML по умолчанию:
Yaml yaml = new Yaml();
Object parsed = yaml.load(name); // SnakeYAML 1.33 — CVE-2022-1471
Конструктор SnakeYAML по умолчанию Constructor будет создавать экземпляры произвольных типов Java, указанных в YAML — это примитив внедрения объектов, лежащий в основе CVE‑2022‑1471. Полезная нагрузка, указывающая javax.script.ScriptEngineManager (точка входа классической цепочки гаджетов RCE), достаточна, чтобы доказать, что парсер построит любой класс, указанный атакующим.
Обычный запрос
/?name=alice → Welcome, alice!
Эксплуатирующий запрос
/?name=!!javax.script.ScriptEngineManager []
Уязвимый SnakeYAML создает экземпляр класса, указанного атакующим; приложение показывает страницу “You've been pwned”, а сервер затем завершается (через несколько секунд, чтобы страница сначала отобразилась). После перезагрузки приложение исчезает — через ngrok вы увидите страницу “endpoint offline”. Это примитив внедрения объектов; полная эксплуатация цепляет его (через URLClassLoader) для загрузки и выполнения удаленного кода.
.
├── pom.xml # объявляет уязвимые зависимости
├── src/main/java/… # приложение Spring Boot (HelloController, DataService)
├── .seal-actions.yml # дополнительное локальное сопоставление режима исправления (уязвимый → запечатанный)
├── Jenkinsfile # пример конвейера Jenkins (Groovy) с этапом Seal
└── .github/workflows/
├── build-and-run.yml # сборка + публикация приложения для тестирования в браузере
└── seal-security.yml # запуск исправления Seal, затем запуск приложения
Seal — это SaaS, размещенный на серверах Seal — ничего не устанавливается в вашей среде, и весь трафик осуществляется только исходящий HTTPS через TCP 443. Для запуска исправления вам понадобится:
| Секрет / учетные данные |
|---|
Настройте их в Settings → Secrets and variables → Actions (GitHub) или Manage Jenkins → Credentials (Jenkins). Никогда не коммитьте токены в репозиторий.
Разрешите для исходящих соединений на порт 443 следующие хосты Seal:
app.sealsecurity.io, authorization.sealsecurity.io, cli.sealsecurity.io, а для запечатанных артефактов Maven — maven.sealsecurity.io. Бинарный файл CLI загружается с github.com / objects.githubusercontent.com.
mvn clean package -DskipTests
java -jar target/java-example-1.0.0.jar # → http://localhost:8080
Откройте http://localhost:8080/?name=alice (работает), затем http://localhost:8080/?name=!!javax.script.ScriptEngineManager [] — приложение показывает "You've been pwned", и сервер завершается через несколько секунд.
Seal CLI выполняется как один дополнительный шаг, после разрешения зависимостей и до упаковки. Он сканирует разрешенные зависимости и перезаписывает уязвимые на их запечатанные версии, используя удаленный режим исправления (политика управляется централизованно в интерфейсе Seal).
Используется seal-community/cli-action:
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: pom.xml # манифест для этой экосистемы
Запустите через Actions → “Seal Security Remediation” → Run workflow. См. .github/workflows/seal-security.yml.
Один добавленный этап после разрешения зависимостей и до упаковки. См. 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 берется из учетных данных Jenkins seal-token; установите SEAL_PROJECT в ваш идентификатор проекта Seal.
После seal fix уязвимые зависимости разрешаются в запечатанные сборки из реестра Maven от Seal — те же координаты, бэкпортированное исправление безопасности:
Запечатанная версия — это тот же артефакт с бэкпортированным исправлением безопасности — готовая замена, без изменений кода и без обновления мажорной версии.
Повторно выполните эксплуатацию против исправленного приложения. Запечатанный snakeyaml отказывается создавать экземпляры вредоносных глобальных типов, поэтому полезная нагрузка больше не загружает удаленный JAR — удаленное выполнение кода блокируется.
seal fix на конкретный манифест — pom.xml для Maven. Для многомодульной сборки запускайте один seal fix на каждый манифест.Вот и вся интеграция — один этап, только исходящие соединения, никаких изменений в коде приложения.
| Используется для |
|---|
| Где хранится |
|---|
| Токен Seal | Аутентификация Seal CLI | Секрет GitHub Actions SEAL_TOKEN / учетные данные Jenkins "Secret text" seal-token |
| Токен ngrok (необязательно) | Публикация работающего приложения для тестирования в браузере | Секрет GitHub Actions NGROK_TOKEN |
| Зависимость | До | После (запечатанная) |
|---|
| 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 |