FlawOpen

flawopen.com/Teardowns/cve-2026-71416-headroom-websocket-origin-hijacking

● CVE-2026-71416 · CVSS 8.8 · उच्च
सुरक्षा अनुसंधान · FlawOpen

CVE-2026-71416: Headroom WebSocket Origin हाइजैक

Headroom ने WebSocket Origin की जाँच नहीं की; खोली गई साइट प्रॉक्सी से LLM अनुरोध भेज सकती थी। 0.35.0 या नए संस्करण पर जाएँ।

💡 आसान भाषा में (ELI5)

रिसेप्शन पर आने वाले का पहचान-पत्र जाँचे बिना उसे निजी सेवा-काउंटर तक जाने दिया जाता है। Origin वही पहचान-पत्र है: सहेजी गई API कुंजी इस्तेमाल करने वाला चैनल खोलने से पहले प्रॉक्सी को इसकी जाँच करनी चाहिए।

इस पेज के मुख्य शब्द

WebSocket
HTTP Upgrade अनुरोध से शुरू होने वाला लगातार द्विदिश कनेक्शन, जिसमें दोनों ओर संदेश भेजे जा सकते हैं।
Origin हेडर
ब्राउज़र द्वारा भेजा गया स्कीम, होस्ट और पोर्ट, जो अनुरोध शुरू करने वाले पेज की पहचान करता है। WebSocket हैंडशेक पर सर्वर को अपनी भरोसा-नीति लागू करनी होती है; CORS हेडर इस जाँच का विकल्प नहीं हैं।
CSWSH
Cross-Site WebSocket Hijacking: अविश्वसनीय साइट किसी पहुँच योग्य सेवा से WebSocket खोलती है और सेवा शुरू करने वाले Origin की जाँच नहीं करती।
परिवेश में उपलब्ध क्रेडेंशियल
प्रोसेस को पहले से उपलब्ध रहस्य, जैसे पर्यावरण चर में API कुंजी, जिसे क्लाइंट की अपनी कुंजी के बिना अनुरोध में इस्तेमाल किया जा सकता है।
CWE-1385
WebSocket में Origin सत्यापन का अभाव: एंडपॉइंट यह नहीं जाँचता कि संचार का स्रोत अनुमत है या नहीं।

फ्रेमवर्क मैपिंग

मूल कारण विश्लेषण (Root Cause)

Headroom का /v1/responses WebSocket हैंडलर हैंडशेक के Origin की जाँच से पहले ब्राउज़र कनेक्शन स्वीकार करता था। इसके बाद प्रॉक्सी अपने पर्यावरण से OPENAI_API_KEY लेकर upstream अनुरोध में जोड़ सकता था। ब्राउज़र की same-origin नीति अपने आप JavaScript को किसी अन्य पहुँच योग्य होस्ट पर WebSocket शुरू करने से नहीं रोकती; ब्राउज़र सामान्यतः Origin भेजता है और सर्वर को अपनी नीति से बाहर के Origin अस्वीकार करने चाहिए। इसलिए शोषण के लिए पीड़ित ब्राउज़र से असुरक्षित Headroom प्रॉक्सी तक पहुँच और प्रॉक्सी में उपयोगी क्रेडेंशियल या एकीकरण होना आवश्यक है। सलाह के अनुसार स्वीकार किया गया कनेक्शन मनमाने LLM अनुरोध भेज सकता है। होस्ट पर कमांड चलना इस बात पर निर्भर है कि अनुरोध कॉन्फ़िगर किए गए कमांड चलाने वाले टूल का उपयोग कर सकता है; केवल हेडर-जाँच की कमी से यह अपने आप नहीं होता। CNA 0.35.0 से पुराने संस्करणों को प्रभावित बताता है, जबकि GitHub सलाह के पैकेज मेटाडेटा में 0.23.0 है। 0.35.0 या नए संस्करण पर जाएँ और स्थापित संस्करण सत्यापित करें।

हमले का चरण-दर-चरण प्रवाह

चरण 1

प्रॉक्सी के पास upstream अधिकार हैं

Headroom प्रोसेस में OPENAI_API_KEY के रूप में OpenAI कुंजी हो सकती है; ब्राउज़र क्लाइंट को कुंजी भेजने की आवश्यकता नहीं है।

चरण 2

ब्राउज़र अविश्वसनीय पेज खोलता है

यदि ब्राउज़र Headroom WebSocket एंडपॉइंट तक पहुँच सकता है, तो पेज का स्क्रिप्ट कनेक्शन का प्रयास कर सकता है। ब्राउज़र हैंडशेक में पेज का Origin शामिल करता है।

चरण 3

कमज़ोर हैंडलर Origin नीति के बिना कनेक्शन स्वीकार करता है

प्रभावित हैंडलर अविश्वसनीय Origin अस्वीकार किए बिना websocket.accept() तक पहुँचता है। same-origin नीति सर्वर-साइड WebSocket प्राधिकरण नहीं है।

चरण 4

प्रॉक्सी प्रमाणीकृत अनुरोध आगे भेजता है

Headroom अनुपस्थित upstream Authorization हेडर को पर्यावरण से भर सकता है। हमलावर-नियंत्रित पेज प्रॉक्सी के अधिकार से अनुरोध करा सकता है; प्रभाव टूल, क्रेडेंशियल, नेटवर्क पहुँच और उपयोगकर्ता क्रिया पर निर्भर है।

चरण 5

फिक्स रूटिंग से पहले निषिद्ध Origin रोकता है

अपस्ट्रीम पैच सत्र स्वीकारने और आगे भेजने से पहले Origin जाँचता है। ब्राउज़र Origin डिफ़ॉल्ट रूप से loopback तक सीमित हैं, स्पष्ट Origin कॉन्फ़िगर किए जा सकते हैं और निषिद्ध कनेक्शन 1008 कोड से बंद होता है।

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

सलाह में handle_openai_responses_ws() और websocket.accept() से पहले जाँच न होने की बात है। अपस्ट्रीम commit c632023 _is_allowed_websocket_origin() जोड़ता है और routing से पहले निषिद्ध Origin रोकता है। बिना Origin वाले native clients चलते रहते हैं, ब्राउज़र Origin डिफ़ॉल्ट रूप से loopback तक सीमित हैं, और HEADROOM_WS_ORIGINS या HEADROOM_CORS_ORIGINS से स्पष्ट Origin दिए जा सकते हैं। यह संक्षिप्त उदाहरण बदली हुई भरोसा-सीमा दिखाता है; सहायक फ़ंक्शन पूरे शामिल नहीं हैं। अपस्ट्रीम regression tests अनुपस्थित, loopback, remote, malformed और स्पष्ट रूप से कॉन्फ़िगर किए Origin जाँचते हैं।

सोर्स अंश: headroom/proxy/handlers/openai.py

कमज़ोर कार्यान्वयन
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
    # कमज़ोर रूप: origin सत्यापन से पहले ब्राउज़र सत्र स्वीकार करना।
    await websocket.accept()
    await self._relay_responses_session(websocket)
सुरक्षित और सुदृढ़ फ़िक्स
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
    ws_headers = dict(websocket.headers)
    if not _is_allowed_websocket_origin(ws_headers):
        logger.warning(
            "event=websocket_origin_not_allowed origin=%r",
            _header_get(ws_headers, "origin"),
        )
        await websocket.close(code=1008, reason="origin not allowed")
        return

    # केवल नीति-अनुमोदित ब्राउज़र सत्र ही upstream रूटिंग तक पहुँचता है।
    await websocket.accept()
    await self._relay_responses_session(websocket)

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत