ตู้เซิร์ฟเวอร์มีท่อหลายเส้นผ่านสลักตรวจสอบ แต่สายสีอำพันหนึ่งเส้นเลี่ยงสลักเข้าสู่ห้อง process

Langflow CVE-2026-105697 คะแนน 9.9: MCP stdio config เปิดทางรันคำสั่งบน host

พี่โชว์Engineering

ผู้ดูแล Langflow ควรตรวจเวอร์ชันทันทีครับ GHSA-w794-rj3p-xv45 หรือ CVE-2026-105697 เป็นช่องโหว่ OS command injection ในการตั้งค่า MCP stdio server ได้คะแนน CVSS 9.9 ระดับ Critical กระทบแพ็กเกจ langflow ตั้งแต่ 1.1.2 จนก่อน 1.10.3 และแก้ครบใน 1.10.3 กับสาย 1.11 ขึ้นไป

ปัญหาไม่ได้อยู่ที่ protocol MCP อย่างเดียว แต่อยู่ที่ boundary ซึ่งรับ command, args และ environment จาก config แล้วนำไปเปิด process บนเครื่องที่รัน Langflow ก่อนรุ่นแก้ เส้นทางบางช่วงห่อคำสั่งผ่าน shell และไม่ได้บังคับ policy ที่ execution sink ทำให้ผู้ใช้ที่เข้าถึงการตั้งค่า MCP หรือ flow บางรูปแบบเปลี่ยน config เป็นคำสั่งระบบได้ บทความนี้ไม่ใส่ payload exploit; ทีมป้องกันไม่จำเป็นต้องทดลองรันคำสั่งอันตรายเพื่อพิสูจน์ว่าอยู่ในช่วงเสี่ยง

สรุป 30 วินาที

  • langflow ตั้งแต่ 1.1.2 จนก่อน 1.10.3, langflow-base ตั้งแต่ 0.1.2 จนก่อน 0.10.3 และ lfx ก่อน 1.10.3 อยู่ใน affected range ตาม advisory
  • ผลกระทบคือรันคำสั่งบน Langflow host ด้วยสิทธิ์ของ process Langflow เมื่อระบบพยายามเชื่อม MCP stdio server
  • รุ่น 1.9.0 เพิ่ม validation ที่ REST model แต่ยังมีเส้นทาง embedded flow/tweak ไปถึง execution sink โดยไม่ผ่าน policy จึงยังไม่ใช่ fix ครบ
  • 1.10.3 ย้าย validation ไปใช้ร่วมกันทุก entry point, ตรวจซ้ำก่อน spawn และเลิกห่อผ่าน shell; 1.11 เพิ่ม hardening สำหรับ multi-tenant ต่อ
  • ค่า LANGFLOW_AUTO_LOGIN=true ที่ออกแบบเพื่อ development ทำให้ exposed default instance บางแบบออก token โดยไม่ต้องมีบัญชี จึงขยายความเสี่ยง; ปิด auto-login และห้ามเปิดตรงสู่อินเทอร์เน็ต
  • หลังอัปเดตยังต้อง pin package ของ npx/uvx, จำกัด custom code, filesystem, network และ secret เพราะ allowlist command ไม่เท่ากับ sandbox

ทำไมเรื่องนี้เกี่ยวกับคุณ

Langflow เป็นเครื่องมือประกอบ flow ของ AI ที่มักเชื่อม API key, database, vector store, cloud credential และ repository เดียวกัน หาก process ถูกสั่งรันคำสั่งได้ ผลกระทบอาจไม่หยุดที่ container นั้น ผู้โจมตีอาจอ่าน secret ที่ process เห็น, แก้ flow, เรียก network ภายใน หรือขยับไปบริการอื่นตามสิทธิ์ ambient

MCP stdio server ดูเหมือน plugin แต่เชิงระบบมันคือ process ลูกที่รันบน host เหมือนจ้างช่างเข้าบ้าน ถ้า config ระบุได้ทั้งโปรแกรมและ argument แล้วประตูอนุญาตทุกชื่อ คนที่แก้ใบสั่งงานได้ก็ไม่ได้แค่ “เลือกเครื่องมือ” เขาเลือกได้ว่าจะเปิด process อะไร การแสดง error ว่า MCP start ไม่สำเร็จก็ไม่ช่วย หากคำสั่งถูกเปิดไปก่อน handshake

ความเสี่ยงสูงขึ้นในระบบ multi-tenant หรือ instance ที่เปิดให้นักพัฒนาหลายทีมสร้าง flow แม้ผู้ใช้จะไม่ใช่ admin ช่องโหว่นี้มี privileges required ระดับ Low ตาม advisory เพราะ authenticated non-admin บางเส้นทางก็ใช้ได้ และเมื่อ auto-login เปิดบน instance ที่เข้าถึงจากภายนอก barrier ของบัญชีอาจหายไปอีกชั้น

ทำงานยังไง: ประตูตรวจหน้าร้าน แต่สายไฟลัดเข้าห้องเครื่อง

ก่อน 1.9.0 config MCP stdio จากหน้าตั้งค่าหรือ component สามารถกำหนดคำสั่งและ argument โดยไม่มี allowlist ที่เพียงพอ เส้นทางเปิด process บางรุ่นสร้าง command string แล้วส่งผ่าน shell หมายความว่า shell metacharacter และ interpreter option กลายเป็นพื้นผิวโจมตี

รุ่น 1.9.0 เพิ่ม validator ที่ MCPServerConfig ฝั่ง API จึงปิดช่อง “Add MCP Server” ที่ผ่าน model นั้น แต่ execution sink ยังไม่บังคับ policy เดียวกัน Config ที่ฝังใน flow หรือส่งเป็น tweak สามารถเดินคนละทาง เปรียบเหมือนห้างติดเครื่องสแกนที่ประตูหน้า แต่ประตูส่งของด้านหลังยังต่อเข้าห้องเครื่องโดยตรง การบอกว่า “มี validation แล้ว” จึงไม่พอ ต้องตรวจทุก entry point ที่ไปถึง sink

รุ่น 1.10.3 รวม policy ในจุดกลางและบังคับทั้ง API, flow execution และก่อน spawn process พร้อมเปลี่ยนจาก shell wrapper เป็น direct execution หลังแยก argument การตรวจใกล้ sink สำคัญเพราะไม่ต้องหวังว่าผู้เรียกทุกตัวจำ validation ได้ และช่วยลดความต่างเมื่อมี entry point ใหม่ในอนาคต

อย่างไรก็ดี allowlist ที่ยังรองรับ package runner เช่น npx หรือ uvx อาจดาวน์โหลด/รัน package ได้ตาม config หากไม่ pin package และจำกัดรายการ Advisory จึงแนะนำ LANGFLOW_MCP_SERVER_ALLOWED_PACKAGES และ hardening mode เพิ่มใน multi-tenant รวมถึงจำกัด custom code ในรุ่นที่รองรับ

NVD และ GitLab Advisory Database ช่วยให้ระบบ vulnerability management จับ CVE/affected package ได้ ส่วน matrix และรายละเอียด fix ต้องยึด advisory ต้นทางกับ release 1.10.3 แล้วตรวจเวอร์ชันที่ติดตั้งจริง

เงินและผลกระทบ

ค่าเสียหายขึ้นกับสิทธิ์ของ Langflow process ถ้ารันเป็น root หรือ mount Docker socket, cloud credential, home directory และ shared volume ผลอาจขยายมาก หากรันเป็น user จำกัดใน container read-only, network egress ปิด และไม่มี long-lived secret blast radius จะเล็กลง แต่ไม่เป็นศูนย์ เพราะ flow/data ใน scope นั้นยังถูกอ่านหรือแก้ได้

การอัปเดตอาจมี compatibility cost กับ custom components และ MCP config จึงควรทำ inventory และ canary ก่อน แต่การเลื่อน patch โดยเปิด public endpoint ทิ้งไว้มีความเสี่ยงสูงกว่า ทีมที่ยังเปลี่ยนรุ่นไม่ได้ต้องปิด auto-login, จำกัด network ด้วย VPN/firewall, ปิด MCP stdio/custom code เท่าที่ทำได้ และใช้ compensating control ชั่วคราวพร้อมวันหมดอายุ

หลัง incident อาจต้อง rotate API keys, database passwords, OAuth tokens และ cloud credentials ที่ process เข้าถึงได้ ตรวจ outbound connection, child process, file change และ flow/config audit ย้อนหลัง การอัปเดต package อย่างเดียวไม่ลบ persistence หรือ secret ที่ถูกขโมยไปแล้ว

สิ่งที่ยังไม่ชัดและแหล่งข่าวพูดไม่ตรงกัน

Advisory ระบุผู้รายงานพบ internet-facing servers ที่เสี่ยง แต่ไม่ได้ยืนยันในหน้าต้นทางนี้ว่ามี exploitation in the wild ของ CVE นี้กี่เหตุการณ์ อย่าเอาสถิติจาก CVE Langflow ตัวอื่นมาปะปน CVE-2026-105697 มีแก่นที่ MCP stdio config และ affected range เฉพาะของมัน

คำว่า fixed ใน 1.9.0 อาจปรากฏในบริบท REST vector เพราะ PR นั้นปิดช่องหนึ่งจริง แต่ advisory อธิบายว่าเส้นทาง execution sink ยังไม่ครบจน 1.10.3 สองข้อความไม่ขัดกันหากระบุ scope แต่จะขัดทันทีเมื่อสรุปสั้นว่า “1.9.0 ปลอดภัยแล้ว” ทีมต้องใช้ fixed version ของ advisory ปัจจุบัน ไม่ใช้ PR แรกเป็นเกณฑ์ patch

คะแนน 9.9 เป็น base score ไม่ได้บอก exposure ของ instance เรา ระบบหลัง firewall และไม่มี untrusted users อาจมีโอกาสโจมตีน้อยกว่า แต่ severity ของผลยังสูง ขณะเดียวกัน instance ที่เปิด auto-login ต่ออินเทอร์เน็ตมี barrier ต่ำกว่าค่า privileges required ทั่วไป การทำ risk exception ต้องแนบหลักฐาน network reachability, auth mode, process privileges และ compensating controls ไม่ใช่ลดคะแนนตามความรู้สึก

ยังไม่รู้จาก version string อย่างเดียวว่า image ถูก rebuild จริงหรือ deployment เก่ายังรันอยู่ ต้องตรวจ package ใน runtime, container digest, pod rollout และ process restart ที่ถูกต้อง โดยไม่ restart production นอก change plan นอกจากนี้ custom fork อาจ backport fix แต่ version ไม่ตรง ต้องมี commit/provenance และ test policy ที่ execution sink

แล้วเราควรทำอะไร

  1. ทำ inventory instance, package (langflow, langflow-base, lfx), container digest, exposure, auth mode และ owner โดยไม่รัน payload
  2. อัปเดตเป็น 1.10.3 หรือรุ่น 1.11+ ที่รองรับ แล้ว rebuild artifact จาก lockfile/provenance ที่เชื่อถือได้
  3. ตรวจว่า deployment ใช้ artifact ใหม่จริงและ config เก่าไม่เปิด auto-login; จำกัด admin/MCP endpoint หลัง VPN หรือ allowlist
  4. รัน regression ที่สร้าง MCP server จากรายการอนุญาต และยืนยันว่าคำสั่งนอก policy ถูกปฏิเสธทั้ง API, embedded flow และจุดก่อน spawn โดยใช้ harmless fixture ใน environment แยก
  5. pin package/digest ของ MCP server ปิด remote installer และ network เป็นค่าเริ่มต้น จำกัด filesystem กับ secret ให้เฉพาะงาน
  6. บน multi-tenant เปิด package allowlist, interpreter/docker hardening และจำกัด custom component/code interpreter ตามรุ่น
  7. ตรวจ log/process/file/network ย้อนหลังและ rotate secret เมื่อมี exposure หรือ indicator น่าสงสัย ติดต่อทีม incident response แทนการลบไฟล์เดียว

ทีมที่ใช้บริการ hosted ควรถามผู้ให้บริการเป็นลายลักษณ์อักษรว่ารันเวอร์ชันใด, patch เมื่อไร, auto-login เป็นอย่างไร, tenant isolation อยู่ตรงไหน และมี compromise assessment หรือไม่ คำตอบ “อัปเดตอัตโนมัติ” ยังไม่พิสูจน์ว่า workload ถูก rollout หรือ secret เก่าไม่รั่ว

Recap

  • langflow ตั้งแต่ 1.1.2 จนก่อน 1.10.3 ได้รับผล; เป้าหมายขั้นต่ำคือ 1.10.3
  • อย่านับ 1.9.0 ว่าแก้ครบ เพราะ sink/embedded path ยังมีช่อง
  • ปิด LANGFLOW_AUTO_LOGIN และห้ามเปิด instance ตรงสู่อินเทอร์เน็ต
  • ตรวจ package/runtime/container digest ไม่ดูแค่ source branch
  • pin MCP packages และจำกัด shell, filesystem, network, custom code, secret
  • ทดสอบ policy ด้วย harmless fixture ใน environment แยก ไม่รัน exploit บน production
  • ตรวจ compromise และ rotate secret เมื่อมี exposure
  • แยก CVE นี้จากช่องโหว่ Langflow รายการอื่นใน ticket และ evidence

บทเรียนใหญ่คือ validation ต้องอยู่ที่ execution sink ครับ ประตูหน้าที่แข็งแรงไม่ช่วยถ้ามีทางอื่นเดินถึง process launcher และเครื่องมือ agent/MCP ควรถูกออกแบบเหมือน code execution boundary ตั้งแต่วันแรก ไม่ใช่ plugin ธรรมดา