ถ้าโมเดลอยากยึดเครื่องที่รันมันเอง มันไม่ต้องแฮ็กอะไรเลย — แค่พ่นโทเคนให้ parser ของ vLLM เป็นคนทำแทน
เวลาพูดถึงความปลอดภัยของ LLM เรามักคิดถึงสองอย่าง — prompt injection กับ sandbox ของเครื่องมือที่เอเจนต์เรียกใช้ แต่มีชั้นหนึ่งที่อยู่ระหว่างกลางและแทบไม่มีใครมองในฐานะ attack surface: ตัว inference engine เอง
25 สิงหาคม 2026 บทความจาก boydkane.com ตั้งข้อสังเกตที่คมมาก — ระหว่างโมเดลกับแอปพลิเคชันของคุณ มีซอฟต์แวร์ตัวหนึ่งที่ต้อง แปลลำดับโทเคนดิบให้กลายเป็นโครงสร้างที่ใช้ได้ ไม่ว่าจะเป็นข้อความแชท reasoning block หรือ tool call พร้อมอาร์กิวเมนต์ ซอฟต์แวร์ตัวนั้นคือ vLLM, SGLang และเพื่อน ๆ
และถ้า parser ตัวนั้นมีบั๊ก สิ่งที่โมเดลพ่นออกมาก็เลิกเป็นข้อมูล แล้วกลายเป็นคำสั่ง
ทำไม parser ของ inference engine ถึงเป็นเป้าที่อ่อนแอ
เหตุผลที่บทความยกมาคือ ความซับซ้อนที่โตขึ้นเรื่อย ๆ เอนจินสมัยใหม่ต้องรองรับสถาปัตยกรรมโมเดลกว่า 200 แบบ chat template หลากหลายรูปแบบ และระบบ tool-calling ที่แต่ละตระกูลโมเดลออกแบบไม่เหมือนกัน อย่างที่บทความเขียนไว้ว่า “parsing an arbitrary token sequence into a fully fledged chat…is not trivial, and the exact process often differs between LLMs. This complexity creates more opportunities for bugs.”
ผลคือแต่ละตระกูลโมเดลมักมี parser เฉพาะของตัวเองในโค้ดเบสของเอนจิน — และ parser พวกนี้เขียนขึ้นเพื่อ “ให้ใช้งานได้” ภายใต้แรงกดดันด้านความเร็วในการรองรับโมเดลใหม่ ไม่ได้เขียนภายใต้สมมติฐานว่า input ที่มันรับมาคือข้อมูลจากแหล่งที่ไม่น่าเชื่อถือ
ซึ่งเป็นสมมติฐานที่ผิด เพราะโมเดลควบคุมสิ่งที่ตัวเองพ่นออกมาได้เต็มที่ และเนื้อหาที่โมเดลพ่นก็ถูกกำหนดทิศทางได้จากคนที่ป้อน prompt เข้าไป
หลักฐานว่ามันเกิดขึ้นมาแล้วจริง: CVE-2025-9141
จุดที่ทำให้บทความนี้ไม่ใช่แค่การจินตนาการ คือช่องโหว่ที่เคยเกิดขึ้นจริงใน vLLM
CVE-2025-9141 (GHSA-79j6-g2m3-jgfw) มีชื่อทางการว่า “vLLM has remote code execution vulnerability in the tool call parser for Qwen3-Coder”:
| รายการ | รายละเอียด |
|---|---|
| CVSS | 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| แพ็กเกจ | pip vllm |
| เวอร์ชันที่ได้รับผลกระทบ | >= 0.10.0, < 0.10.1.1 |
| เวอร์ชันที่แก้แล้ว | 0.10.1.1 |
| วันที่ประกาศ | 20 ส.ค. 2025 |
กลไกตรงไปตรงมาจนน่าตกใจ — tool parser ของ Qwen3-Coder มีฟังก์ชันช่วยชื่อ convert_param_value ที่ทำหน้าที่แปลงค่าพารามิเตอร์ให้เป็นชนิดข้อมูล Python ที่ถูกต้อง และใน fallback path ถ้าค่าที่ได้ไม่ใช่ชนิดมาตรฐานและ decode เป็น JSON ไม่ได้ โค้ดจะเรียก eval() ใส่ค่านั้น
เงื่อนไขที่ทำให้โจมตีได้คือ เปิด tool calling ไว้, ระบุ parser เป็น qwen3_coder และชนิดของพารามิเตอร์ไม่ได้ถูกประกาศไว้ชัดเจนหรือระบบไม่รู้จัก — เมื่อนั้นผู้ใช้ที่ authenticate แล้วสามารถรันโค้ดอะไรก็ได้บนเซิร์ฟเวอร์ ถ้าเขาทำให้โมเดลส่งโค้ดนั้นมาเป็นอาร์กิวเมนต์ของ tool call
ต้องพูดให้ชัด: ช่องโหว่นี้ถูกแก้ไปแล้วตั้งแต่ปี 2025 และบทความก็ไม่ได้แนบ proof of concept ของการโจมตีแบบใหม่ สิ่งที่มันทำคือใช้เคสนี้เป็นหลักฐานว่ารูปแบบบั๊กแบบนี้เกิดขึ้นได้จริงในโค้ดเบสที่คนใช้กันเป็นล้าน แล้วชี้ว่า SGLang ก็มีความซับซ้อนในระดับเดียวกัน
ทางลดความเสี่ยงที่เสนอไว้
ข้อเสนอในบทความมีสามข้อหลัก:
- แยกเครื่อง — ให้ GPU กับตัว token parser อยู่คนละเครื่อง เพื่อให้การหลุดของ parser ไม่เท่ากับการยึดเครื่องที่มีข้อมูลและสิทธิ์
- จำกัดสิทธิ์ของ host และปฏิบัติกับ ทุกอย่างที่ออกมาจาก GPU ในฐานะข้อมูลที่ไม่น่าเชื่อถือ — ไม่ใช่ output ที่เชื่อได้เพราะ “มันมาจากโมเดลของเราเอง”
- red-team ตัว inference engine เอง ในฐานะซอฟต์แวร์ที่รับ untrusted input ไม่ใช่แค่ infra ที่รันโมเดล
มุมมอง AI Curator
ข้อเสนอ “แยก GPU กับ parser ออกคนละเครื่อง” ในทางปฏิบัติแทบไม่มีใครทำ เพราะมันแลกมาด้วย latency และความซับซ้อนที่ทีมส่วนใหญ่รับไม่ไหว แต่ข้อ 2 กับ 3 เป็นเรื่องที่ทำได้จริงตั้งแต่วันนี้ และผมคิดว่าข้อ 2 คือหัวใจ
เพราะจุดบอดที่แท้จริงคือ สมมติฐานเรื่องความไว้ใจ ทีมที่ self-host มักคิดว่า “โมเดลนี้เราโหลดมาเอง รันบนเครื่องเราเอง เราคุมทุกอย่าง” ซึ่งเป็นความรู้สึกที่ถูกในเชิงข้อมูลรั่ว แต่ผิดในเชิง supply chain — น้ำหนักโมเดลที่โหลดมาจาก Hugging Face คือ artifact จากคนอื่น และ output ของมันคือข้อมูลที่คนภายนอกกำหนดทิศทางได้ผ่าน prompt ในสายตาของ parser มันไม่ต่างจาก request ที่เข้ามาจากอินเทอร์เน็ต
เรื่องนี้เกี่ยวข้องกับผู้อ่านไทยและ SEA มากกว่าที่คิด เพราะเหตุผลที่คนแถบนี้เลือก self-host vLLM แทนการเรียก API มักเป็นเรื่อง PDPA และข้อกำหนดว่าข้อมูลต้องไม่ออกนอกประเทศ — องค์กรจำนวนไม่น้อยจึงยก vLLM ขึ้นบนเซิร์ฟเวอร์ในองค์กร ต่อกับฐานข้อมูลภายใน เปิด tool calling แล้วถือว่าจบเรื่องความปลอดภัย ทั้งที่เพิ่งย้าย attack surface จากคลาวด์ของผู้ให้บริการมาไว้ในเครือข่ายตัวเอง โดยที่ทีมที่ดูแลอาจไม่ได้มองมันเป็นซอฟต์แวร์ที่ต้องแพตช์ตามรอบด้วยซ้ำ
สิ่งที่ควรทำจริง ๆ ในสัปดาห์นี้มีสามอย่างและไม่ยากเลย: ตรวจเวอร์ชัน vLLM/SGLang ที่รันอยู่ในโปรดักชัน แล้วเทียบกับ advisory ที่ประกาศไปแล้ว, ดูว่าใช้ tool parser ตัวไหนอยู่ และพารามิเตอร์ของ tool ที่ประกาศไว้มีชนิดข้อมูลครบหรือไม่ (เคสนี้ทริกเกอร์ตรงชนิดที่ไม่ถูกประกาศพอดี) และ อย่ารัน inference server ด้วยสิทธิ์ที่กว้างกว่าที่จำเป็น — โดยเฉพาะอย่ารันเป็น root ในคอนเทนเนอร์ที่ mount ข้อมูลจริงเข้าไป
บทเรียนที่ใหญ่กว่าคือ เรากำลังเพิ่มความสามารถให้เอเจนต์เร็วกว่าที่เราทบทวนว่าใครไว้ใจใครในสถาปัตยกรรม ทุกครั้งที่เพิ่ม tool calling, structured output หรือ reasoning channel ใหม่ เราก็เพิ่ม parser อีกตัวที่ต้องแยกแยะ “ข้อมูล” ออกจาก “คำสั่ง” ให้ถูก — ซึ่งเป็นปัญหาที่วงการซอฟต์แวร์แก้ไม่หมดมาสามสิบปีแล้วในชื่อ SQL injection และ deserialization bug
แหล่งข่าว
อ่านเพิ่มในหมวด งานวิจัย
Anthropic ให้ Claude สร้างชุดข้อมูลที่ดูไร้พิษภัยแต่ทำโมเดลเบี้ยว ซ่อนในเรื่องเลี้ยงผึ้งและมวยปล้ำ จนผ่านระบบตรวจที่คล้ายของจริง
ทีม Alignment ของ Anthropic ให้ Claude ปีนหาชุดข้อมูล fine-tune ที่หลบ monitor ได้ ผลคือซ่อนพฤติกรรมในงานเขียนแนวบทบาทสมมติ และโมเดลที่เทรนแล้วนำไปใช้ในบุคลิกตัวเอง ผลซ้ำได้บน Qwen 3.6 27B แต่การทดลองเอื้อฝ่ายโจมตีมากและไม่ได้สะท้อนโมเดลที่ใช้งานจริง
Memdoor ทำซ้ำ GVS5H ได้: ทีม Qwen3.8-27B ห้าตัวตามทัน Fable 5 บนโจทย์ LiveCodeBench Hard แต่ผู้ทำบอกเองว่า 'เท่า' ไม่ใช่ 'ชนะ'
Memdoor ปล่อย workflow team-solve ที่เขียนวิธี GVS5H เป็น YAML ล้วนและทำคะแนน 9.8/10 บน LiveCodeBench Hard 10 ข้อ เทียบกับ 8.0 ของ Fable 5 แบบเรียกครั้งเดียว แต่ตัวอย่างเล็กและมีข้อจำกัด ส่วนงานวิจัยต้นฉบับชี้ว่าวิธีนี้ไม่ได้ช่วยทุกโมเดล
QwenPU รัน LLM ซ้อนใน LLM ด้วยหน่วยเวกเตอร์ที่คอมไพล์ลงในน้ำหนัก Qwen3.5-4B ส่วน bootgpt ทำให้เครื่อง 386 บูตเข้าโมเดลภาษาโดยไม่มี OS
ผู้สร้าง Qwenputer ปล่อย QwenPU เมื่อ 31 ต.ค. รัน stories260K ของ Karpathy บนหน่วยเวกเตอร์ที่คอมไพล์ลงในน้ำหนัก Qwen3.5-4B ลดเหลือ 53,000 trace token ต่อหนึ่ง token เรื่องเล่า วันเดียวกัน bootgpt ใส่โมเดล int8 ขนาด 11.5KB ให้บูตบนเครื่อง 386 โดยไม่มี OS