
Seal Security Beispiel — anfällige npm-App (EJS CVE-2022-29078) auf sealed Versionen aktualisiert; GitHub Actions + Jenkins Integration
Eine minimale, absichtlich unsichere Node.js/Express-Anwendung, die verwendet wird, um durchgängig zu demonstrieren, wie Seal Security eine bekannte CVE behebt, indem sie eine anfällige Abhängigkeit durch eine gesiegelte (zurückportierte, einsetzbare) Version ersetzt – ohne Änderung Ihrer deklarierten Versionsbereiche oder Ihres Codes.
Es ist als umfassender Smoke-Test für die Seal CLI in CI/CD konzipiert: Führen Sie die App aus, lösen Sie einen echten Exploit aus, führen Sie Seal aus und beobachten Sie, wie derselbe Exploit blockiert wird.
| Ökosystem | JavaScript / npm |
| Verwundbares Paket | [email protected] (löst auf zu 2.7.4) |
| CVE | CVE‑2022‑29078 — EJS server-seitige Template-Injection → Remote Code Execution (CVSS 9.8) |
| Gesiegelte (behobene) Version | ejs 2.7.4-sp1 aus Seals npm-Registry |
| Integration | Seal CLI als ein Build-Schritt – gezeigt für GitHub Actions und Jenkins |
Die App enthält auch andere bekannte verwundbare Abhängigkeiten (lodash 4.17.5, json5 0.5.1, got 6.7.1), die Seal jeweils ebenfalls zu einer gesiegelten Version behebt.
Die App übergibt den gesamten URL-Abfragestring direkt an den EJS-Render-Aufruf:
const data = { name: 'World', ...req.query };
res.render('page', data, ...)
EJS akzeptiert ein Objekt settings['view options'], dessen Wert outputFunctionName – ungefiltert – in den kompilierten Template-Funktionskörper geschrieben wird. Ein Angreifer kann daher beliebiges JavaScript injizieren, das auf dem Server mit den Privilegien des Node.js-Prozesses ausgeführt wird.
Normale Anfrage
/?name=alice
rendert Hello alice!.
Exploit-Anfrage
/?name=Hacker&settings[view%20options][outputFunctionName]=x;setTimeout(function()%7Bprocess.exit(1)%7D,3000);s
Der Server führt setTimeout(function(){ process.exit(1) }, 3000) aus. Die Seite lädt zunächst und zeigt klar an, dass RCE erfolgreich war; laden Sie einige Sekunden später neu und Sie erhalten ERR_CONNECTION_REFUSED – der injizierte Code hat den Server beendet, was beweist, dass beliebiger Code ausgeführt wurde.
Die 3-Sekunden-Verzögerung ist beabsichtigt: Sie lässt die Antwort den Browser erreichen, bevor der Prozess beendet wird, sodass Sie die Seite 'Exploit erfolgreich' sehen und dann einen sauberen Absturz, anstatt eines eingefrorenen Tabs.
.
├── index.js # die verwundbare Express-App
├── views/ # EJS-Templates
├── package.json / package-lock.json
├── Jenkinsfile # Beispiel-Jenkins-(Groovy)-Pipeline mit dem Seal-Schritt
└── .github/workflows/
├── build-and-run.yml # baut + stellt die App für Browser-Tests bereit
└── seal-security.yml # führt Seal-Behebung aus, startet dann die App
Seal ist SaaS, von Seal gehostet – nichts wird in Ihrer Umgebung installiert, und der gesamte Verkehr ist nur ausgehendes HTTPS auf TCP 443. Um die Behebung durchzuführen, benötigen Sie:
Konfigurieren Sie diese in Settings → Secrets and variables → Actions (GitHub) oder Manage Jenkins → Credentials (Jenkins). Committen Sie Tokens niemals in das Repository.
Erlauben Sie diese Seal-Hosts für ausgehende Verbindungen auf Port 443: app.sealsecurity.io, authorization.sealsecurity.io, cli.sealsecurity.io, und – für gesiegelte npm-Pakete – npm.sealsecurity.io. Die CLI-Binärdatei wird von github.com / objects.githubusercontent.com heruntergeladen.
npm install
npm start # → http://localhost:3001
Öffnen Sie http://localhost:3001/?name=alice (funktioniert), dann die Exploit-URL oben (stürzt den Server ab).
Die Seal CLI wird als ein zusätzlicher Schritt nach npm install und vor dem Packen ausgeführt. Sie scannt die aufgelösten Abhängigkeiten und schreibt die anfälligen auf deren gesiegelte Versionen um, dabei wird der Remote-Fix-Modus verwendet (Richtlinien werden zentral in der Seal UI verwaltet).
Verwendet seal-community/cli-action:
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: package-lock.json # die Lock-Datei für dieses Ökosystem
Führen Sie es aus über Actions → 'Seal Security Remediation' → Run workflow. Siehe .github/workflows/seal-security.yml.
Ein einzelner hinzugefügter Schritt, nach der Installation und vor dem Packen. Siehe 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=package-lock.json
'''
}
}
SEAL_TOKEN stammt aus der seal-token Jenkins-Anmeldedaten; setzen Sie SEAL_PROJECT auf Ihre Seal-Projekt-ID.
Nach seal fix lösen die anfälligen Abhängigkeiten auf gesiegelte Builds aus Seals Registry auf – Ihre package.json-Versionsbereiche bleiben gleich:
Eine gesiegelte Version ist das gleiche Paket mit dem zurückportierten Sicherheitsfix, also ein Drop-in-Ersatz – keine Code-Änderungen, kein Major-Version-Upgrade.
Führen Sie die Exploit-URL erneut gegen die behobene App aus. Die Injektion wird nicht mehr ausgeführt: Das gesiegelte ejs weist den bösartigen outputFunctionName zurück und die App antwortet mit „Ungültiger Parameter“ anstatt die Payload auszuführen. Der Server bleibt verfügbar.
seal fix auf die spezifische Manifest-/Lock-Datei – package-lock.json für npm. Für ein Repository mit mehreren Manifesten führen Sie ein seal fix pro Manifest aus.Das ist die gesamte Integration – ein Schritt, nur ausgehend, keine Änderungen am Anwendungscode.
| Geheimnis / Zugangsdaten |
|---|
| Verwendet für |
|---|
| Wo es gespeichert wird |
|---|
| Seal-Token | Authentifizierung der Seal CLI | GitHub Actions Secret SEAL_TOKEN / Jenkins 'Secret text'-Credential seal-token |
| ngrok-Token (optional) | Bereitstellung der laufenden App für einen Browser zum Testen | GitHub Actions Secret NGROK_TOKEN |
| Abhängigkeit | Vorher | Nachher (gesiegelt) |
|---|
| ejs | 2.7.4 | 2.7.4‑sp1 |
| lodash | 4.17.5 | 4.17.5‑sp1 |
| json5 | 0.5.1 | 0.5.1‑sp1 |
| got | 6.7.1 | 6.7.1‑sp1 |