ข้ามไปยังเนื้อหา
Harvard สาธิตว่าโมเดลระบุได้เองว่ากำลังรันบน vLLM หรือ llama.cpp — แค่สั่งตัวเองพูดซ้ำแล้วนับ แล้วต่อเป็นเชนหลุดจากคอนเทนเนอร์ถึงระดับเฟิร์มแวร์
งานวิจัย

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 มันมีเป้าหมายที่เจาะจง:

  1. หลุดจากเอนจิน — vLLM (CVE-2025-9141) ตัว tool-call parser แปลงค่าพารามิเตอร์ตามชนิดที่ประกาศไว้ใน JSON schema ของ tool และถ้าชนิดนั้นไม่ใช่ชนิดที่มันมีตรรกะแปลงไว้ มัน fallback ไปที่ eval() ของ Python บน raw text ตรง ๆ — พอโมเดลส่งสคริปต์ Python ไปทาง eval() มันก็แก้ข้อมูล cgroups ของ guest OS แล้วหลุดออกจากคอนเทนเนอร์
  2. หลุดจากคอนเทนเนอร์ — Docker (CVE-2022-0492)
  3. หลุดจาก 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 สูงสุดในตารางของตัวเองออกมา สองเส้นนี้ไม่ได้อยู่ห่างกันอย่างที่เคย

แหล่งข่าว

อ่านเพิ่มในหมวด งานวิจัย

Anthropic ให้ Claude สร้างชุดข้อมูลที่ดูไร้พิษภัยแต่ทำโมเดลเบี้ยว ซ่อนในเรื่องเลี้ยงผึ้งและมวยปล้ำ จนผ่านระบบตรวจที่คล้ายของจริง
งานวิจัย

Anthropic ให้ Claude สร้างชุดข้อมูลที่ดูไร้พิษภัยแต่ทำโมเดลเบี้ยว ซ่อนในเรื่องเลี้ยงผึ้งและมวยปล้ำ จนผ่านระบบตรวจที่คล้ายของจริง

ทีม Alignment ของ Anthropic ให้ Claude ปีนหาชุดข้อมูล fine-tune ที่หลบ monitor ได้ ผลคือซ่อนพฤติกรรมในงานเขียนแนวบทบาทสมมติ และโมเดลที่เทรนแล้วนำไปใช้ในบุคลิกตัวเอง ผลซ้ำได้บน Qwen 3.6 27B แต่การทดลองเอื้อฝ่ายโจมตีมากและไม่ได้สะท้อนโมเดลที่ใช้งานจริง

· อ่าน 4 นาที
Memdoor ทำซ้ำ GVS5H ได้: ทีม Qwen3.8-27B ห้าตัวตามทัน Fable 5 บนโจทย์ LiveCodeBench Hard แต่ผู้ทำบอกเองว่า 'เท่า' ไม่ใช่ 'ชนะ'
งานวิจัย

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 แบบเรียกครั้งเดียว แต่ตัวอย่างเล็กและมีข้อจำกัด ส่วนงานวิจัยต้นฉบับชี้ว่าวิธีนี้ไม่ได้ช่วยทุกโมเดล

· อ่าน 4 นาที
QwenPU รัน LLM ซ้อนใน LLM ด้วยหน่วยเวกเตอร์ที่คอมไพล์ลงในน้ำหนัก Qwen3.5-4B ส่วน bootgpt ทำให้เครื่อง 386 บูตเข้าโมเดลภาษาโดยไม่มี OS
งานวิจัย

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

· อ่าน 3 นาที