
एक स्थानीय पैकेज स्थापना सहायक ने कॉलर-आपूर्ति पैकेज नामों पर बहुत अधिक भरोसा किया। yeoman-environment में, लापता जनरेटर उपयोगकर्ता की पुष्टि के बिना स्थापित किए जा सकते हैं, जिससे हमलावर-नियंत्रित प्रोजेक्ट मेटाडेटा पैकेज-स्थापना और कोड-निष्पादन पथ में बदल जाता है।
एक स्थानीय पैकेज इंस्टॉलेशन हेल्पर ने कॉलर द्वारा प्रदान किए गए पैकेज नामों पर बहुत अधिक भरोसा किया। yeoman-environment में, लापता जनरेटर उपयोगकर्ता की पुष्टि के बिना स्थापित किए जा सकते थे, जिससे हमलावर-नियंत्रित प्रोजेक्ट मेटाडेटा पैकेज-इंस्टॉल और कोड-निष्पादन पथ में बदल गया।
मुझे यह मुद्दा generator-jhipster की समीक्षा करते समय एक सरल सुरक्षा प्रश्न के साथ मिला:
क्या हमलावर-नियंत्रित प्रोजेक्ट मेटाडेटा एक डेवलपर टूल को तीसरे पक्ष का कोड लाने और निष्पादित करने के लिए मजबूर कर सकता है, इससे पहले कि उपयोगकर्ता स्पष्ट रूप से ऐसा करने के लिए कहे?
इस मामले में, उत्तर हाँ था।
जो शुरू में JHipster मुद्दा लग रहा था, वह yeoman-environment में एक गहरे अपस्ट्रीम मूल कारण के रूप में सामने आया।
कमजोर व्यवहार Yeoman के स्थानीय जनरेटर इंस्टॉलेशन फ्लो में था, जहां कॉलर द्वारा प्रदान किए गए लापता पैकेज उपयोगकर्ता की पुष्टि के बिना स्वचालित रूप से स्थापित हो जाते थे। एक डाउनस्ट्रीम उपभोक्ता में जो हमलावर-नियंत्रित पैकेज नामों को उस पथ में पास करता था, यह एक वास्तविक पैकेज-इंस्टॉलेशन और कोड-निष्पादन श्रृंखला बनाने के लिए पर्याप्त था।
That issue became CVE-2026-42089.
yeoman-environment: GitHub पर yeoman-environment
Package: yeoman-environment (npm)
CVE: CVE-2026-42089
इसने yeoman-environment को प्रभावित किया, जो Yeoman के जनरेटर-लोडिंग और बूटस्ट्रैपिंग फ्लो के पीछे का रनटाइम लेयर है। आधिकारिक प्रोजेक्ट इसे जनरेटर जीवनचक्र और खोज को संभालने वाले घटक के रूप में वर्णित करता है, और 26 जून, 2026 तक, npm पैकेज पेज ने 1,466,426 साप्ताहिक डाउनलोड सूचीबद्ध किए, जो इसे जावास्क्रिप्ट टूलिंग इकोसिस्टम में व्यापक रूप से तैनात पैकेज बनाता है।
attacker-controlled project config -> caller-supplied generator package names -> yeoman-environment silently installs missing packages -> downstream tool loads installed generator code -> package installation and code execution during CLI bootstrap
yeoman-environment Yeoman-आधारित टूलिंग के पीछे का रनटाइम और जनरेटर-लोडिंग लेयर है।
अन्य चीजों के अलावा, यह संभालता है:
इसका मतलब है कि यह सीधे एक विश्वास सीमा पर बैठता है।
प्रासंगिक प्रश्न यह नहीं है कि Yeoman "सिर्फ एक स्थानीय उपकरण" है या नहीं।
प्रासंगिक प्रश्न यह है कि क्या अविश्वसनीय इनपुट पैकेज स्थापना और कोड लोडिंग व्यवहार को प्रभावित कर सकता है।
इस मामले में, यह कर सकता था।
मैं यहां मेमोरी भ्रष्टाचार या केवल क्रैश बग की तलाश में नहीं था।
मजबूत लक्ष्य एक्सटेंशन और पैकेज-समाधान सतह था।
कोई भी सिस्टम जो:
करीबी जांच का हकदार है।
यह विशेष रूप से तब सच है जब डाउनस्ट्रीम उपभोक्ता उन पैकेज नामों को प्रोजेक्ट-स्थानीय डेटा से प्राप्त कर सकता है।
यह बिल्कुल वैसी जगह है जहां सामान्य कॉन्फ़िगरेशन चुपचाप एक सुरक्षा सीमा बन सकता है।
यह देखने के लिए सही जगह थी।
मैंने पहले generator-jhipster के माध्यम से व्यवहार को पुन: उत्पन्न किया।
महत्वपूर्ण पथ था:
.yo-rc.json एक ब्लूप्रिंट पैकेज घोषित करता हैइसका मतलब था कि एक सौम्य कमांड भी जैसे:
jhipster --help
अनुरोधित कमांड पूर्ण होने से पहले पैकेज इंस्टॉलेशन तक पहुँच सकता था।
यह एक वास्तविक विश्वास-सीमा विफलता है।
डाउनस्ट्रीम ट्रिगर ने इसे उजागर करने में मदद की, लेकिन असुरक्षित डिफ़ॉल्ट व्यवहार Yeoman में था।
बग सरल था।
yeoman-environment में, कमजोर विधि थी:
async installLocalGenerators(packages) {
const entries = Object.entries(packages);
const specs = entries.map(([packageName, version]) => `${packageName}${version ? `@${version}` : ''}`);
const installResult = await this.repository.install(specs);
const failToInstall = installResult.find(result => !result.path);
if (failToInstall) {
throw new Error(`Fail to install ${failToInstall.pkgid}`);
}
await this.lookup({ packagePaths: installResult.map(result => result.path) });
return true;
}
वह विधि कॉलर द्वारा प्रदान किए गए पैकेज नामों को सीधे इसके माध्यम से स्थापित करती थी:
this.repository.install(specs)
बिना पहले उपयोगकर्ता से पूछे।
यह मुख्य कमजोरी है।
क्योंकि पैकेज नामों को किसी विश्वसनीय स्रोत से आने की आवश्यकता नहीं है।
यदि कोई डाउनस्ट्रीम उपभोक्ता उन्हें हमलावर-नियंत्रित प्रोजेक्ट मेटाडेटा से प्राप्त करता है, तो शोषण श्रृंखला सीधी है:
यह सिर्फ "पैकेज इंस्टॉल हुआ" नहीं है।
यह अविश्वसनीय इनपुट है जो स्पष्ट सहमति सीमा के बिना पैकेज इंस्टॉलेशन सिंक में पार कर रहा है।
महत्वपूर्ण अंतर अविश्वसनीय इनपुट से मौन स्थापना है।
एक वास्तविक अंतर है:
वह अंतर तब और भी मायने रखता है जब पैकेज तुरंत बाद लोड करने योग्य हो जाता है।
मुद्दा यह नहीं था कि तृतीय-पक्ष जनरेटर मौजूद हैं।
मुद्दा यह था कि Yeoman ने कॉलर द्वारा प्रदान किए गए पैकेज नामों को उपयोगकर्ता की पुष्टि के बिना डिफ़ॉल्ट रूप से स्थापित करने योग्य माना।
यह असुरक्षित डाउनस्ट्रीम विश्वास धारणाओं को काफी खराब बनाता है।
यही कारण है कि फिक्स ने एक पुष्टि गेट जोड़ा।
मैंने दो स्तरों के प्रमाण का उपयोग किया क्योंकि उन्होंने मूल कारण और वास्तविक डाउनस्ट्रीम प्रभाव दोनों का प्रदर्शन किया।
पहला प्रमाण अपरिवर्तित generator-jhipster का उपयोग करता था।
मैंने एक प्रोजेक्ट बनाया जिसमें एक रूट .yo-rc.json था जो एक ब्लूप्रिंट पैकेज को संदर्भित करता था जो पहले से स्थापित नहीं था, फिर चलाया:
jhipster --help
इसके कारण JHipster ने हेल्प पूर्ण होने से पहले लापता ब्लूप्रिंट को Yeoman के स्थानीय जनरेटर इंस्टॉलेशन फ्लो में पास कर दिया।
महत्वपूर्ण परिणाम था:
इसने वास्तविक ट्रिगर स्थिति को स्पष्ट रूप से स्थापित किया।
दूसरे प्रमाण में एक नियंत्रित स्थानीय रजिस्ट्री और एक पैकेज का उपयोग किया गया जो आयात-समय के दुष्प्रभावों को सुरक्षित रूप से प्रदर्शित करने के लिए डिज़ाइन किया गया था।
यह मायने रखता था क्योंकि मैं मजबूत कहानी दिखाना चाहता था:
यह सबसे मजबूत साक्ष्य श्रृंखला थी क्योंकि इसने मुद्दे को आगे बढ़ाया:
"अप्रत्याशित स्थापना प्रयास"
और इसमें:
"इंस्टॉल प्लस डाउनस्ट्रीम कोड-लोडिंग पथ वास्तव में पहुंच योग्य है"
यह वह बिंदु है जहां विश्वास-सीमा विफलता को खारिज करना बहुत कठिन हो जाता है।
पहला PoC मौन स्थापना व्यवहार साबित करता है।
दूसरा PoC साबित करता है कि वह व्यवहार क्यों मायने रखता है।
यह विभाजन महत्वपूर्ण था।
एक रिपोर्ट जो यहीं रुक जाती है:
"एक पैकेज स्थापित किया जा सकता है"
एक ऐसी रिपोर्ट से कमजोर है जो दिखाती है:
यह पूरी कहानी है।