
keyv/cacheable सप्लाई-चेन हमले के लिए स्कैनर: समझौता किए गए npm पैकेजों का पता लगाता है, पेलोड हैश सत्यापित करता है, और रेपो और होस्ट मोड में पर्सिस्टेंस इम्प्लांट ढूंढता है।
अंग्रेज़ी | Português
keyv/cacheable सप्लाई-चेन घटना ("Shai-Hulud: Here We Go Again", 4 अगस्त 2026) के लिए स्टैंडअलोन स्कैनर — 440+ npm पैकेज एक स्व-प्रसार वर्म द्वारा समझौता किए गए हैं जो क्लाउड/CI क्रेडेंशियल्स चुराता है और डेड-मैन स्विच के साथ पर्सिस्टेंस स्थापित करता है।
मिनटों में और कुछ भी इंस्टॉल किए बिना पता लगाता है:
package-lock.json, npm-shrinkwrap.json, yarn.lock (v1 और Berry), pnpm-lock.yaml और bun.lock में — ट्रांज़िटिव डिपेंडेंसी सहित, पूरी चेन के साथ (जैसे eslint → file-entry-cache → flat-cache → [email protected]);node_modules में (ज्ञात आर्टिफैक्ट्स का नाम + SHA-256 हैश);SUSPECT चिह्नित, बिना हैश के कभी पुष्टि नहीं;.claude/settings.json और .vscode/tasks.json में हुक, अस्थायी आर्टिफैक्ट्स (bun-dl-*);keyv/cacheable परिवारों का मेंटेनर खाता समझौता किया गया; हमलावर ने "preinstall": "node setup.mjs" हुक के साथ नए वर्शन प्रकाशित किए — वह कोड जो पैकेज इंस्टॉल होने से पहले चलता है, उसी के विशेषाधिकारों के साथ जिसने npm install चलाया।setup.mjs GitHub से Bun रनटाइम डाउनलोड करता है और उसमें पेलोड चलाता है — उन टूल्स से बचाव जो केवल node प्रोसेस की निगरानी करते हैं।Math_Symbol.js (~728 KB, ऑबफस्केटेड) क्रेडेंशियल्स चुराता है: AWS इंस्टेंस मेटाडेटा, AWS/GCP/Azure कुंजियाँ, Vault टोकन, Kubernetes सर्विस अकाउंट, GitHub Actions सीक्रेट, npm टोकन, साथ ही डिस्क पर प्राइवेट कुंजियों और bearer टोकन के लिए एक सामान्य regex स्वीप।npm install/npm ci चलाया। --ignore-scripts के साथ, हुक नहीं चला।.claude/settings.json (SessionStart) और .vscode/tasks.json (folderOpen) में ऑटोस्टार्ट हुक मिले जो क्लोन किए गए फ़ोल्डर को खोलने पर लोडर चलाते हैं — न कोई npm install, न कुछ इंस्टॉल हुआ। इसमें वे लोग शामिल हैं जिन्होंने घटना की जांच करने के लिए रिपो क्लोन की और AI कोडिंग एजेंट जिन्होंने डायरेक्टरी खोली — AI-एजेंट हुक (.claude/) को सप्लाई-चेन वेक्टर के रूप में उपयोग किए जाने के पहले सार्वजनिक मामलों में से एक।इम्प्लांट एक "वॉचर" (gh-token-monitor) इंस्टॉल करता है जिसे LaunchAgent (macOS) या systemd यूज़र सर्विस + loginctl enable-linger (Linux) जीवित रखता है। हर 60 सेकंड में यह चुराए गए GitHub टोकन को API के विरुद्ध मान्य करता है। जब तक टोकन काम करता है, कुछ नहीं होता। जब प्रतिक्रिया 4xx हो जाती है — यानी जिस क्षण आप टोकन रिवोक करते हैं — यह eval के माध्यम से ~/.config/gh-token-monitor/handler की सामग्री चलाता है: हमलावर द्वारा रिमोट से परिभाषित एक मनमाना कमांड। सार्वजनिक विश्लेषण नहीं जानता कि इसमें क्या है — यह डेटा विनाश, पुनः-इम्प्लांटेशन, रैंसमवेयर या कुछ भी नहीं हो सकता। जोखिम का आकलन संभव नहीं है; इसीलिए प्रतिक्रिया क्रम अनिवार्य है।
तीन गुण जो प्रतिक्रिया बदलते हैं:
host मोड में इस बारे में चेतावनी देता है।[email protected] पासिंग SLSA अटेस्टेशन के साथ भेजा गया था। प्रोवेनेंस बिल्ड इंटीग्रिटी की पुष्टि करता है, सोर्स की नहीं: वैध वर्कफ़्लो ने पहले से ट्रोजनाइज़्ड कोड को संकलित किया।package.json के preinstall हुक और पैकेज में जोड़ी गई दो नई फ़ाइलों (setup.mjs, Math_Symbol.js) में है।eslint → file-entry-cache → flat-cache → keyv है। इसीलिए स्कैनर हर निष्कर्ष में चेन दिखाता है।scan.mjs में निम्नलिखित गुण हैं — सप्लाई-चेन घटना का जवाब देने वाले किसी भी व्यक्ति के लिए महत्वपूर्ण:
npm install नहीं। इसे चलाने से पहले 15 मिनट में पूरे scan.mjs का ऑडिट करें।--update है (एक ताज़ा IOC मेनिफेस्ट डाउनलोड करना), स्पष्ट और वैकल्पिक।docker run --network=none या एक आइसोलेटेड मशीन: बस scan.mjs + iocs.json कॉपी करें।आवश्यकता: Node.js ≥ 18 (npm वाली किसी भी मशीन पर यह पहले से मौजूद है)। दो फ़ाइलें डाउनलोड करें — scan.mjs + iocs.json — और बस: कोई इंस्टॉलेशन नहीं।
सावधानी: यदि आपने यह पूरी रिपॉजिटरी क्लोन की है, तो
fixtures/फ़ोल्डर में परीक्षणों में उपयोग किए गए निष्क्रिय IOC हैं (वास्तविक नाम और वर्शन, डमी सामग्री — कोई मैलवेयर नहीं)। स्कैनर इसे स्वचालित रूप से छोड़ देता है और आउटपुट में चेतावनी देता है; इससे प्राप्त निष्कर्ष केवल तभी दिखाई देते हैं यदि आप इसे जानबूझकर स्कैन करते हैं।
दो रन मोड हैं जो अलग-अलग प्रश्नों के उत्तर देते हैं, और यही तय करता है कि कहाँ चलाना है:
repo मोड लॉकफ़ाइल्स और node_modules पढ़ता है — और लॉकफ़ाइल्स git में रहती हैं, इसलिए इसे केंद्रीकृत किया जा सकता है: एक व्यक्ति कंपनी की हर रिपॉजिटरी को स्कैन करता है।host मोड इम्प्लांट (वॉचर, LaunchAgent/systemd, IDE हुक) की तलाश करता है, जो उस मशीन पर रहता है जहाँ कोड निष्पादित हुआ — यह git में नहीं है और इसे केंद्रीकृत नहीं किया जा सकता।node scan.mjs repo /folder/with/all/the/repos --json=result.json --html=report.html
मिनटों में उत्तर देता है कि "कौन से प्रोजेक्ट एक्सपोज़्ड हैं", बिना किसी को शामिल किए। कई पथ स्वीकार करता है; उपनिर्देशिकाओं में जाता है (मोनोरेपो और वर्कस्पेस सहित)।
निष्कर्ष वाले प्रत्येक प्रोजेक्ट के लिए, पहचानें कि 2026-08-04 09:35 UTC से किसने इसे छुआ (git log, CI लॉग)। वे लोग अपनी मशीन पर चलाते हैं:
node scan.mjs # current directory + host, in ~30 seconds
दायरे में: कोई भी जिसने (a) उस अवधि में npm install/npm ci चलाया; या (b) केवल क्लोन किया और फ़ोल्डर को VS Code या AI एजेंट में खोला — वेक्टर B को किसी इंस्टॉल की आवश्यकता नहीं है।
चूंकि लागत ~30 सेकंड है और फ़नल लीक हो सकता है (एक भटका हुआ क्लोन, एक व्यक्तिगत प्रोजेक्ट), सबसे सुरक्षित आंतरिक संदेश है: हर डेवलपर एक बार node scan.mjs चलाता है और --json/--html AppSec को भेजता है। भेजना डिज़ाइन द्वारा मैनुअल है — स्कैनर में कोई टेलीमेट्री नहीं है (शून्य एग्रेस)।
सर्वोच्च प्राथमिकता: यहीं सबसे मूल्यवान क्रेडेंशियल्स रहते हैं। यहाँ स्कैनर की दो अलग-अलग भूमिकाएँ हैं — एक अतीत के लिए, एक भविष्य के लिए:
अतीत का ट्राइएज — निर्णय के लिए रनर को स्कैन न करें। प्रश्न "क्या यह रनर प्रभावित हुआ?" का उत्तर स्कैन से नहीं मिलता: यदि किसी जॉब ने 08-04 से --ignore-scripts के बिना एक प्रभावित वर्शन इंस्टॉल किया, तो क्रेडेंशियल्स उसी क्षण पहले ही चुराए जा चुके थे, और रनर होस्ट शायद ही साक्ष्य रखता है (एपेमरल रनर जॉब के अंत में कंटेनर को नष्ट कर देते हैं; वॉचर ~24h में स्वयं-साफ़ हो जाता है)। इसका उत्तर चरण 1 की लॉकफ़ाइल्स और CI लॉग देते हैं। यदि उत्तर "हाँ, इसे इंस्टॉल किया गया" है: रनर को फिर से बनाएं और उसके सीक्रेट रोटेट करें — रनर एपेमरल होते हैं, उन्हें साफ़ करने का कोई कारण नहीं है।
आगे की रोकथाम — हाँ, इसे पाइपलाइन में चलाएं। स्कैनर को एक बिल्ड चरण के रूप में जोड़ें, repo मोड में, चेकआउट के बाद और npm install से पहले। यह रनर होस्ट की जांच नहीं करता — यह उस कोड की जांच करता है जो इंस्टॉल होने वाला है, और एक्ज़िट कोड दुर्भावनापूर्ण preinstall को चलने का मौका मिलने से पहले बिल्ड को विफल कर देता है:
# example (GitHub Actions / GitLab CI — adapt):
- run: node scan.mjs repo . --json # exit 0 clean · 1 findings · 2 COMPROMISED
- run: npm ci --ignore-scripts # only runs if the previous step passed
node scan.mjs # scan the current directory + the host
node scan.mjs repo /path/a /path/b
node scan.mjs host # persistence/implants on the machine only
node scan.mjs repo . --json=result.json --html=report.html
node scan.mjs --update # update iocs.json (the only network operation)
| स्तर | अर्थ | कार्रवाई |
|---|---|---|
COMPROMISED | node_modules में दुर्भावनापूर्ण वर्शन इंस्टॉल, हैश द्वारा पुष्टि किया गया पेलोड, या पर्सिस्टेंस इम्प्लांट मिला | होस्ट को समझौता मानें; प्रतिक्रिया क्रम का पालन करें — क्रेडेंशियल्स रोटेट करने से पहले इम्प्लांट साफ़ करें |
EXPOSED | लॉकफ़ाइल में दुर्भावनापूर्ण वर्शन पिन किया गया, निष्पादन का कोई साक्ष्य नहीं | एक सुरक्षित वर्शन पिन करें, node_modules हटाएं, --ignore-scripts के साथ पुनः इंस्टॉल करें |
AT_RISK | package.json में रेंज (^/~) जो दुर्भावनापूर्ण वर्शन स्वीकार करती है | एक सटीक वर्शन पिन करें या इसे रजिस्ट्री प्रॉक्सी पर ब्लॉक करें |
SUSPECT | ह्यूरिस्टिक (बेमेल हैश वाली वर्म फ़ाइलनाम, संदिग्ध लाइफसाइकल स्क्रिप्ट) | मैन्युअल रूप से निरीक्षण करें — नया वैरिएंट या गलत सकारात्मक हो सकता है |
INFO | वेक्टर मौजूद लेकिन कोई IOC नहीं (जैसे एक सामान्य folderOpen कार्य) | समीक्षा करें |
--html एक स्व-निहित रिपोर्ट तैयार करता है जिसमें टाइमस्टैम्प, होस्टनाम, IOC मेनिफेस्ट वर्शन और स्कैनर की अपनी SHA-256 होती है — घटना सूचना के अनुलग्नक और ऑडिट ट्रेल के रूप में उपयोग योग्य।
अभी किसी भी क्रेडेंशियल को रिवोक या रोटेट न करें — यही जाल का ट्रिगर है। अनुक्रम:
1. आइसोलेट करें — मशीन को नेटवर्क से काट दें। यह सुरक्षित है: कोई HTTP प्रतिक्रिया न होने पर कोई 4xx नहीं, जाल नहीं चलता, और डेटा बाहर निकालना रुक जाता है। पावर ऑफ न करें (वोलेटाइल मेमोरी साक्ष्य है)।
2. संरक्षित करें — कुछ भी हटाने से पहले (वॉचर ~24h में स्वयं-नष्ट हो जाता है):
mkdir -p /tmp/evidence && cp -r ~/.config/gh-token-monitor /tmp/evidence/ 2>/dev/null
cp /tmp/gh-token-monitor.*.log /tmp/evidence/ 2>/dev/null
shasum -a 256 /tmp/evidence/* 2>/dev/null
handler फ़ाइल हमलावर का वह कमांड है जो निष्पादित किया जाएगा — इसे न चलाएं, इसे शेल में पेस्ट न करें; इसे निष्क्रिय पाठ मानें। started_at फ़ाइल एक्सपोज़र विंडो को सीमित करती है (ऑडिटर और नियामक इसके लिए पूछेंगे)।
3. उन्मूलित करें — पहले वॉचर प्रोसेस को खत्म करें, फिर:
# macOS
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
rm -f ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
# Linux
systemctl --user disable --now gh-token-monitor.service
loginctl disable-linger "$USER"
rm -f ~/.config/systemd/user/gh-token-monitor.service
# both
rm -rf ~/.config/gh-token-monitor ~/.local/bin/gh-token-monitor.sh /tmp/bun-dl-*
साथ ही .claude/settings.json और .vscode/tasks.json से दुर्भावनापूर्ण हुक, setup.mjs/Math_Symbol.js/math_init.js फ़ाइलें हटाएं, और कैश साफ़ करें (~/.npm/_cacache, pnpm, yarn)। node scan.mjs host को तब तक फिर से चलाएं जब तक यह साफ़ वापस न आए।
4. रोटेट करें — केवल तब जब हर प्रभावित होस्ट साफ़ और सत्यापित हो (एक भी जीवित वॉचर ट्रिगर चलाने के लिए पर्याप्त है)। पहले npm टोकन रिवोक करें (वर्म को प्रसारित होने से रोकता है); फिर GitHub (PATs, डिप्लॉय कुंजियाँ), AWS/GCP/Azure, Vault, Kubernetes, CI सीक्रेट — और कोई भी सीक्रेट जो डिस्क पर था, क्योंकि एक regex स्वीप हुआ था।
5. ऑडिट करें — वर्म आपके नाम पर कार्य करता है: अपने संगठनों में Shai-Hulud: Here We Go Again वर्णित रिपॉजिटरी खोजें, 08-04 से अप्रत्याशित रूप से प्रकाशित npm वर्शन (उन्हें डेप्रिकेट करें और उपभोक्ताओं को सूचित करें), और started_at विंडो के भीतर CloudTrail/Audit Logs में क्रेडेंशियल्स का उपयोग देखें।
बाद में: node_modules हटाएं, एक साफ़ लॉकफ़ाइल से --ignore-scripts के साथ पुनः इंस्टॉल करें। पुष्टि किए गए निष्पादन वाले CI रनर और होस्ट: हमेशा खरोंच से फिर से बनाएं — मनमाना कोड निष्पादित हुआ, और ज्ञात आर्टिफैक्ट्स की सूची पूर्णता की गारंटी नहीं है।
विनियमित संस्थान (BR): क्रेडेंशियल एक्सेस के साथ पुष्टि किया गया समझौता रिपोर्टिंग दायित्वों को ट्रिगर कर सकता है (Res. CMN 4.893/2021, Res. BCB 85/2021; व्यक्तिगत डेटा शामिल होने पर LGPD art. 48)। UTC में समयरेखा दर्ज करें —
started_at, पहचान, रोकथाम, उन्मूलन, रोटेशन — और कानूनी/अनुपालन के साथ समय-सीमाओं की पुष्टि करें।
घटना सक्रिय है और सूची बढ़ती रहती है। नवीनतम मेनिफेस्ट लाने के लिए:
node scan.mjs --update # the only operation that touches the network
--update iocs.json को इसी रिपॉजिटरी से (securest8/npm-incident-response) लाता है, कभी किसी तीसरे पक्ष से नहीं — Securest8 क्यूरेशन गेट है। आपको वही मिलता है जो यहाँ अंतिम रूप से प्रकाशित हुआ था।
पैकेज सूची सार्वजनिक Wiz फ़ीड से आती है; हैश, C2 डोमेन, पर्सिस्टेंस IOC और सुरक्षित वर्शन स्थिर हैं और tools/gen-iocs.mjs में क्यूरेट किए गए हैं। Wiz CSV का एक स्नैपशॉट पुनरुत्पादन और ऑफ़लाइन रन के लिए tools/keyv-packages.csv पर रहता है।
node tools/gen-iocs.mjs # fetch the latest Wiz CSV, regenerate iocs.json + refresh the snapshot
node tools/gen-iocs.mjs --offline # regenerate from the committed snapshot, no network
node tools/gen-iocs.mjs --allow-shrink # allow a package count lower than the snapshot (guarded by default)
जेनरेटर आइडेम्पोटेंट है: यह मौजूदा manifest_version बनाए रखता है और जब कुछ भी भौतिक रूप से नहीं बदला होता तो फ़ाइल को दोबारा नहीं लिखता, और यह एक खाली या सिकुड़ा हुआ मेनिफेस्ट लिखने से इनकार कर देता है (छोटे/बदले हुए अपस्ट्रीम फ़ीड से सुरक्षा)।
स्वचालन: .github/workflows/update-iocs.yml जेनरेटर को दैनिक (और मांग पर) चलाता है और main में केवल तभी कमिट करता है जब IOC वास्तव में बदलते हैं — इसलिए उपयोगकर्ताओं का --update लगभग एक दिन के भीतर Wiz फ़ीड को ट्रैक करता है, पूरा इतिहास कमिट्स में ऑडिट योग्य होता है। घटना शांत होने के बाद इसे पुल-रिक्वेस्ट चरण में बदल दें (वर्कफ़्लो में नोट किया गया) यदि आप इसके बजाय मैनुअल मर्ज चाहते हैं।
node test/run-tests.mjs # 15 assertions against fixtures/demo-repo
fixtures/demo-repo एक परीक्षण रिपॉजिटरी है जिसमें निष्क्रिय IOC हैं (वास्तविक नाम और वर्शन, डमी सामग्री — कोई मैलवेयर नहीं)। स्कैनर की अपनी रिपॉजिटरी को स्कैन करते समय, fixtures/ फ़ोल्डर स्वचालित रूप से छोड़ दिया जाता है (आउटपुट में चेतावनी के साथ); परीक्षण पथ को स्पष्ट रूप से पास करके इसे स्कैन करते हैं।
एक एकल-घटना उपकरण, हमले की सक्रिय विंडो के दौरान तेज़ ट्राइएज के लिए बनाया गया — Socket, Snyk या समान का प्रतिस्थापन नहीं। अनुसंधान और IOC: Socket.dev, Wiz Research (सार्वजनिक CSV), Kodem Security।
Securest8 द्वारा अनुरक्षित। MIT लाइसेंस।