ทำไม AI Agent ถึงยังทำงานต่อแม้พนักงานจะลาออกไปแล้ว
ลองจินตนาการว่าในทีมของคุณมี AI Agent (โปรแกรมปัญญาประดิษฐ์ที่ทำงานแทนคน) คอยช่วยจัดการข้อมูลให้เพื่อนร่วมงานคนหนึ่งอยู่ แต่จู่ๆ เพื่อนคนนั้นต้องลาออกไปกะทันหัน คุณจัดการลบชื่อเขาออกจากระบบบริษัทแล้ว แต่เจ้า AI ตัวนั้นก็ยังก้มหน้าก้มตาทำงานต่อไปเหมือนไม่มีอะไรเกิดขึ้น
เหตุผลที่มันยังทำงานอยู่ เพราะระบบส่วนใหญ่ใช้สิ่งที่เรียกว่า Access Token (กุญแจดิจิทัลที่ใช้ยืนยันตัวตน) ซึ่งเปรียบเสมือนบัตรผ่านเข้าตึก เมื่อบัตรถูกออกไปแล้ว แม้คนถือบัตรจะถูกไล่ออกไปจากระบบหลัก แต่บัตรใบนั้นก็ยังใช้งานได้จนกว่าจะหมดอายุตามเวลาที่กำหนดไว้
นี่คือช่องโหว่ที่โปรแกรมเมอร์มือใหม่มักมองข้าม เพราะเรามักคิดว่าแค่สั่งลบข้อมูลในฐานข้อมูล (ที่เก็บข้อมูลหลักของระบบ) ทุกอย่างจะจบลงทันที แต่ความจริงแล้วระบบรักษาความปลอดภัยแบบ OAuth (มาตรฐานการตรวจสอบสิทธิ์ที่นิยมใช้กันทั่วโลก) ทำงานแยกส่วนกันระหว่าง "การตรวจสอบสิทธิ์" และ "การใช้งานจริง"
ทำความรู้จักกับ Access Token และช่องโหว่ของระบบ
Access Token ไม่ใช่การเช็กชื่อกับฐานข้อมูลทุกครั้งที่ใช้งาน แต่มันคือ "เอกสารรับรองที่ลงนามแล้ว" เปรียบเหมือนตั๋วหนังที่คุณซื้อมาแล้ว แม้โรงหนังจะประกาศปิดกิจการไปแล้ว แต่ตั๋วในมือคุณก็ยังเป็นกระดาษที่มีตราประทับถูกต้องอยู่ดี ระบบจึงยอมให้ผ่านเข้างานได้ตามปกติ
เมื่อเราใช้ Kinde (เครื่องมือจัดการผู้ใช้งานและระบบล็อกอิน) ในการดูแลบัญชีผู้ใช้ การสั่งระงับสิทธิ์ในหน้า Dashboard (หน้าจอควบคุมระบบ) จะมีผลแค่ในฐานข้อมูลของ Kinde เท่านั้น มันไม่ได้ส่งสัญญาณไปบอก AI Agent ที่กำลังถือตั๋วใบเดิมอยู่ให้หยุดทำงานทันที
นี่คือสาเหตุที่ทำให้เกิด "ช่องว่างด้านความปลอดภัย" ขึ้นมา เพราะระบบไม่ได้ตรวจสอบความสดใหม่ของสิทธิ์ผู้ใช้งานในทุกๆ ขั้นตอนการทำงานจริง หากเราไม่สร้างกลไกมาดักจับเหตุการณ์เหล่านี้ เจ้า AI ก็จะทำงานต่อจนกว่าตั๋วของมันจะหมดเวลาไปเอง ซึ่งอาจกินเวลานานหลายชั่วโมงหรือหลายวัน
ใช้ Webhooks เพื่อดักจับการเปลี่ยนแปลงสถานะ
วิธีแก้ปัญหาคือเราต้องทำให้ระบบของเรา "ตื่นตัว" อยู่เสมอ โดยใช้ Webhooks (ระบบแจ้งเตือนอัตโนมัติเมื่อเกิดเหตุการณ์บางอย่าง) ทันทีที่มีการลบหรือระงับผู้ใช้งานใน Kinde ระบบจะส่งสัญญาณมาบอกแอปพลิเคชันของเราทันทีว่า "คนนี้ไม่อยู่แล้วนะ"
เราต้องสร้างฟังก์ชันเพื่อรับข้อมูลนี้มาบันทึกไว้ในฐานข้อมูลของเราเอง เพื่อให้แอปพลิเคชันรู้สถานะปัจจุบันของพนักงานแต่ละคน แทนที่จะเชื่อใจแค่ตั๋วที่ถืออยู่เพียงอย่างเดียว การทำแบบนี้จะช่วยปิดช่องว่างที่ AI Agent จะแอบทำงานต่อหลังจากพนักงานคนนั้นลาออกไปแล้ว
การเขียนโค้ดรับ Webhook ต้องระวังเรื่องความปลอดภัยด้วย เพราะใครก็อาจส่งข้อมูลปลอมมาหาเราได้ ดังนั้นเราต้องตรวจสอบให้แน่ใจว่าสัญญาณนั้นมาจาก Kinde จริงๆ โดยการเช็ก Signature (ลายเซ็นดิจิทัลเพื่อยืนยันแหล่งที่มา) ก่อนจะนำข้อมูลไปประมวลผลต่อ
สร้างระบบตรวจสอบสิทธิ์ก่อนสั่งงาน Agent
หัวใจสำคัญคือการสร้างฟังก์ชันคั่นกลางก่อนที่ AI จะลงมือทำงาน เราเรียกสิ่งนี้ว่า Seam (รอยต่อหรือจุดเชื่อมต่อ) ซึ่งจะทำหน้าที่เหมือนยามเฝ้าประตู ทุกครั้งที่ Agent จะเรียกใช้เครื่องมือใดๆ มันต้องผ่านด่านตรวจสอบนี้ก่อนเสมอ
เราจะกำหนดรายการคำสั่งที่อนุญาตให้ AI ทำได้ไว้ใน ACTION_REGISTRY เพื่อไม่ให้มันทำอะไรนอกเหนือจากที่กำหนด และทุกคำสั่งต้องถูกตรวจสอบสถานะของผู้ใช้ผ่าน decideAccess เสมอ เพื่อยืนยันว่าผู้ใช้งานคนนั้นยัง "Active" (ยังเป็นพนักงานอยู่) จริงๆ
// รายการคำสั่งที่อนุญาตให้ AI ทำงานได้
export const ACTION_REGISTRY = {
list_resources: { name: "list_resources", destructive: false },
write_resource: { name: "write_resource", destructive: true },
};
// ฟังก์ชันตัดสินใจว่าจะอนุญาตให้ทำหรือไม่
export function decideAccess(userStatus) {
if (userStatus === "active") return "allow";
return "refuse"; // ถ้าไม่อยู่ในสถานะ active ให้ปฏิเสธทันที
}
ในโค้ดชุดนี้ เราสร้าง ACTION_REGISTRY เพื่อระบุว่าคำสั่งไหนทำอะไรได้บ้าง จากนั้น decideAccess จะรับค่าสถานะผู้ใช้มาตัดสินใจ หากไม่ใช่สถานะที่ถูกต้อง ระบบจะส่งค่า refuse (ปฏิเสธ) ออกไปทันที
ผลลัพธ์ที่ได้คือ ไม่ว่า AI จะพยายามสั่งงานอะไรก็ตาม ถ้าผู้ใช้คนนั้นถูกระงับสิทธิ์ไปแล้ว ระบบจะตีกลับคำสั่งนั้นทันที ทำให้ AI หยุดทำงานในวินาทีที่ได้รับคำสั่งปฏิเสธ ไม่มีการทำงานค้างคาอีกต่อไป
จุดที่มือใหม่มักพลาดในการจัดการระบบความปลอดภัย
ความผิดพลาดที่พบบ่อยที่สุดคือการ "เชื่อใจ" ข้อมูลเก่าที่เก็บไว้ใน localStorage (พื้นที่เก็บข้อมูลบนเบราว์เซอร์) หรือใน Session (ข้อมูลการใช้งานชั่วคราว) มากเกินไป จนลืมตรวจสอบความสดใหม่ของข้อมูลก่อนใช้งานจริงทุกครั้ง
อีกจุดคือการลืมเช็กเวลาของ Webhook หากสัญญาณการแจ้งเตือนเกิดความล่าช้าหรือเป็นข้อมูลเก่าที่ถูกดักจับมาส่งใหม่ (Replay Attack) ระบบของคุณอาจจะปิดกั้นผู้ใช้งานผิดคนได้ ดังนั้นการตรวจสอบ Timestamp (เวลาที่เกิดเหตุการณ์) จึงเป็นเรื่องที่ห้ามละเลยเด็ดขาด
สุดท้ายคือการเขียนโค้ดตรวจสอบที่ซับซ้อนเกินไปจนจัดการยาก แนะนำให้แยกส่วนการตัดสินใจ (Logic) ออกจากส่วนการทำงาน (Execution) ให้ชัดเจน เหมือนกับตัวอย่าง decideAccess ที่เราทำไว้ข้างต้น เพื่อให้แก้ไขหรือปรับปรุงกฎความปลอดภัยในอนาคตได้ง่ายขึ้น
สรุป: การสร้างระบบที่ปลอดภัยเริ่มจากความใส่ใจ
การจัดการ Auto-Revoke (การยกเลิกสิทธิ์อัตโนมัติ) ไม่ใช่เรื่องไกลตัวสำหรับโปรแกรมเมอร์ แต่เป็นทักษะพื้นฐานที่แสดงถึงความรับผิดชอบต่อซอฟต์แวร์ที่เราสร้าง การเข้าใจว่าระบบสื่อสารกันอย่างไรผ่าน Webhooks และการมีด่านตรวจสอบก่อนสั่งงาน Agent คือสิ่งที่ทำให้แอปของคุณมีความเป็นมืออาชีพ
ลองนำแนวคิดนี้ไปปรับใช้กับโปรเจกต์ที่คุณกำลังทำอยู่ เช่น หากคุณทำแอปจัดการงาน ให้ลองเพิ่มขั้นตอนเช็กสิทธิ์ทุกครั้งก่อนบันทึกข้อมูลเข้าฐานข้อมูล การฝึกฝนเช่นนี้จะทำให้คุณมองเห็นภาพรวมของระบบความปลอดภัยได้ชัดเจนขึ้น และเป็นรากฐานที่ดีในการก้าวไปเป็นนักพัฒนาซอฟต์แวร์ที่เก่งกาจ
จำไว้ว่าในฐานะโปรแกรมเมอร์ เราไม่ได้แค่เขียนโค้ดให้มันทำงานได้เท่านั้น แต่เราต้องเขียนให้มันทำงานได้อย่างปลอดภัยและถูกต้องในทุกสถานการณ์ แม้ในวันที่พนักงานคนนั้นไม่ได้เป็นส่วนหนึ่งของทีมเราแล้วก็ตาม ขอให้สนุกกับการเขียนโค้ดและสร้างระบบที่แข็งแกร่งครับ
ที่มา: How to Auto-Revoke a Claude Agent's Access When a User Is Offboarded With Kinde Webhooks — DEV Community