
librsvg के VectorFreed use-after-free RCE चेन (CVE-2026-96889) का दस्तावेज़ीकरण करता है, जिसमें librsvg, Next.js और Satori के लिए एक SVG जनरेटर PoC और उपचार मार्गदर्शन शामिल है।
यह दस्तावेज़ "VectorFreed" प्रस्तुत करता है, एक भेद्यता श्रृंखला जो librsvg में मेरे (@rafabd1) द्वारा खोजे गए use-after-free से शुरू होती है (CVE-2026-96889)। एक Node.js/Sharp/libvips बिल्ड में, इस बग ने कमांड निष्पादन को जन्म दिया। यह बग, अब तक अनुप्रयोगों में पुष्ट किए गए पथ, और अब उपलब्ध समाधानों को कवर करता है।
एक SVG XInclude के माध्यम से एक अन्य SVG को शामिल कर सकता है। भेद्य पथ में, librsvg एक शामिल दस्तावेज़ को पार्स करना शुरू करता है जबकि libxml2 अभी भी बाहरी दस्तावेज़ में एक एंटिटी का विस्तार कर रहा होता है। यदि शामिल SVG उसी नाम की एक एंटिटी घोषित करता है, तो librsvg पहली एंटिटी को प्रतिस्थापित और मुक्त कर देता है। libxml2 अभी भी उसका एक पॉइंटर रखता है।
जब शामिल पार्स समाप्त होता है, तो libxml2 उस पुराने पॉइंटर के साथ आगे बढ़ता है। उस समय तक वह मेमोरी पहले से ही किसी और चीज़ की हो सकती है, इसलिए बाद के लेखन इसे दूषित कर सकते हैं। क्रैश इसका एक परिणाम है। अन्य मामलों में, इसने कमांड निष्पादन को भी जन्म दिया।
हमलावर को librsvg तक पहुँचने के लिए तैयार किए गए SVG मार्कअप की आवश्यकता होती है। यह तब हो सकता है जब कोई अनुप्रयोग SVG फ़ाइल स्वीकार करता है, लेकिन यह तब भी हो सकता है जब अनुप्रयोग उपयोगकर्ता इनपुट से SVG बनाता है। केवल निर्भरता ट्री में कहीं librsvg का उपयोग करना एक शोषणीय पथ स्थापित नहीं करता; छवि रेंडर होने पर इनपुट को एक प्रभावित बिल्ड तक पहुँचना चाहिए।
हमने जिस Next.js रूट का परीक्षण किया, उसने SVG अपलोड के बजाय टेक्स्ट स्वीकार किया। इसने उस टेक्स्ट को ImageResponse के Node.js संस्करण के लिए एक इनलाइन SVG के अंदर रखा। Satori में एक अलग एस्केपिंग बग ने टेक्स्ट को जनरेट किए गए SVG मार्कअप को बदलने की अनुमति दी। Sharp/libvips ने फिर उस SVG को librsvg को पास किया। Vercel ने Next.js पथ को CVE-2026-94545 के रूप में ट्रैक किया। ImageResponse का Edge संस्करण इस पथ से प्रभावित नहीं है। यहाँ एक संक्षिप्त Next.js प्रतिकृति है।
एक दूसरा Next.js रूट Image Optimization API के माध्यम से उसी librsvg बग तक पहुँचा। जब API द्वारा हमलावर-नियंत्रित छवि स्रोत स्वीकार किया गया, तो एक तैयार की गई छवि फ्रेमवर्क की SVG अस्वीकृति को पार कर सकती थी और बाद में Sharp/libvips द्वारा SVG के रूप में संभाली जा सकती थी। इसने Satori या ImageResponse का उपयोग किए बिना glibc-आधारित Linux पर अनधिकृत अनुरोधों के लिए अपस्ट्रीम मेमोरी करप्शन को उजागर किया।
Vercel ने इस पथ को GHSA-2464-fhr4-w9xw के रूप में प्रकाशित किया, अपस्ट्रीम CVE-2026-96889 के अंतर्गत। सलाहकार इसे 9.5 के CVSS स्कोर के साथ Critical रेट करता है।
Ghost का एक अलग पथ है। एक स्टाफ उपयोगकर्ता, जिसमें एक Contributor भी शामिल है, अपने नियंत्रित साइट के लिए एक बुकमार्क कार्ड बना सकता था। कार्ड छवि को संसाधित करने से फिर Ghost सर्वर पर कमांड चल सकते थे। Ghost ने इसे CVE-2026-105642 के रूप में प्रकाशित किया।
इस शोध के दौरान, मैंने कई डाउनस्ट्रीम उत्पादों में प्रभावित इनपुट पथों की पहचान की और उनमें से कई में कमांड निष्पादन की पुष्टि की, जिसमें दोनों Next.js रूट और ऊपर दिया गया Ghost मामला शामिल है। वह इनपुट librsvg तक कैसे पहुँचता है, यह उत्पाद-दर-उत्पाद भिन्न होता है। यही कारण है कि एक अपस्ट्रीम इमेज पार्सर बग ऐसी जगहों पर प्रकट हो सकता है जो पहली नज़र में संबंधित नहीं लगतीं; हालिया libheif मामला एक और उदाहरण है। इसका मतलब यह नहीं है कि librsvg का उपयोग करने वाला हर उत्पाद दूरस्थ रूप से शोषणीय है।
ImageResponse): संस्करण 16.2.0 से 16.3.5 तक प्रभावित हैं जब कोई एप्लिकेशन हमलावर-नियंत्रित मानों को SVG सामग्री, एट्रिब्यूट्स, या स्टाइल्स में डालता है। 16.3.6 पर अपग्रेड करें।>= 10.0.0 <= 15.5.27 और > 16.0.0 <= 16.4.0 को प्रभावित के रूप में सूचीबद्ध किया गया है। 15.5.28 या 16.4.1 पर अपग्रेड करें। Sharp 0.35.5 या बाद के संस्करण में अपस्ट्रीम फिक्स शामिल है।यदि आप Sharp के प्रीबिल्ट बाइनरीज़ का उपयोग करते हैं, तो जाँचें कि आपके ऐप ने कौन सा @img/sharp-libvips-* पैकेज इंस्टॉल किया है। यह libvips और उसकी निर्भरताओं को बंडल करता है, जिसमें librsvg भी शामिल है। librsvg की सिस्टम कॉपी को अपडेट करने पर आपका ऐप पुरानी कॉपी का उपयोग करता रह सकता है।
UAF PoC में कई इनपुट पाथ के लिए एक SVG जेनरेटर शामिल है और इसका उपयोग चेन की शुरुआत में use-after-free की जाँच के लिए किया जा सकता है।
EQSTLab Next.js ImageResponse RCE PoC अपने पिन किए गए Node.js/Sharp बिल्ड के लिए उस चेन का एक कार्यशील उदाहरण है। यह पेलोड को स्वचालित रूप से जेनरेट और भेजता है। एक कार्यशील एक्सप्लॉइट अब सार्वजनिक है, इसलिए जल्द से जल्द प्रभावित निर्भरताओं को अपडेट करें या इनपुट पाथ को मिटिगेट करें।
[!WARNING] इस चेन के लिए कोई सार्वभौमिक RCE PoC नहीं है। EQSTLab का उदाहरण अपने पिन किए गए बिल्ड को लक्षित करता है; अन्य लक्ष्यों के लिए अलग पेलोड की आवश्यकता हो सकती है। कमांड निष्पादन के लिए SVG
<foreignObject>पर निर्भर PoCs यहाँ वर्णित चेन को प्रदर्शित नहीं करते हैं।
अन्य लक्ष्यों पर प्रारंभिक सत्यापन के लिए, UAF PoC अधिक व्यावहारिक है। मैं आने वाले हफ्तों में तकनीकी राइट-अप भी प्रकाशित करूँगा, जिसमें UAF से कमांड निष्पादन तक के चरण और इस चेन पर पिछले महीने की रिसर्च को कवर करने वाला पोस्ट-मॉर्टम शामिल होगा।