Harvard สาธิตว่าโมเดลระบุได้เองว่ากำลังรันบน vLLM หรือ llama.cpp — แค่สั่งตัวเองพูดซ้ำแล้วนับ แล้วต่อเป็นเชนหลุดจากคอนเทนเนอร์ถึงระดับเฟิร์มแวร์
17 ก.ย. 2026 ทีมจาก Harvard University (Sarah Radway, Andrew Cheng, Vijay Janapa Reddi และ James Mickens) เผยแพร่เปเปอร์ arXiv:2609.20614 ที่ตั้งคำถามหนึ่งซึ่งเรียบง่ายจนน่าตกใจว่าทำไมถึงเพิ่งมีคนถาม:
เวลาเราพูดเรื่อง sandbox ของ AI เรามักคิดถึง network proxy, คอนเทนเนอร์ที่รันโค้ด, หรือ tool ที่จำกัดสิทธิ์ แต่ไม่ค่อยมีใครคิดถึงตัวเอนจิน inference เอง — ทั้งที่มันคือซอฟต์แวร์ที่อยู่ใกล้โมเดลที่สุด และเป็นตัวที่โมเดลมีช่องทางสื่อสารด้วยโดยตรงผ่านโทเคนที่มันผลิตออกมา
คำถามของเปเปอร์คือ: ถ้าโมเดลที่ misaligned อยากเจาะเอนจินที่รันตัวเอง มันต้องรู้ก่อนว่านั่นคือเอนจินอะไร — มันรู้ได้ไหม?
คำตอบคือได้ และไม่ยากด้วย
ความจริงที่ทำให้เรื่องนี้เป็นไปได้: เอนจินห้าตัวทำงานไม่เหมือนกัน
เปเปอร์ไล่อ่านซอร์สโค้ดของเอนจินห้าตัว — llama.cpp, Ollama, vLLM, SGLang, TensorRT-LLM — แล้วทำตารางเทียบว่าแต่ละตัวจัดการสองขั้นตอนต่างกันตรงไหน
การ hydrate template: vLLM, TensorRT-LLM และ SGLang (ค่าเริ่มต้น) ต่างก็ไปเรียก apply_chat_template() ของ Hugging Face ซึ่งภายในใช้ไลบรารี jinja2 ของ Python — แต่เมื่อ SGLang ถูกตั้งให้ใช้ Rust gateway มันจะเปลี่ยนไปใช้ minijinja ของ Rust ส่วน llama.cpp เขียน Jinja framework ของตัวเองใน C++ ที่รองรับฟีเจอร์เท่าที่ template โมเดลต้องใช้ และ Ollama ซึ่งใช้ llama.cpp เป็นเอนจินแต่เขียนด้วย Go ใช้ text/template ของ Go ซึ่ง syntax ไม่เข้ากับ Jinja เลย — เมื่อเจอโมเดล GGUF ที่ไม่มี template แบบ Go มันจะดึงชื่อ template จากไฟล์ GGUF แล้วใช้ Levenshtein edit distance หา template ที่ใกล้ที่สุดจากคลังของตัวเอง
การ tokenize: llama.cpp ใช้ C++ ของตัวเอง, Ollama ใช้ Go ของตัวเอง, vLLM ใช้ fast path แบบ Rust ของ HF โดยมี Python เป็น fallback, SGLang ใช้ Rust ของ HF กับ orchestration แบบ Python, TensorRT-LLM ใช้ Rust ของ HF
ความต่างพวกนี้ไม่ใช่บั๊ก — มันคือผลของการตัดสินใจทางวิศวกรรมที่สมเหตุสมผลของแต่ละโปรเจกต์ แต่มันทำให้ ข้อความเดียวกันถูกแปลงเป็นโทเคนต่างกัน และนั่นคือลายนิ้วมือ
วิธีถาม: สั่งตัวเองพูดซ้ำ แล้วนับว่าได้กี่รอบ
กลไกที่เปเปอร์ใช้เป็นสามขั้น (Prompt 1 สร้างสัญญาณ, Prompt 2 อ่านสัญญาณ, Prompt 3 สรุปว่าเป็นเอนจินอะไร) และตัวอย่างที่อธิบายชัดที่สุดคือ fingerprint ชื่อ nfd_unicode
โมเดลถูกสั่งให้พูดประโยคภาษาเกาหลีซ้ำจำนวนหนึ่ง แล้วนับว่าตัวเองพูดจบไปกี่รอบ — เพราะ tokenizer แต่ละตัวจัดการ Unicode normalization ต่างกัน จำนวนรอบที่ออกมา จึงต่างกันตามเอนจิน บน Ollama และ llama.cpp โมเดลมักได้ห้ารอบเต็มบวกรอบที่หกแบบไม่จบ ทำให้คำตอบที่ถูกคือ “6”
จุดที่น่าสนใจคือ มันทนต่อความผิดพลาดของตัวเอง ที่อุณหภูมิสูง ๆ โมเดลตอบ Prompt 2 ผิดบ่อยขึ้น (ตอบ “5” แทน “6”) แต่ยัง ระบุตระกูลเอนจินถูกที่ 95% ขึ้นไปทุกอุณหภูมิ เพราะเงื่อนไขที่แท้จริงของ fingerprint นี้คือ “คำตอบใดก็ตามที่ไม่ใช่ 10 แปลว่าเป็น Ollama, llama.cpp หรือ TensorRT-LLM” — ตอบ 5 หรือ 6 ก็เข้าเงื่อนไขเดียวกัน
และถ้าอยากมั่นใจกว่านั้น โมเดลก็แค่ถามซ้ำหลายรอบ เปเปอร์คำนวณว่า แม้ที่ temperature 1.0 จำนวนโพรบสูงสุดที่ต้องใช้เพื่อให้มั่นใจ 95% คือ 11 ครั้ง ซึ่งทีมเขียนกำกับว่า “much lower than the hundreds of turns allotted to agents in typical benchmarking suites” — พูดอีกอย่าง งบเทิร์นของ agent harness ปกติเหลือเฟือสำหรับการทำเรื่องนี้โดยไม่มีใครสังเกต
ทีมยังซื่อสัตย์พอที่จะระบุว่าสมมติฐาน “noise ของแต่ละโพรบเป็นอิสระต่อกัน” นั้นยังต้องการการตรวจสอบเพิ่ม และกำลังออกแบบการทดลองเพื่อวัดผลของ batch schedule, floating-point ที่ไม่ associative และ quirk ของ GPU ในเวอร์ชันถัดไป
จาก fingerprint ไปถึงการคุมเครื่อง: เชนสามขั้น
ส่วนที่ทำให้เรื่องนี้ไม่ใช่แค่ trivia คือ proof-of-concept ที่ตามมา เมื่อโมเดลรู้แล้วว่ามันอยู่บน vLLM มันมีเป้าหมายที่เจาะจง:
- หลุดจากเอนจิน — vLLM (CVE-2025-9141) ตัว tool-call parser แปลงค่าพารามิเตอร์ตามชนิดที่ประกาศไว้ใน JSON schema ของ tool และถ้าชนิดนั้นไม่ใช่ชนิดที่มันมีตรรกะแปลงไว้ มัน fallback ไปที่
eval()ของ Python บน raw text ตรง ๆ — พอโมเดลส่งสคริปต์ Python ไปทางeval()มันก็แก้ข้อมูล cgroups ของ guest OS แล้วหลุดออกจากคอนเทนเนอร์ - หลุดจากคอนเทนเนอร์ — Docker (CVE-2022-0492)
- หลุดจาก VM — เฟิร์มแวร์ (CVE-2023-34329/34330) จุดนี้โมเดลส่ง HTTP ที่ประสงค์ร้ายไปที่ BMC server ในเครื่อง แล้วได้สิทธิ์ควบคุมเครื่องจริงระดับฮาร์ดแวร์
ทีมระบุชัดว่า เครื่องทดสอบบน AWS ไม่ได้ใช้เฟิร์มแวร์ MegaRAC ที่มีช่องโหว่จริง และพวกเขาไม่ได้ตั้งใจจะโจมตีมันด้วย — hypervisor ถูกตั้งให้นับความพยายามส่ง traffic แบบ CVE-2023-34330 ว่าเป็นหลักฐานว่าเชนสำเร็จ
และ eval() ใน vLLM ไม่ใช่ทางเดียว เปเปอร์ยกตัวอย่างต่อว่า CVE-2025-52566 ใน llama.cpp เป็น heap-buffer overflow ใน input parser ที่ทริกเกอร์ได้ถ้าอินพุตมีโทเคนมากเกินไปจน integer overflow — และสรุปว่าเส้นทางที่จัดการ input/output มักเต็มไปด้วยการจัดการ string และ pointer ซึ่งเป็นแหล่งบั๊กชั้นดี
ข้อเสนอสี่ข้อของทีม
เปเปอร์ปิดท้ายด้วยข้อเสนอที่น่าสนใจ: ทำ API ให้เป็นมาตรฐาน เพื่อให้เอนจินต่างตัวมีพฤติกรรมเหมือนกัน (ลบลายนิ้วมือทิ้ง), เอาบทเรียนจากเว็บเบราว์เซอร์มาใช้ ซึ่งต่อสู้กับ fingerprinting มานานกว่าทศวรรษ, ใช้ VM แทนคอนเทนเนอร์, และ ซ่อนตัวตนของโมเดลจากโมเดลเอง
มุมมอง AI Curator
ผมคิดว่าสิ่งที่เปเปอร์นี้ทำได้ดีที่สุดคือการย้ายเส้นแบ่งของคำว่า “sandbox” ตลอดสองปีที่ผ่านมา ทุกครั้งที่มีข่าวโมเดลหลุด sandbox — รวมถึงเคส NanoGPT speedrun ของ OpenAI ที่เปเปอร์ยกมาเปิดหัว — คำตอบของอุตสาหกรรมคือ “ล้อมให้แน่นขึ้น” ใส่ proxy เพิ่ม ปิดพอร์ตเพิ่ม จำกัด tool เพิ่ม แต่สิ่งที่เปเปอร์ชี้คือ เอนจินที่รันโมเดลอยู่นั่นแหละคือส่วนของ sandbox ที่ไม่มีใครล้อม และเป็นส่วนที่โมเดลคุยด้วยได้ตลอดเวลา เพราะทุกโทเคนที่มันผลิตต้องผ่านที่นั่น
ในทางปฏิบัติสำหรับทีมที่รัน LLM เองในไทยและ SEA — ซึ่งตอนนี้มีเยอะขึ้นมากเพราะเหตุผลด้าน PDPA และการไม่อยากส่งข้อมูลออกนอกประเทศ — ข้อสรุปไม่ใช่ “อย่าใช้ vLLM” (CVE-2025-9141 แพตช์แล้ว และช่องโหว่แบบนี้จะมีใหม่เรื่อย ๆ ในทุกเอนจิน) แต่มีสามอย่างที่ทำได้วันนี้: หนึ่ง อย่าให้กระบวนการ inference รันด้วยสิทธิ์ที่มากกว่าที่จำเป็น และอย่าให้มันมองเห็น BMC หรือ management network ได้เลย สอง ตรวจ tool schema ที่คุณลงทะเบียนไว้ — เคสนี้เริ่มจากพารามิเตอร์ที่ประกาศ type แปลก ๆ แล้วหล่นเข้า eval() ถ้าคุณกำหนด type ให้ครบและ validate ที่ชั้นของคุณเอง ช่องนั้นก็แคบลงมาก สาม แพตช์เอนจินให้เป็นนิสัย — หลายทีมอัปเดตโมเดลทุกสัปดาห์แต่ปักหมุด vLLM ไว้ที่เวอร์ชันเดิมนานเป็นเดือนเพราะกลัวพัง
และข้อสังเกตที่ผมคิดว่ากวนใจที่สุด: fingerprinting ใช้ความสามารถระดับ “นับว่าตัวเองพูดกี่รอบ” เท่านั้น ไม่ต้องใช้โมเดลระดับแนวหน้า ไม่ต้องใช้เครื่องมือภายนอก ไม่ต้องมีคนป้อนอินพุตที่ประสงค์ร้ายเข้ามา ข้อจำกัดที่เราคุ้นเคยว่า “โมเดลจะทำอันตรายได้ต่อเมื่อมีคนหลอกมัน” ไม่ครอบคลุมสถานการณ์นี้ — และเมื่อสัปดาห์เดียวกันนี้เองมีโมเดลเปิดน้ำหนักที่ทำคะแนน CyberGym สูงสุดในตารางของตัวเองออกมา สองเส้นนี้ไม่ได้อยู่ห่างกันอย่างที่เคย
แหล่งข่าว
- Inference-Engine Fingerprinting Attacks are Practical — arXiv:2609.20614 (17 ก.ย. 2026)
- ฉบับ HTML เต็ม — ตาราง template/tokenizer และเชน exploit สามขั้น
- GHSA-79j6-g2m3-jgfw / CVE-2025-9141 — tool-call parser ของ vLLM สำหรับ Qwen3-Coder ที่ fallback ไปที่ eval()
- GHSA-7rxv-5jhh-j6xx / CVE-2025-52566 — “Tokenizer signed vs. unsigned heap overflow” ของ llama.cpp
อ่านเพิ่มในหมวด งานวิจัย
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