
Seal Security उदाहरण — असुरक्षित npm ऐप (EJS CVE-2022-29078) को सीलबंद संस्करणों में सुधारा गया; GitHub Actions + Jenkins एकीकरण
एक minimal, जानबूझकर vulnerable Node.js/Express एप्लिकेशन, जिसका उपयोग अंत-से-अंत (end-to-end) यह प्रदर्शित करने के लिए किया जाता है कि Seal Security किसी ज्ञात CVE को कैसे remediate करता है — एक vulnerable डिपेंडेंसी को sealed (backported, drop‑in) संस्करण से बदलकर — आपके declared version ranges या आपके कोड में कोई बदलाव किए बिना।
इसे CI/CD में Seal CLI के लिए फ्रंट-टू-बैक स्मोक टेस्ट के रूप में डिज़ाइन किया गया है: ऐप चलाएँ, एक वास्तविक exploit ट्रिगर करें, Seal चलाएँ, और देखें कि वही exploit ब्लॉक हो जाता है।
| इकोसिस्टम | JavaScript / npm |
| Vulnerable पैकेज | [email protected] (2.7.4 पर resolve होता है) |
| CVE | CVE‑2022‑29078 — EJS सर्वर‑साइड टेम्पलेट इंजेक्शन → रिमोट कोड एक्ज़ीक्यूशन (CVSS 9.8) |
| Sealed (ठीक किया गया) संस्करण | Seal के npm registry से ejs 2.7.4-sp1 |
| एकीकरण | एक बिल्ड स्टेप के रूप में Seal CLI — GitHub Actions और Jenkins दोनों के लिए दिखाया गया |
ऐप अन्य जानी-मानी vulnerable डिपेंडेंसीज़ (lodash 4.17.5, json5 0.5.1, got 6.7.1) भी शामिल करता है, जिनमें से प्रत्येक को Seal एक sealed बिल्ड में भी remediate करता है।
ऐप पूरी URL query string को सीधे EJS render कॉल में फैला देता है:
const data = { name: 'World', ...req.query };
res.render('page', data, ...)
EJS एक settings['view options'] ऑब्जेक्ट स्वीकार करता है जिसका outputFunctionName मान — बिना sanitize किए — संकलित टेम्पलेट फ़ंक्शन बॉडी में लिखा जाता है। इसलिए एक हमलावर मनमाना JavaScript इंजेक्ट कर सकता है जो Node.js प्रोसेस के विशेषाधिकारों के साथ सर्वर पर चलता है।
सामान्य अनुरोध
/?name=alice
Hello alice! रेंडर करता है।
Exploit अनुरोध
/?name=Hacker&settings[view%20options][outputFunctionName]=x;setTimeout(function()%7Bprocess.exit(1)%7D,3000);s
सर्वर setTimeout(function(){ process.exit(1) }, 3000) निष्पादित करता है। पेज पहले लोड होता है और स्पष्ट रूप से बताता है कि RCE सफल रहा; कुछ सेकंड बाद रीलोड करें और आपको ERR_CONNECTION_REFUSED मिलेगा — इंजेक्ट किए गए कोड ने सर्वर को kill कर दिया, जिससे यह साबित होता है कि मनमाना कोड चला।
3‑सेकंड की देरी जानबूझकर है: यह प्रोसेस के बाहर निकलने से पहले रिस्पॉन्स को ब्राउज़र तक पहुँचने देती है, ताकि आप "exploit succeeded" पेज देखें और फिर एक फ्रोज़न टैब के बजाय एक साफ़ क्रैश देखें।
.
├── index.js # the vulnerable Express app
├── views/ # EJS templates
├── package.json / package-lock.json
├── 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
Seal SaaS, Seal‑hosted है — आपके वातावरण में कुछ भी इंस्टॉल नहीं होता है, और सारा ट्रैफ़िक केवल TCP 443 पर आउटबाउंड HTTPS है। Remediation चलाने के लिए आपको चाहिए:
| सीक्रेट / क्रेडेंशियल |
|---|
इन्हें Settings → Secrets and variables → Actions (GitHub) या Manage Jenkins → Credentials (Jenkins) में कॉन्फ़िगर करें। टोकन को कभी भी रिपॉजिटरी में कमिट न करें।
आउटबाउंड 443 के लिए इन Seal होस्ट्स को allowlist करें:
app.sealsecurity.io, authorization.sealsecurity.io, cli.sealsecurity.io, और — sealed npm पैकेजों के लिए — npm.sealsecurity.io। CLI बाइनरी github.com / objects.githubusercontent.com से डाउनलोड होती है।
npm install
npm start # → http://localhost:3001
http://localhost:3001/?name=alice खोलें (काम करता है), फिर ऊपर दिया गया exploit URL खोलें (सर्वर क्रैश हो जाता है)।
Seal CLI एक अतिरिक्त चरण के रूप में चलती है, npm install के बाद और पैकेजिंग से पहले। यह resolved डिपेंडेंसीज़ को स्कैन करती है और vulnerable डिपेंडेंसीज़ को उनके sealed संस्करणों में फिर से लिखती है, remote fix मोड का उपयोग करके (पॉलिसी Seal UI में केंद्रीय रूप से प्रबंधित होती है)।
यह seal-community/cli-action का उपयोग करता है:
- uses: seal-community/cli-action@latest
with:
mode: fix
fix_mode: remote
token: ${{ secrets.SEAL_TOKEN }}
target: package-lock.json # the lock file for this ecosystem
इसे Actions → “Seal Security Remediation” → Run workflow के माध्यम से चलाएँ। .github/workflows/seal-security.yml देखें।
इंस्टॉल के बाद और पैकेजिंग से पहले एक अतिरिक्त stage। 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 seal-token Jenkins क्रेडेंशियल से आता है; SEAL_PROJECT को अपने Seal Project ID पर सेट करें।
seal fix के बाद, vulnerable डिपेंडेंसीज़ Seal के registry से sealed बिल्ड्स पर resolve होती हैं — आपके package.json version ranges वही रहते हैं:
एक sealed संस्करण वही पैकेज है जिसमें सुरक्षा फिक्स backport किया गया है, इसलिए यह एक drop‑in प्रतिस्थापन है — कोई कोड परिवर्तन नहीं, कोई major‑version अपग्रेड नहीं।
Remediated ऐप पर exploit URL फिर से चलाएँ। इंजेक्शन अब निष्पादित नहीं होता: sealed ejs दुर्भावनापूर्ण outputFunctionName को अस्वीकार कर देता है और ऐप payload चलाने के बजाय “Invalid parameter” के साथ प्रतिक्रिया करता है। सर्वर चालू रहता है।
seal fix को विशिष्ट manifest/lock फ़ाइल पर इंगित करें — npm के लिए package-lock.json। कई manifests वाली रिपॉजिटरी के लिए, प्रत्येक manifest के लिए एक seal fix चलाएँ।पूरा एकीकरण बस इतना है — एक stage, केवल आउटबाउंड, एप्लिकेशन कोड में कोई बदलाव नहीं।
| उपयोग |
|---|
| कहाँ जाता है |
|---|
| Seal टोकन | Seal CLI को प्रमाणित करना | GitHub Actions सीक्रेट SEAL_TOKEN / Jenkins "Secret text" क्रेडेंशियल seal-token |
| ngrok टोकन (वैकल्पिक) | चल रहे ऐप को परीक्षण के लिए ब्राउज़र पर एक्सपोज़ करना | GitHub Actions सीक्रेट NGROK_TOKEN |
| डिपेंडेंसी | पहले | बाद में (sealed) |
|---|
| 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 |