Prompt injection โจมตี coding agent จากจุดใดบ้าง
ทำความเข้าใจจุดที่ผู้โจมตีแทรกข้อความใน coding agent บนเซิร์ฟเวอร์ ตั้งแต่ไฟล์และ pull request ถึง tool call พร้อมจัดลำดับการป้องกันที่ลดความเสียหายได้จริง
Prompt injection ต่อ coding agent คืออะไร
Prompt injection ต่อ coding agent อธิบายได้ง่าย ๆ ว่า ข้อความที่ agent อ่านจะถูกปฏิบัติเสมือนเป็นคำสั่งที่ agent ต้องทำตาม agent อาจเปิดไฟล์ ความคิดเห็นใน pull request เว็บเพจ หรือผลลัพธ์จาก tool call ข้อมูลทั้งหมดนี้จะมาถึงในรูปแบบข้อความเดียวกับคำขอของคุณ หากผู้โจมตีควบคุมข้อความส่วนใดส่วนหนึ่งได้ ผู้โจมตีก็กำลังเขียนข้อความลงใน session ของคุณ
ผลิตภัณฑ์ agent ในปัจจุบันทุกตัวมีคุณสมบัตินี้ model จะได้รับลำดับ token ชุดเดียว คำขอของคุณ system prompt เนื้อหาในไฟล์ และผลลัพธ์จาก tool จะถูกรวมเข้าด้วยกัน จากนั้น model จะคาดการณ์ว่าข้อความถัดไปควรเป็นอะไร รูปแบบนี้ไม่มี privilege bit กำกับ token แต่ละรายการ และไม่มีข้อมูลใดระบุว่าส่วนใดได้รับอนุญาตจากคุณ หรือส่วนใดมาจากไฟล์ README ของบุคคลอื่น
หน้านี้อธิบาย threat model ว่าข้อความที่ผู้โจมตีควบคุมสามารถเข้าถึง agent ที่ทำงานบนเซิร์ฟเวอร์ได้จากจุดใด ผู้โจมตีได้ความสามารถอะไรในแต่ละจุด และการป้องกันใดคุ้มค่ากับความพยายาม คำแนะนำด้าน containment ในคู่มืออื่นของเราจะมีความหมายก็ต่อเมื่อคุณเข้าใจก่อนว่ากำลังป้องกันอะไรไม่ให้เข้าถึง agent
เหตุใดโมเดลจึงไม่สามารถแยกเนื้อหาออกจากคำสั่งได้
การฝึกโมเดลช่วยลดปัญหาได้ แต่ไม่สามารถแก้ปัญหาได้ทั้งหมด โมเดลในปัจจุบันได้รับการฝึกให้ระมัดระวังข้อความที่ดึงมาใช้ และปฏิเสธความพยายามแบบตรงไปตรงมาหลายรูปแบบ การปฏิเสธเป็นเพียงความน่าจะเป็น ไม่ใช่กฎตายตัว ผู้โจมตีสามารถเปลี่ยนถ้อยคำ ลองซ้ำ และซ่อนข้อความไว้ในรูปแบบที่ไม่เคยมีใครเตรียมรับมือได้ โดยไม่มีข้อจำกัดว่าพวกเขาจะลองใช้ถ้อยคำได้กี่รูปแบบ
โครงการ OWASP GenAI จัดปัญหานี้ไว้ใน LLM01:2025 Prompt Injection และแบ่งออกเป็น 2 ประเภท Direct injection คือ prompt ของผู้ใช้ที่เปลี่ยนพฤติกรรมของโมเดล ส่วน indirect injection คือเนื้อหาภายนอก เช่น เว็บไซต์หรือไฟล์ ที่เปลี่ยนพฤติกรรมของโมเดลขณะที่โมเดลประมวลผลเนื้อหานั้น Indirect injection เป็นประเด็นสำคัญบนเซิร์ฟเวอร์ เพราะ agent อ่านข้อความมากกว่าที่คุณพิมพ์เองอย่างมาก
งานศึกษาที่เป็นระบบชิ้นแรกคือผลงานของ Greshake และคณะเรื่อง Not what you've signed up for (2023) ข้อสรุปที่ควรจดจำคือ เมื่อแอปพลิเคชันป้อนข้อความที่ดึงมาให้โมเดลซึ่งสามารถเรียกใช้เครื่องมือได้ การประมวลผลข้อความนั้นแทบไม่ต่างจากการเรียกใช้โค้ดโดยพลการ
เงื่อนไขที่ทำให้การอ่านกลายเป็นการถูกเจาะระบบ
การอ่านข้อความที่เป็นอันตรายไม่ก่อให้เกิดความเสียหายด้วยตัวมันเอง ความเสียหายต้องมีช่องทางออกจากเครื่อง
Simon Willison เรียกการผสมผสานนี้ว่า สามประสานร้ายแรง ในเดือน June 2025 เอเจนต์ที่มีข้อมูลส่วนตัว เข้าถึงเนื้อหาที่ไม่น่าเชื่อถือ และสามารถส่งข้อมูลออกไปได้ อาจถูกชักจูงให้ส่งข้อมูลส่วนตัวออกผ่านช่องทางดังกล่าว
coding agent บน VPS ของคุณมีเงื่อนไขเหล่านี้ครบตั้งแต่เริ่มต้น ข้อมูลส่วนตัวคือ source code, ไฟล์ .env, SSH keys และ shell history ของคุณ เนื้อหาที่ไม่น่าเชื่อถือคือ repository, page และผลลัพธ์จาก tool ทุกอย่างที่เอเจนต์อ่าน ช่องทางออกคือ git push, curl, npm publish, เนื้อหา pull request หรือลิงก์ที่แสดงใน terminal ซึ่งคุณคลิก
คุณไม่สามารถนำเงื่อนไขข้อที่สองออกได้ เพราะการอ่านข้อความที่ไม่น่าเชื่อถือคือหน้าที่ที่คุณมอบหมายให้เอเจนต์ ดังนั้นแนวทางป้องกันที่ใช้ได้จริงทั้งหมดจึงต้องจัดการกับอีก 2 เงื่อนไข
เมื่อข้อความที่ไม่น่าเชื่อถือไปถึง coding agent บนเซิร์ฟเวอร์
Repository ที่ agent กำลังทำงานอยู่
ทุกไฟล์ใน checkout คือ input ทั้งหมด ไม่ว่าจะเป็น comment ใน source code, README.md, changelog, test fixture, code ที่ vendor มา หรือไฟล์คำสั่งของ agent เอง ได้แก่ CLAUDE.md, AGENTS.md และไฟล์ที่เทียบเท่ากัน เมื่อสั่งให้ agent ทำความเข้าใจ codebase agent จะอ่านไฟล์เหล่านี้ เพราะนั่นคือสิ่งที่คุณสั่งให้ทำ
สิ่งที่ผู้โจมตีได้คือช่องทางเข้าถึงทุกคนที่ clone repository แล้วชี้ agent ไปยัง repository นั้น ไฟล์คำสั่งเป็นช่องทางที่ตรงที่สุด เพราะไฟล์เหล่านี้มีไว้ให้อ่านในฐานะคำสั่ง pull request ที่เพิ่มบรรทัดที่เป็นประโยชน์ 4 บรรทัดลงใน CLAUDE.md และเพิ่มอีก 1 บรรทัดเพื่อ redirect agent อาจเป็นการเปลี่ยนแปลงที่ผู้ตรวจสอบซึ่งเป็นมนุษย์อ่านผ่านไปอย่างรวดเร็ว
Issues, pull requests และ comment ในการ code review
ทุกสิ่งที่บุคคลภายนอกพิมพ์ลงใน tracker ได้ จะไปถึง agent ทันทีที่คุณสั่งให้ agent คัดกรอง ใน May 2025, Invariant Labs เผยแพร่ ข้อค้นพบเกี่ยวกับ GitHub MCP ที่มีลักษณะเช่นนี้พอดี agent ของ developer เข้าถึง repository สาธารณะ 1 แห่งและ repository ส่วนตัวหลายแห่ง ผู้โจมตีเปิด issue ใน repository สาธารณะ เมื่อ developer สั่งให้ agent ตรวจสอบ issue ที่ยังเปิดอยู่ agent อ่านเนื้อหาจาก repository ส่วนตัว แล้วเขียนเนื้อหานั้นลงใน pull request ฝั่งสาธารณะ
รายงานดังกล่าวอธิบายปัญหาด้านสถาปัตยกรรม ไม่ใช่ข้อบกพร่องของ code ใน MCP server agent ถือ access token ที่มีสิทธิ์กว้าง อ่านข้อมูลจาก inbox สาธารณะ และมีสิทธิ์เขียน ไม่มีการตั้งค่าผิดในความหมายทั่วไป นี่จึงเป็นปัญหาที่ต้องแก้ด้วยการจำกัดขอบเขตสิทธิ์ ไม่ใช่การแก้ patch
Web page ที่ agent fetch
Documentation, คำตอบใน forum, หน้าเว็บของ vendor และผลการค้นหา สิ่งใดก็ตามอาจมีข้อความที่เขียนถึง agent แทนที่จะเขียนถึงคุณ HTML ที่แปลงเป็น text เปิดพื้นที่ให้ผู้โจมตีเพิ่มขึ้น เพราะเนื้อหาที่ browser ไม่เคยแสดงก็ยังไปถึง model ได้
ผู้โจมตีได้การควบคุมในช่วงที่มีการเฝ้าดู agent น้อยที่สุด ไม่มีใครอ่านข้อความทั้งหมดของ page ที่ agent fetch ขณะค้นข้อมูล
MCP tool output
MCP (model context protocol) เป็นวิธีทั่วไปที่ agent ใช้เชื่อมต่อกับ external tool ผลลัพธ์จะกลับมาเป็น text และเข้าสู่ context window โดยตรง ในส่วนนี้มี attack surface 2 จุด ไม่ใช่ 1 จุด จุดแรกคือข้อมูลที่ tool ส่งกลับมา ซึ่งเห็นได้ชัด อีกจุดคือชื่อและคำอธิบายของ tool เอง ซึ่ง model อ่านเพื่อพิจารณาว่าจะเรียกใช้ tool เมื่อใด และ server ที่คุณไม่ได้ควบคุมอาจเปลี่ยนแปลงสิ่งใดสิ่งหนึ่งระหว่างการเรียกแต่ละครั้งได้
ผู้โจมตีที่แทรกข้อความลงใน output ของ tool หนึ่งได้ จะเข้าถึง tool อื่นทั้งหมดที่ agent มี นี่คือสาเหตุที่ injection ในสิ่งที่มีมูลค่าต่ำสามารถกลายเป็นตัวขับเคลื่อนสิ่งที่มีมูลค่าสูงได้
CI log, build output และ dependency metadata
npm install พิมพ์ข้อความจาก package ที่คุณไม่ได้เขียน test failure พิมพ์ assertion message จาก library ส่วน log ของ continuous integration (CI) job มี output จาก third party หลายพันบรรทัด เมื่อสั่งให้ agent แก้ build ที่ล้มเหลว agent จะอ่านข้อมูลทั้งหมด
ในกรณีนี้ผู้โจมตีได้เข้าถึง build machine ซึ่งโดยทั่วไปมี deploy credential และ registry token อีกทั้งมักได้รับความสนใจน้อยกว่า laptop】【。
สิ่งที่ผู้โจมตีได้รับจริง
ควรวางแผนรับมือผลลัพธ์ 4 รูปแบบ
การขโมยข้อมูลรับรอง สิ่งใดก็ตามที่ process ของ agent อ่านได้ล้วนอยู่ในขอบเขตความเสี่ยง ได้แก่ environment variables, ~/.aws/credentials, ~/.ssh, token ของ gh และไฟล์ config ของ Docker การส่งข้อมูลเหล่านี้ออกไปไม่จำเป็นต้องใช้ curl การ commit ไปยัง branch, คำอธิบายใน pull request, package ที่เผยแพร่ไปยัง registry หรือ DNS lookup สำหรับชื่อที่ผู้โจมตีควบคุม ล้วนทำให้ข้อมูลออกจากเครื่องได้
การเปลี่ยนแปลงโค้ดที่คุณอนุมัติ การเขียนโค้ดคือหน้าที่ของ agent ดังนั้นการทำให้ agent เขียนบรรทัดที่ผิดอย่างแนบเนียนจึงเป็นผลลัพธ์ที่ทำได้ง่ายที่สุด เช่น การเพิ่ม dependency หรือการเพิ่ม logging call ที่นำ token ไปไว้ใน log ซึ่งคุณส่งต่อไปยังที่อื่น
การคงอยู่ในระบบ ไฟล์ที่ถูกเขียนเพียงครั้งเดียวยังคงทำงานได้โดยไม่ต้องมี model เกี่ยวข้อง เช่น hook ใน .git/hooks, สคริปต์ postinstall ใน package.json, บรรทัดที่เพิ่มต่อท้ายไฟล์เริ่มต้นของ shell หรือบรรทัดเพิ่มเติมใน CLAUDE.md คำสั่งถัดไปจะเรียกใช้งานสิ่งนั้น
การเคลื่อนย้ายภายในเครือข่าย agent จะทำงานบนเครื่องที่คุณนำไปติดตั้ง หากเครื่องนั้นเชื่อมต่อไปยัง database ผ่าน loopback, บริการผู้ดูแลระบบภายใน, metadata service ของ cloud provider หรือ host อื่นใน private network สิ่งใดก็ตามที่ควบคุม agent ก็จะเข้าถึงปลายทางเหล่านั้นได้เช่นกัน
โหมดอนุมัติอัตโนมัติจะลบการตรวจสอบขั้นสุดท้าย
ในโหมดเริ่มต้น Claude Code จะขออนุญาตก่อนเรียกใช้คำสั่งหรือแก้ไขไฟล์ พรอมต์นี้คือการตรวจสอบโดยมนุษย์ที่คั่นอยู่ระหว่างช่องทางทั้งหมดข้างต้นกับการดำเนินการจริง โหมดที่ลบพรอมต์นี้จะลบการตรวจสอบดังกล่าวออกไปด้วย
เอกสารระบุไว้อย่างชัดเจนเกี่ยวกับ bypassPermissions: ให้ใช้เฉพาะในสภาพแวดล้อมที่แยกออกจากระบบอื่น เช่น container หรือ VM ซึ่ง Claude Code ไม่สามารถสร้างความเสียหายได้ Auto mode มีข้อจำกัดมากกว่า และอนุมัติการเรียกใช้เครื่องมือโดยอัตโนมัติ พร้อมการตรวจสอบความปลอดภัยเบื้องหลังเพื่อยืนยันว่าการดำเนินการสอดคล้องกับคำขอของคุณ การตรวจสอบเหล่านี้ช่วยตรวจจับปัญหาได้มาก แต่ยังคงเป็นการใช้ดุลยพินิจของโมเดลต่อผลลัพธ์ของโมเดล ดังนั้นควรมองว่าเป็นตัวกรอง ไม่ใช่ขอบเขตป้องกัน
ผู้ดูแลระบบสามารถลบการตรวจสอบทั้งสองรายการได้ ให้กำหนด permissions.disableBypassPermissionsMode หรือ permissions.disableAutoMode เป็น "disable" ในไฟล์ settings แล้วนำไฟล์นั้นไปไว้ใน managed settings เพื่อไม่ให้โปรเจกต์ที่ checkout แล้วเขียนทับได้ คู่มือของเราเรื่อง Claude Code auto mode และกฎ permission อธิบายว่ากฎแต่ละข้อมีผลที่ใด
แนวป้องกัน เรียงตามสิ่งที่ช่วยป้องกันได้
ไม่มีข้อใดเป็นการแก้ปัญหาโดยตรง แต่ละข้อจำกัดขอบเขตของสิ่งที่ agent ถือครอง หรือจำกัดสิ่งที่ agent ทำกับสิ่งนั้นได้
- เครื่องที่สามารถทำลายและสร้างใหม่ได้ เพื่อให้ server ที่ถูกเจาะเสียเวลาเพียง 1 ชั่วโมง แทนที่จะกลายเป็นเหตุการณ์ด้านความปลอดภัย
- Credential ที่แยกจากของคุณเอง จำกัดสิทธิ์ไว้กับ repository เดียว และมีอายุสั้น
- ไม่มี secret ที่มีอายุยาวอยู่ใน environment ที่คำสั่งของ agent สืบทอดมา
- การบังคับใช้จาก operating system กับ network egress และการเข้าถึงไฟล์ ซึ่งมีผลกับทุก process ที่ agent เริ่มทำงาน
- เปิด approval prompt ไว้สำหรับการเขียนข้อมูลและการเรียก network
- ใช้ hook เป็นแนวป้องกันแบบ deterministic สำหรับการกระทำเฉพาะที่คุณระบุได้
- อ่าน diff ก่อน merge
ลำดับมีความสำคัญ ข้อ 1 ถึง 4 ยังคงมีผลแม้ model จะถูก attacker ควบคุมทั้งหมด ส่วนข้อ 5 ถึง 7 ต้องอาศัยคนคอยตรวจสอบ ซึ่งเป็นสิ่งที่มักหยุดทำเมื่อ agent ทำงานเป็นเวลานาน
ให้ agent ทำงานบนเครื่องที่ทิ้งได้
VPS ที่มี checkout และ token ที่จำกัดสิทธิ์เพียง 1 รายการ มีมูลค่าน้อยกว่า laptop ที่เก็บ key ของคุณไว้มาก ให้ agent ทำงานด้วย user ที่ไม่มีสิทธิ์พิเศษเป็นของตัวเอง อย่าใช้ account ที่คุณ login อยู่ และอย่าใช้ root คู่มือของเราเกี่ยวกับ VM แบบทิ้งได้สำหรับ coding agent และ user ที่ใช้สิทธิ์น้อยที่สุดบน VPS อธิบายการตั้งค่า ส่วน การรัน Claude Code อย่างปลอดภัยบน VPS อธิบายรูปแบบการใช้งานประจำวัน
นำ secret ออกจาก environment
environment variable สามารถอ่านได้โดยทุก child process ซึ่งหมายถึงทุกคำสั่งที่ agent เรียกใช้ Claude Code sandbox สามารถ unset ตัวแปรที่ระบุชื่อไว้ก่อนแต่ละ sandboxed command ได้ บน Linux ต้องติดตั้ง package 2 รายการก่อน:
sudo apt-get install bubblewrap socatจากนั้นใน ~/.claude/settings.json:
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
},
"credentials": {
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "NPM_TOKEN", "mode": "deny" }
]
}
}
}รายการ deny จะ unset ตัวแปรนั้นก่อนที่แต่ละ sandboxed command จะทำงาน และ allowedDomains ใช้ระบุ host ที่อนุญาตให้ sandboxed command เชื่อมต่อได้ block credentials ต้องใช้ Claude Code v2.1.187 หรือใหม่กว่า โดยตรวจสอบเมื่อ August 2026 เรียกใช้ /sandbox ใน session เพื่อดูว่า layer ใดกำลังทำงานอยู่ และ dependency ใดขาดหาย การตัดสินใจว่า secret ใดจำเป็นต้องมีอยู่บนเครื่องนั้นจริง ๆ เป็นงานส่วนที่ใหญ่กว่า และ การเก็บ secret ให้พ้นจากการเข้าถึงของ AI agent อธิบายเรื่องนี้โดยละเอียด
ตัด network egress ที่ระดับ operating system
กฎ firewall ไม่สนใจว่า model ตัดสินใจอย่างไร ให้ agent ทำงานด้วย user agent โดยเฉพาะ แล้ว drop traffic ที่ user นั้นส่งออก:
table inet agentcage {
chain output {
type filter hook output priority filter; policy accept;
meta skuid "agent" ct state established,related accept
meta skuid "agent" oif lo accept
meta skuid "agent" counter drop
}
}วิธีนี้ทำให้ user agent ใช้งานได้เฉพาะ loopback ดังนั้น traffic ของ user จะต้องผ่าน proxy ที่รันอยู่บนเครื่องเดียวกัน และ proxy จะเป็นผู้ถือ hostname allowlist เมื่อ https_proxy ชี้ไปยัง proxy นั้น client จะส่งคำขอ CONNECT และ proxy จะทำ name lookup เอง ดังนั้น agent จึงไม่ต้องมี outbound DNS (domain name system) ของตัวเอง ตรวจสอบผลด้วย sudo nft list ruleset และดู counter ของกฎ drop เพิ่มขึ้นขณะที่ agent พยายามเชื่อมต่อไปยังสิ่งใหม่
เปิด SSH session สำรองไว้อีก 1 session ระหว่างแก้ไข firewall ตรวจสอบด้วยว่า container runtime จัดการกฎเหล่านี้อย่างไร Docker จะเขียน chain ของตัวเอง และ พอร์ต Docker ที่ publish สามารถ bypass ufw อธิบายสาเหตุของพฤติกรรมที่คาดไม่ถึงนี้
Hook: การตรวจสอบที่ model ไม่สามารถพูดโน้มน้าวให้ผ่านได้
Permission rule และ hook ถูกบังคับใช้โดย Claude Code ไม่ใช่ model เอกสารระบุไว้อย่างชัดเจนว่า instruction ใน prompt หรือ CLAUDE.md มีผลต่อสิ่งที่ Claude พยายามทำเท่านั้น และไม่ได้เปลี่ยนสิ่งที่ Claude Code อนุญาต ความแตกต่างนี้คือประโยชน์หลัก บรรทัดใน CLAUDE.md ที่ระบุว่า "ห้ามรัน curl" เป็นเพียงคำแนะนำที่ paragraph ซึ่งถูก inject เข้ามาสามารถโต้แย้งได้ ส่วน hook คือ process ที่คืนค่า exit code
ลงทะเบียน hook PreToolUse ใน .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/no-egress.sh"
}
]
}
]
}
}hook จะได้รับ tool call ในรูปแบบ JSON ผ่าน standard input ค่า exit code 2 จะ block call และแสดงเหตุผลจาก standard error ให้ Claude เห็น ค่า exit code 0 จะปล่อยให้ call ดำเนินต่อผ่าน permission flow ตามปกติ
#!/usr/bin/env bash
# PreToolUse: stdin holds the tool call, exit 2 blocks it.
cmd=$(jq -r '.tool_input.command // ""')
if printf '%s' "$cmd" | grep -qE '(^|[;&|]|\s)(curl|wget|nc|ncat)(\s|$)'; then
echo "Blocked: this repository does not allow outbound network commands." >&2
exit 2
fi
exit 0ส่วนที่ต้องยอมรับตามจริงคือ นี่เป็น denylist ที่ตรวจสอบ shell string และ denylist ของ shell string มีช่องโหว่ python3 -c สามารถเปิด socket ได้โดยไม่ใช้คำว่า curl ส่วน target แบบ make deploy สามารถซ่อน call เดียวกันไว้ลึกลงไปอีก 1 ระดับ ให้เขียน hook สำหรับข้อผิดพลาดที่คุณระบุได้ และวางขอบเขตที่คุณพึ่งพาจริงไว้ใน kernel หรือบน network
Permission deny rule มีข้อจำกัดด้านการจับคู่ที่ควรรู้ deny rule Read และ Edit ครอบคลุม file tool ของ Claude เอง และ file command ที่ Claude รู้จักใน Bash เช่น cat, head, tail และ sed แต่ไม่ครอบคลุม script ของ Python หรือ Node ที่เปิดไฟล์ด้วยตัวเอง Rule จะถูกประเมินตามลำดับ deny ก่อน จากนั้น ask แล้วจึง allow ดังนั้น deny rule จึงไม่สามารถมีข้อยกเว้นแบบ allowlist ได้
{
"permissions": {
"deny": [
"Read(.env)",
"Read(./secrets/**)",
"Bash(git push *)"
]
}
}เฝ้าดูสิ่งที่ออกจากเครื่อง และอ่าน diff
การทำงานของ agent จะสร้าง diff และ network call หลายรายการ ทั้งสองอย่างควรได้รับการตรวจสอบก่อน merge หรือ deploy ขั้นตอน security review แบบ self-hosted ที่ตรวจ diff จะตรวจพบการเปลี่ยนแปลงคนละประเภทกับการที่คนอ่านแบบกวาดตา ส่วน การรู้ว่า coding agent ส่งอะไรออกจากเครื่อง จะช่วยให้คุณทราบว่า traffic ปกติเป็นอย่างไร เพื่อให้คำขอที่ผิดปกติโดดเด่นขึ้นมา
สิ่งที่ยังแก้ไม่ได้
ปัจจุบันยังไม่มีการแยกเนื้อหาออกจากคำสั่งที่เชื่อถือได้อย่างสมบูรณ์ ระบบป้องกันทุกแบบที่มีให้ใช้งานจริงล้วนเป็นตัวกรองที่มีอัตราความผิดพลาด หรือเป็นการจำกัดผลกระทบที่อาจเกิดขึ้น ไม่มีส่วนใดใน stack ที่ระบุช่วงข้อความว่าเป็นข้อมูลซึ่งต้องไม่ปฏิบัติตามโดยเด็ดขาด
ตัวกรองช่วยลดความเสี่ยงได้ แต่ก็ล้มเหลวได้เช่นกัน ตัวจำแนกที่ตรวจจับความพยายามทำ prompt injection ได้เกือบทั้งหมด ยังคงต้องตรวจจับให้ถูกต้องทุกครั้ง ขณะที่ผู้โจมตีต้องทำสำเร็จเพียงครั้งเดียว ความไม่สมมาตรนี้ทำให้อัตราความสำเร็จที่ประกาศสำหรับระบบป้องกันเป็นเพียงจุดเริ่มต้นของความพยายามครั้งถัดไป ไม่ใช่การรับประกัน
งานที่มีแนวโน้มดีที่สุดอยู่ที่ระดับการออกแบบ ไม่ใช่ระดับ model CaMeL จาก Defeating Prompt Injections by Design (Debenedetti และคณะ, 2025) จะแยก control flow และ data flow จากคำขอที่เชื่อถือได้ก่อน เพื่อไม่ให้ข้อมูลที่ไม่เชื่อถือเปลี่ยนการทำงานของโปรแกรม จากนั้นจึงบังคับใช้การตรวจสอบ capability เมื่อมีการเรียกใช้ tools ตัวเลขของบทความเองจาก benchmark AgentDojo แสดงให้เห็นว่าการออกแบบนี้มีต้นทุนเท่าใด
The data behind this chart
[
{
"label": "Undefended agent",
"tasks_solved_pct": 84
},
{
"label": "CaMeL",
"tasks_solved_pct": 77
}
]Agent ที่ไม่มีการป้องกันทำงานสำเร็จ 84 เปอร์เซ็นต์ของ task ส่วน CaMeL ทำงานสำเร็จ 77 เปอร์เซ็นต์ พร้อม security guarantee ตัวเลขเหล่านี้เป็นตัวเลขที่บทความเผยแพร่สำหรับ benchmark เดียว และไม่ใช่การวัด workload ของคุณ ช่องว่างระหว่างตัวเลขทั้งสองโดยคร่าวคือราคาของการรับประกันที่ใช้งานได้จริงในปัจจุบัน
จนกว่าการออกแบบลักษณะนี้จะมีให้ใช้งานใน tools ที่คุณใช้เป็นประจำ ให้เตรียมรับว่า agent อาจถูก compromise ได้ในสักวันหนึ่ง และทำให้เหตุการณ์นั้นไม่ก่อความยุ่งยาก นี่คือเหตุผลทั้งหมดที่ควรใช้เครื่องที่ทิ้งได้, scoped credentials, ควบคุม egress และสร้างนิสัยตรวจสอบ diff
FAQ
ฉันหยุด prompt injection ได้หรือไม่ หากบอก agent ให้เพิกเฉยต่อคำสั่งในไฟล์
ไม่ได้ ข้อความนั้นอยู่ใน context window เดียวกับการโจมตี และมีน้ำหนักเท่ากับข้อความของผู้โจมตี Claude Code ระบุขอบเขตไว้อย่างชัดเจนว่า คำสั่งใน prompt หรือ CLAUDE.md กำหนดสิ่งที่ agent พยายามทำ และไม่ได้เปลี่ยนแปลงสิ่งที่เครื่องมืออนุญาต ให้ถือว่าไฟล์คำสั่งเป็นเพียงการระบุเจตนา และนำสิ่งที่ต้องพึ่งพาไปกำหนดไว้ในกฎ permission, hook ของ PreToolUse หรือกฎ firewall
prompt injection เป็นความเสี่ยงจริงหรือไม่ หาก agent เข้าถึงเฉพาะ repository ของฉันเอง
เป็นความเสี่ยงจริง เพราะ repository ของคุณเต็มไปด้วยข้อความที่คุณไม่ได้เขียน ไฟล์ README ของ dependency, URL ใน lockfile, test fixture, โค้ดที่ vendored และ output ของ npm install ล้วนถูกนำเข้ามาระหว่างงานตามปกติ สิ่งใดก็ตามที่ดึงมาจาก issue tracker หรือเว็บไซต์เอกสารก็เข้ามาในลักษณะเดียวกัน ความเสี่ยงจะเพิ่มขึ้นตามปริมาณข้อมูลที่ agent อ่าน และ agent ที่มีประโยชน์มักอ่านข้อมูลจำนวนมาก
การเรียกใช้ agent ใน container แก้ปัญหานี้ได้หรือไม่
ช่วยจำกัดความเสียหายได้ แต่จะได้ผลก็ต่อเมื่อคุณนำ credentials ออกไปด้วย หาก forward SSH agent, ใส่ cloud credentials ไว้ใน environment และเปิด network access แบบไม่จำกัดให้ container ผู้โจมตีก็จะเข้าถึงเกือบทุกอย่างที่ host เข้าถึงได้ สิ่งที่ container ช่วยได้จริงคือมี filesystem ที่ลบทิ้งได้ และมีพื้นที่สะอาดสำหรับบังคับใช้กฎ egress ควรใช้ร่วมกับ token ที่จำกัดขอบเขตไว้กับ repository เดียว
การเปลี่ยนแปลงเพียงอย่างเดียวที่ลดความเสี่ยงได้มากที่สุดคืออะไร
นำ credentials ที่มีอายุยาวออกจาก environment ที่คำสั่งของ agent สืบทอดมา จากนั้นกำหนด default-deny egress policy ให้กับเครื่องนั้น ทั้งสองอย่างนี้ตัดเงื่อนไขข้อที่สามของ lethal trifecta ได้ ข้อความยังสามารถ hijack agent ได้ แต่ข้อมูลที่ agent เข้าถึงจะไม่สามารถนำไปใช้ต่อได้อย่างมีประโยชน์ approval prompt และการตรวจสอบ diff ก็ช่วยได้เช่นกัน แต่ทั้งสองอย่างต้องอาศัยมนุษย์ที่มีสมาธิตลอดการทำงานระยะยาว จึงมีความสำคัญรองลงมาจากการเปลี่ยนแปลง 2 ข้อนี้