GitLost: หลอก GitHub AI Agent ให้ทำข้อมูลจากรีโปส่วนตัวรั่วไหล
(noma.security)- Noma Labs ค้นพบช่องโหว่ indirect prompt injection ชื่อ GitLost ใน GitHub Agentic Workflows ซึ่งสามารถทำให้ข้อมูลจากรีโปส่วนตัวในองค์กรเดียวกันถูกเปิดเผยในคอมเมนต์สาธารณะได้ โดยอาศัยเพียง issue ในรีโปสาธารณะ
- ฟีเจอร์นี้ทำงานโดยคอมไพล์เวิร์กโฟลว์ Markdown เป็นไฟล์ YAML Actions และให้ AI agent ที่อิงกับ Claude หรือ GitHub Copilot อ่าน issue เรียกใช้เครื่องมือ และเข้าถึงรีโปภายในองค์กร
- เวิร์กโฟลว์ที่มีช่องโหว่อ่าน Title และ Body ของ issue จากอีเวนต์
issues.assignedแล้วตอบกลับด้วยadd-commentโดยมีสิทธิ์อ่านทั้งรีโปสาธารณะและรีโปส่วนตัว - ผู้โจมตีไม่ต้องมีโค้ด สิทธิ์เข้าถึง หรือข้อมูลรับรองใดๆ เพียงแค่เปิด issue ที่ดูน่าเชื่อถือในรีโปสาธารณะ และในการทดสอบ เนื้อหา
README.mdของpocและtestlocalก็ถูกโพสต์ในคอมเมนต์ของ issue สาธารณะ - การ์ดเรลของ GitHub ไม่สามารถป้องกันได้ตามตั้งใจเมื่อใช้รูปแบบ “Additionally” และใน AI แบบ agentic นั้น ต้องมอง context window เองว่าเป็นพื้นผิวการโจมตี และแยกคอนเทนต์ที่ผู้ใช้ควบคุมได้ออกจากคำสั่งที่เชื่อถือได้
เส้นแบ่งความเชื่อถือที่ GitLost โจมตี
- Noma Labs พบช่องโหว่ชื่อ GitLost ใน Agentic Workflows แบบใหม่ของ GitHub
- หากผู้โจมตีที่ไม่ผ่านการยืนยันตัวตนโพสต์ GitHub Issue ที่ถูกดัดแปลงในรีโปสาธารณะขององค์กรเดียวกัน ก็อาจชักจูงให้ agent ดึงข้อมูลจาก รีโปส่วนตัว ภายในองค์กรออกมาได้
- วิธีโจมตีนี้เข้าข่าย indirect prompt injection ซึ่งซ่อนคำสั่งอันตรายไว้ในคอนเทนต์ที่ AI agent อ่าน
- หากคำสั่งที่ผู้โจมตีซ่อนไว้ถูกประมวลผลก่อนคำสั่งที่ผู้ดูแลตั้งใจไว้ ข้อมูลส่วนตัวอาจรั่วไปอยู่ในคอมเมนต์ของ issue สาธารณะที่ใครก็เห็นได้
GitHub Agentic Workflows ทำงานอย่างไร
- GitHub Agentic Workflows ช่วยให้ทีมเขียนระบบอัตโนมัติของรีโปด้วย ภาษาธรรมชาติ ได้
- เวิร์กโฟลว์ถูกเขียนเป็นไฟล์ Markdown
.mdและคอมไพล์เป็นไฟล์ GitHub Actions แบบ YAML.yml - ตอนรัน AI agent ที่อิงกับ Claude หรือ GitHub Copilot จะทำงานภายในสิทธิ์ที่กำหนดไว้
- อ่าน GitHub Issue
- เรียกใช้เครื่องมือ
- เข้าถึงรีโปอื่นภายในองค์กร
เงื่อนไขของเวิร์กโฟลว์ที่มีช่องโหว่
- การตั้งค่าที่ Noma Labs ตรวจพบจะมีปัญหาเมื่อ issue สาธารณะถูกใช้ร่วมกับสิทธิ์ของ agent
- ทริกเกอร์เวิร์กโฟลว์จากอีเวนต์
issues.assignedของ GitHub - อ่าน Title และ Body ของ issue
- โพสต์คอมเมนต์ด้วยเครื่องมือ
add-comment - มีสิทธิ์อ่านรีโปอื่นภายในองค์กร
- รีโปสาธารณะ
- รีโปส่วนตัว
- ทริกเกอร์เวิร์กโฟลว์จากอีเวนต์
- ผู้โจมตีไม่จำเป็นต้องเขียนโค้ดเพิ่ม มีสิทธิ์เข้าถึง หรือมีข้อมูลรับรองใดๆ
- เงื่อนไขที่ต้องมีคือแค่เปิด issue ใน รีโปสาธารณะ ขององค์กรที่ใช้ GitHub Agentic Workflow
ลำดับการโจมตี
- นักวิจัยเขียน GitHub Issue ที่ดูน่าเชื่อถือ ให้เหมือนเป็นคำขอจาก VP Sales หลังการประชุมกับลูกค้า
- เมื่อ issue ถูก assign เวิร์กโฟลว์แอ็กชันก็ถูกทริกเกอร์ และจากการทดสอบพบว่าวิธีเดียวกันนี้ทำงานกับ GitHub workflow action อื่นๆ ได้เช่นกัน
- หลังจากระบบอัตโนมัติของ GitHub ทำการ assign issue เวิร์กโฟลว์ที่รันจากอีเวนต์ก็ทำให้ agent ไปดึงเนื้อหาของรีโป
- agent ถูกชักจูงให้ดึงเนื้อหา
README.mdของรีโปต่อไปนี้pocรีโปสาธารณะtestlocalรีโปส่วนตัว
- จากนั้น GitHub agent ก็โพสต์เนื้อหาดังกล่าวเป็นคอมเมนต์ของ issue ในรีโปสาธารณะ ทำให้ใครก็อ่านได้
เลี่ยงการ์ดเรลด้วย “Additionally”
- GitHub มี การ์ดเรลแบบจำกัด เพื่อป้องกันสถานการณ์นี้อยู่แล้ว
- Noma Labs ทดสอบซ้ำหลายรูปแบบเหมือนที่ผู้โจมตีอาจทำ
- เมื่อเพิ่มคีย์เวิร์ด “Additionally” โมเดลกลับไม่ปฏิเสธและเกิดพฤติกรรมที่ไม่ตั้งใจ คือจัดรูปเอาต์พุตใหม่แทน
- ช่องทางเลี่ยงนี้ทำให้การ์ดเรลของ GitHub ไม่ทำงานตามที่ตั้งใจ และไม่สามารถหยุดการรั่วไหลของข้อมูลได้
PoC และข้อมูลที่ถูกเปิดเผย
- Noma Labs เปิดเผยผลการตรวจสอบ เวิร์กโฟลว์ที่ใช้ทำซ้ำ และหลักฐานจริง
- ข้อมูลที่รั่วไหลมีเนื้อหา
README.mdของรีโปต่อไปนี้รวมอยู่ด้วยsasinomalabs/poc: รีโปสาธารณะsasinomalabs/remote-ping: รีโปสาธารณะ ยืนยันว่าไม่มี READMEsasinomalabs/testlocal: รีโปส่วนตัว
สมมติฐานด้านความปลอดภัยที่เปลี่ยนไปใน AI แบบ agentic
- context window ของ agent เป็นทั้งพื้นที่ทำงานและพื้นผิวการโจมตี
- ทุกคอนเทนต์ที่ agent อ่านสามารถถูกทำให้เป็นอาวุธได้
- issue
- Pull Request
- คอมเมนต์
- ไฟล์
- โมเดลความปลอดภัยแบบดั้งเดิมมักตั้งสมมติฐานว่าเส้นแบ่งความเชื่อถือถูกบังคับใช้ด้วยโค้ด
- แต่ในระบบแบบ agentic เส้นแบ่งความเชื่อถือบางส่วนถูกบังคับใช้ด้วย พฤติกรรมของโมเดล
- เนื่องจากโมเดลมีธรรมชาติคือทำตามคำสั่ง prompt injection จึงกลายเป็นช่องโหว่เชิงหมวดหมู่ใน AI แบบ agentic เช่นเดียวกับที่ SQL injection เคยเป็นต่อเว็บแอปพลิเคชัน
- ช่องโหว่ประเภทนี้ต้องการกลยุทธ์และการป้องกันอย่างเป็นระบบ
แนวทางป้องกันที่แนะนำและกระบวนการเปิดเผย
- ไม่ควรปฏิบัติต่อคอนเทนต์ที่ผู้ใช้ควบคุมได้เหมือนเป็น อินพุตคำสั่งที่เชื่อถือได้ ของ AI agent
- ควรจำกัดสิทธิ์ของ agent ให้เหลือเท่าที่จำเป็นขั้นต่ำ
- agent ที่เข้าถึงได้หลายรีโปเป็นเป้าหมายโจมตีที่มีมูลค่าสูงเป็นพิเศษ
- ควรจำกัดสิ่งที่ agent สามารถโพสต์ต่อสาธารณะได้ เช่น ในกรณีที่ตอบกลับคอนเทนต์ของ issue
- ก่อนส่งอินพุตของผู้ใช้ให้โมเดล ควร กรองหรือแยก ออกจากบริบทของคำสั่ง
- GitLost ถูกเปิดเผยต่อ GitHub อย่างรับผิดชอบ และมีการแชร์รายละเอียดช่องโหว่ในขณะที่ GitHub รับทราบเรื่องแล้ว
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
การเปรียบเทียบว่า prompt injection อยู่ในตำแหน่งเดียวกับที่ SQL injection เคยมีต่อเว็บแอปนั้นดูแปลก ๆ ผมคิดว่า prompt injection น่าจะร้ายแรงต่อ LLM มากกว่า SQL injection มาก
SQL injection เกิดขึ้นเมื่ออินพุตจากผู้ใช้กลายเป็นส่วนหนึ่งของสตริงคำสั่งที่ส่งต่อไปยัง SQL engine และเมื่ออินพุตประสงค์ร้ายใช้โทเค็นไวยากรณ์ของ SQL เพื่อจบคำสั่งปัจจุบันแล้วต่อท้ายคำสั่ง SQL ของตัวเอง engine ก็จะรันทั้งสองคำสั่ง วิธีแก้คือใช้สตริงคำสั่งที่คงที่ ตายตัว และคอมไพล์ไว้ล่วงหน้า เช่น prepared statements แล้วให้อินพุตใด ๆ จากผู้ใช้ถูกใช้เป็นข้อมูลเท่านั้น
มาตรการบรรเทาที่คล้ายกันในเอเจนต์คือการมีการกระทำแบบตายตัว เช่น “อ่าน repo 1”, “อ่าน repo 2” แล้วใช้อินพุตจากผู้ใช้เป็นข้อมูลเพื่อเลือกว่าจะรันการกระทำใดเท่านั้น แต่นี่เป็นเทคนิคที่เราเรียกกันอยู่แล้วว่า เมนู คุณค่าของ LLM อยู่ที่การเป็นอะไรที่มากกว่าเมนูโดยเนื้อแท้ ขณะที่คุณค่าของ SQL ไม่จำเป็นต้องมากกว่า “ตรรกะที่นิยามไว้ล่วงหน้าซึ่งนำไปใช้กับข้อมูลใด ๆ” ตรงนี้คือความต่าง
การอนุญาตให้เอเจนต์ทำได้เฉพาะการกระทำที่จำกัดนั้นครอบคลุมได้แค่ปัญหาเฉพาะบางส่วน และไม่ได้แยกโค้ดออกจากข้อมูลผู้ใช้ จึงไม่ใช่ปัญหาเดียวกัน การมีเฉพาะการกระทำที่จำกัดนั้นใกล้เคียงกับการใช้สิทธิ์ฐานข้อมูลที่เข้มงวดกว่า ถ้าอนุญาตให้ผู้ใช้ใช้ได้เฉพาะ SQL ที่เขาสามารถรันได้อยู่แล้ว SQL injection ก็แทบไม่มีความหมาย
การให้เลือกจากเมนูก็เป็นวิธีหนึ่ง แต่ขอบเขตการกระทำที่เป็นไปได้สามารถออกแบบให้กว้างกว่านั้นได้ ถ้าให้เครื่องมืออีเมล ก็อาจส่งสแปมไปหาลูกค้าได้ และถ้าล็อกให้ทำได้แค่ตอบกลับ ก็ลดขอบเขตความเสียหายได้ เช่นเดียวกับช่องโหว่ที่ข้อมูลรั่วผ่านการเรนเดอร์ภาพ ก็ต้องจำกัด การรั่วไหลของข้อมูล ด้วย
วิธีแก้ก็เหมือนกัน ใช้การควบคุมการเข้าถึงตามบทบาทแบบสิทธิ์ขั้นต่ำสุด และกำหนดให้การกระทำสำคัญต้องได้รับอนุมัติจากผู้ดูแลระบบ เท่านี้สิ่งเลวร้ายที่สุดที่ LLM ทำได้เองก็แค่พ่นคำที่ไม่เหมาะสมออกมา
มาตรการบรรเทาอย่างหนึ่งคือ prepared statements แต่อีกอย่างคือไม่อนุญาตให้ผู้ใช้คนใดเข้าถึงฐานข้อมูลทั้งหมด ผู้ใช้แบบอ่านอย่างเดียวไม่ควร
DROP TABLEได้ ไม่ว่าจะมี SQL injection หรือไม่ก็ตามเอเจนต์นี้มีสิทธิ์อ่านแบบไม่จำกัด และไม่มีแนวคิดเรื่อง “ผู้รับ” ของคำตอบ หากรวมสิทธิ์ของผู้รับเข้าไปด้วย การทำให้การเข้าถึงแบบอ่านถูกปฏิเสธโดยอัตโนมัติก็ค่อนข้างตรงไปตรงมา นี่ไม่ใช่วิธีแก้เดียว แต่ก็ไม่ยากที่จะนึกถึงแนวทางแก้ในทิศทางนั้น
ตัวอย่าง “เมนู” ก็หมายความว่าไม่มีอะไรเปลี่ยนไปเช่นกัน ไม่ว่าจะเป็น LLM หรือพนักงานมนุษย์ สิ่งที่อนุญาตให้ทำได้ก็คือชุดการกระทำคงที่ที่ถูกควบคุมเท่านั้น อิสระส่วนใหญ่อยู่ที่การแสดงออก ส่วนการมอบสิทธิ์เป็นชุดคงที่ ผมไม่เข้าใจว่าทำไมต้องเป็นอะไรที่มากกว่าเมนู
ไม่เข้าใจว่าทำไมเรื่องนี้ถึงเป็นช่องโหว่ของ GitHub นักวิจัยให้สิทธิ์เอเจนต์เข้าถึงรีโพซิทอรีส่วนตัว แล้วให้มันตอบคำถามจากรีโพซิทอรีสาธารณะ ก็ย่อมทำให้ ดึงข้อมูลส่วนตัวออกมา ได้อยู่แล้ว
เหมือนกับการสร้างงาน CI ทั่วไปที่เข้าถึงค่าลับได้ แล้วให้รันจาก PR สาธารณะ ถ้าตั้งค่า GitHub ให้โค้ดสาธารณะหรือคำสั่งของ LLM รันในบริบทที่เข้าถึงสิ่งละเอียดอ่อนได้ มันก็รั่ว นั่นไม่ใช่ความผิดของ GitHub แต่เป็นความผิดของคนตั้งค่า
ต่อให้กำหนดขอบเขตโทเคนอย่างเข้มงวด การเข้าถึงรีโพซิทอรีสาธารณะก็ยังถูกอนุญาตเสมอ และยังเหลือเส้นทางรั่วไหลผ่าน issue ของรีโพซิทอรีสาธารณะได้ เป็นต้น ถ้าจะให้ปลอดภัย ต้องเสริมด้วยพร็อกซี MITM ที่ใช้การควบคุมเข้มงวดกว่าที่ GitHub มีให้
GitHub Agentic workflows น่าจะเป็นทางแก้ระดับแรกอย่างเป็นทางการสำหรับปัญหานี้ แต่ไม่ว่าจะในแง่โมเดลความปลอดภัยหรือ usability ที่ปลอดภัย ก็ยังดูมีงานต้องทำอีก
รายละเอียดเพิ่มเติม: https://haulos.com/blog/do-not-give-your-agent-github-access...
แบบนี้ยังไปด้วยกันได้กับการพัฒนาแบบเปิด และยังอนุญาตให้คนนอกเปิด issue สาธารณะได้ พร้อมสะท้อนระดับความไว้วางใจที่จะให้กับผู้ใช้แต่ละคน ถ้าคิดให้ดีจริง ๆ ก็น่าจะมีทางเลือกมากกว่านี้
การจะทำแบบนั้นต้องมีการรองรับทางเทคนิคสำหรับการกำหนดขอบเขตและสิทธิ์อย่างละเอียด และต้องใช้เวลาพิจารณาว่าต้องการให้เอเจนต์ทำอะไรให้สำเร็จ และสิทธิ์กับความสามารถขั้นต่ำที่จำเป็นคืออะไร
อย่างแรกน่าจะมาถึงได้ ตอนนี้การใช้เอเจนต์ยังเหมือนยุคบุกเบิกตะวันตกอยู่ น่าสนใจว่านามธรรมแบบไหนจะลดแรงเสียดทานตอนที่คนออกแบบเอเจนต์ต้องหาและกำหนดขอบเขตกับสิทธิ์ และอินเทอร์เฟซแบบไหนจะสร้างสมดุลระหว่างความละเอียดกับ usability เมื่อต้องจำกัดความสามารถของเอเจนต์
อย่างที่สองเป็นอุปสรรคหลักที่ขัดขวางการสร้างซอฟต์แวร์คุณภาพสูงมาโดยตลอด การใช้เวลาคิดให้รอบคอบและลงมือทำให้ถูกต้องนั้นขัดกันตรง ๆ กับแนวทาง “move fast and break things” ที่โยนเอเจนต์ไปไว้ทุกที่
ถ้าคำตอบของคำถามข้อใดข้อหนึ่งคือ “ไม่” นั่นก็เป็นปัญหาแล้ว GitHub Workflows แบบดั้งเดิมก็มี การยกระดับสิทธิ์ ผ่าน workflow ที่ทริกเกอร์จาก PR อยู่เต็มไปหมดเหมือนกัน แต่นั่นเป็นอีกประเด็นหนึ่ง
ทางแก้จริง ๆ คือทำ UI ควบคุมสิทธิ์ตามพรอมป์ต ให้ดีกว่านี้ ควรเปิดปิดตัวเลือกอย่าง “รวมรีโพซิทอรีส่วนตัวของฉัน” ได้ง่าย ๆ เหมือนเลือกว่าจะ “ค้นเว็บหรือไม่”
ตลกดีที่นักวิจัยหลบ guardrail ที่ GitHub อวดไว้ได้ด้วยคำคำเดียวอย่าง “Additionally” มันแสดงให้เห็นว่าความพยายามสร้าง ขอบเขตความปลอดภัย ที่แข็งแรงภายใน context window ของ LLM นั้นย่อมล้มเหลว
โดยพื้นฐานแล้วโมเดลถูกสร้างมาให้ทำตามคำสั่ง ดังนั้นเมื่อเอากฎของระบบมาปนกับอินพุตของผู้ใช้ คำสั่งที่ใหม่กว่าหรือดื้อด้านกว่าก็จะชนะ
ทำไมส่วน “responsible disclosure” ถึงไม่มีบอกว่าแก้เมื่อไหร่ หรือ GitHub ยอมรับหรือปฏิเสธ? บอกว่า GitLost ถูกเปิดเผยต่อ GitHub อย่างรับผิดชอบ และแชร์รายละเอียดโดยที่ GitHub ทราบแล้ว แปลว่ายังไม่ได้แก้หรือ?
https://github.github.com/gh-aw/reference/cross-repository/#...
บริษัทใหญ่ ๆ อย่าง Microsoft กำลังยัด AI เข้าไปในทุกผลิตภัณฑ์ เพื่ออ้างว่าตอนนี้เป็นบริษัท AI เพราะแรงกดดันจากนักลงทุน คล้ายกับที่ Adobe เคยทำ
ผู้บริโภคเริ่มเบื่อ การผสาน AI แบบครึ่ง ๆ กลาง ๆ เหล่านี้แล้ว และดูเหมือนใกล้ถึงจุดแตกหัก
พูดจริง ๆ เวลา click ไปมาตามที่ต่าง ๆ ทุกอย่างตอบสนองทันที และ CI ที่ต่อ runner ไว้ก็ทำงานสวยงาม เอกสารการตั้งค่า runner น่าจะชัดกว่านี้ได้อีกหน่อย แต่นอกเหนือจากนั้นทุกอย่างลื่นไหลมาก
รายได้มีอยู่จริงและน่าประทับใจ และกำลังเข้ามาแทนรายได้จากผู้บริโภค/แบบคิดตามจำนวนที่นั่ง ตลาดยังคงปรับลดตัวคูณของ SaaS อยู่ ซึ่งผมว่าการตัดสินนั้นถูกต้อง ถ้าแยกรายได้ในรายงานรายไตรมาสออกมาดู จะเห็น เรื่องราวการเติบโตครั้งใหญ่ ที่มาจากประสิทธิภาพจริง
ไม่แน่ใจว่าทำไมแอ็กชันที่รันในบริบทของ repository สาธารณะถึงมีสิทธิ์เข้าถึง repository ส่วนตัวได้ ดูจาก workflow แล้วเหมือนใช้
github tokenซึ่งโดยปกติจะไม่ให้สิทธิ์ repository ส่วนตัวหรือไม่ก็ตัวเอเจนต์เอง somehow มีสิทธิ์สูงกว่านั้น? ถ้าเป็นอย่างนั้นก็เป็นการตั้งค่าเอเจนต์ผิด เรารู้อยู่แล้วว่าไม่ควรเชื่อว่าเอเจนต์จะบังคับอะไรบางอย่างได้
บทความนี้อ่านแล้วเหมือน การตลาดของ Noma มีทั้งชื่อที่น่ารัก โลโก้ หัวข้อแนว clickbait และโทนดราม่าที่ดูเหมือนตั้งใจเจาะผู้อ่านที่ไม่ใช่สายเทคนิค
ถ้าถามว่าช่องโหว่จริง ๆ คืออะไร ก็คือถ้าเอาข้อมูลส่วนตัวให้ LLM แล้วปล่อยให้ใครก็ได้มาโต้ตอบด้วย ข้อมูลก็อาจรั่วได้ ซึ่งชัดเจนเกินไป
คนแบบนี้คงให้สิทธิ์ LLM เขียนได้ทั้งดิสก์ แล้วมาบ่นว่ามันทำงานแบบทำลายล้าง
ถ้าไม่อยากให้ AI agent อ่าน repository ส่วนตัว ก็แค่ไม่ต้องให้ สิทธิ์เข้าถึง repository ส่วนตัว นี่ไม่ใช่ปัญหาการข้ามสิทธิ์ แต่เป็นปัญหา prompt injection และไม่สามารถแก้ได้อย่างน่าเชื่อถือในเลเยอร์ของเอเจนต์
อาจเป็นปัญหาที่แก้ไปแล้ว หรือไม่ก็ GitHub ยังแก้ไม่ได้ และในระหว่างนั้นผู้ไม่หวังดีจะลองโจมตีช่องโหว่กับ repository ต่าง ๆ
เนื่องจากมี repository จำนวนมาก จึงมีโอกาสที่ไม่เป็นศูนย์ว่าจะเกิดการรั่วไหลได้ เพียงแต่เหมือนกรณีตกเป็นเหยื่อมิจฉาชีพ แทบไม่มีใครยอมรับว่าข้อมูลรั่ว