2 คะแนน โดย GN⁺ 2025-12-09 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • GitHub Actions มีโครงสร้างที่ประกาศและรัน การพึ่งพาแพ็กเกจ ผ่านรูปแบบ uses: ในไฟล์ workflow ซึ่งในทางปฏิบัติทำหน้าที่เป็นตัวจัดการแพ็กเกจ
  • อย่างไรก็ตาม ไม่มี lockfile, hash ความสมบูรณ์, การ pin การพึ่งพาแบบทรานซิทีฟ, และความสามารถในการมองเห็นต้นไม้การพึ่งพา ซึ่งเป็นฟีเจอร์หลักที่ตัวจัดการแพ็กเกจอื่นมอบให้เป็นค่าเริ่มต้น
  • จากการวิจัยพบว่า ผู้ใช้ GitHub Actions ส่วนใหญ่รันโค้ดจากบุคคลภายนอกที่ไม่ได้รับการตรวจสอบ และมีช่องโหว่การฉีดโค้ดปรากฏใน workflow จำนวนหลายพันรายการ
  • GitHub มีมาตรการบรรเทาบางส่วน (เช่น immutable release, นโยบาย pin ด้วย SHA ฯลฯ) แต่ ปัญหาการพึ่งพาแบบทรานซิทีฟและความสามารถในการทำซ้ำยังคงไม่ถูกแก้ไข
  • ข้อบกพร่องเชิงโครงสร้างเหล่านี้ส่งผลกระทบต่อความมั่นคงปลอดภัยของซัพพลายเชนซอฟต์แวร์ทั้งหมด และถูกขยายไปยังระบบ CI อื่น ๆ ที่อาศัย GitHub Actions

โครงสร้างการจัดการแพ็กเกจของ GitHub Actions และปัญหา

  • ไวยากรณ์เช่น uses: actions/checkout@v4 คือการ ประกาศ dependency และ GitHub แปลผลเพื่อต้องดาวน์โหลดและรัน
    • เป็นพฤติกรรมใกล้เคียงกับการจัดการแพ็กเกจทั่วไป แต่เนื่องจาก ไม่มี lockfile ทำให้แต่ละครั้งที่รันอาจเลือกเวอร์ชันแตกต่างกัน
  • เมื่อเทียบกับตัวจัดการแพ็กเกจอื่น ๆ (npm, Cargo, NuGet เป็นต้น) Actions ขาด lockfile, การ pin dependency แบบทรานซิทีฟ, การตรวจสอบความสมบูรณ์, ความสามารถในการมองเห็นต้นไม้ dependency และสเปกการ resolve ทั้งหมด
  • การไม่มี lockfile เป็นปัญหาหลัก ทำให้การตีความ dependency เปลี่ยนไปทุกครั้งที่รันและเกิด การ build แบบไม่กำหนดผลได้ (non-deterministic build)

ผลการวิจัยด้านความปลอดภัยและช่องโหว่

  • การวิจัย USENIX Security 2022 ระบุว่า 99.7% ของ repository รัน Actions จากนักพัฒนาภายนอก และ 97% มาจากผู้สร้างที่ไม่ได้รับการยืนยัน และ 18% ไม่มีการอัปเดตความปลอดภัย
  • งานวิจัยต่อมาพบช่องโหว่การฉีดโค้ดใน มากกว่า 4,300 ของ workflow จาก 2.7 ล้าน รายการ
  • GitHub Actions ยังไม่จัดให้ครบคุณสมบัติความปลอดภัยที่จำเป็นของ CI/CD เช่น admittance control, execution control, code control, และการควบคุมการเข้าถึง secrets

ข้อบกพร่องทางเทคนิคสำคัญ

  • ปัญหาเวอร์ชันแบบเปลี่ยนได้: แท็กอย่าง @v4 สามารถถูก re-tag ด้วย commit ใหม่โดยผู้ดูแลได้ ทำให้โค้ดถูก เปลี่ยนแปลงอย่างเงียบ
    • หากมี lockfile ก็สามารถบันทึกได้ว่าแท็กนั้นถูกตีความเป็น SHA ใด
  • ความไม่โปร่งใสของการพึ่งพาแบบทรานซิทีฟ: Action ที่เป็น Composite เรียกใช้ Action อื่นจากภายในไม่สามารถมองเห็นหรือตั้งการควบคุมได้
    • การวิจัยพบว่า JavaScript Actions จำนวน 54% มีจุดอ่อนด้านความปลอดภัย และส่วนใหญ่เกิดจาก dependency แบบทางอ้อม
    • ในกรณี tj-actions/changed-files มีการโจมตีรั่วไหลข้อมูลลับผ่านการอัปเดต dependency แบบทรานซิทีฟ
  • ขาดการตรวจสอบความสมบูรณ์: npm หรือ Cargo บันทึก hash เพื่อยืนยันการดาวน์โหลด แต่ Actions พึ่งพาความน่าเชื่อถือจาก SHA เท่านั้น
  • การรันซ้ำไม่สามารถทำซ้ำได้: GitHub ระบุว่าหากมีการ forced push เวอร์ชันล่าสุดจะถูกดึงมาใช้งานเสมอ ดังนั้น แม้ workflow เดิมก็อาจรันโค้ดที่ต่างกันได้
  • การมองไม่เห็นต้นไม้ dependency: ไม่มีฟังก์ชันแบบ npm ls ของ npm หรือ cargo tree ของ Cargo ทำให้ไม่มีวิธีตรวจสอบโครงสร้าง dependency ทั้งหมด
  • กฎการ resolve ไม่เปิดเผย: การ resolve dependency ของ Actions ไม่ได้มีเอกสารอธิบาย และในโค้ด ActionManager.cs มีเพียง logic ดาวน์โหลดแบบ recursive อย่างง่าย

ข้อจำกัดเชิงโครงสร้างเพิ่มเติม

  • ไม่มี registry กลาง: Actions อยู่ใน Git repository และยังไม่มีความสามารถในการสแกนความปลอดภัย, ตรวจจับมัลแวร์, หรือป้องกัน typosquatting
  • ปัญหาสภาพแวดล้อมที่แชร์กัน: Action หลายตัวแก้ไข $PATH เดียวกัน ทำให้ผลลัพธ์ต่างกันตามลำดับการรัน
  • ไม่สามารถรันแบบออฟไลน์ได้: ทุกครั้งต้องดาวน์โหลดจาก GitHub จึงไม่สามารถรันได้หากไม่มีเครือข่าย
  • ช่องโหว่ที่ namespace: ชื่อผู้ใช้ GitHub ทำหน้าที่เป็น namespace โดยตรง ทำให้เสี่ยงต่อการแฮกบัญชีหรือการโจมตีแบบพิมพ์ผิด
    • หากมี lockfile และ hash ความสมบูรณ์ การเปลี่ยนโค้ดจะถูกตรวจพบผ่านความล้มเหลวในการ build

ที่มาของการออกแบบและผลกระทบ

  • Runner ของ Actions เดิมมีรากฐานจาก Azure DevOps และถูกออกแบบโดยสมมติฐานว่าอยู่ในสภาพแวดล้อมที่เชื่อถือได้
    • เมื่อ GitHub ขยายไปเป็น marketplace สาธารณะ จึงยังไม่ได้ออกแบบใหม่โมเดลความไว้วางใจใหม่
  • จึงทำให้ขาดฟีเจอร์พื้นฐานอย่าง lockfile, การตรวจสอบความสมบูรณ์, การ pin แบบทรานซิทีฟ, ความโปร่งใสของ dependency
  • เมื่อ OIDC-based การ deploy แพ็กเกจอัตโนมัติ กำลังแพร่หลาย ความเสี่ยงของ Actions ก็ส่งผลต่อความปลอดภัยซัพพลายเชนของ registry แพ็กเกจทั้งหมด
  • GitLab CI นำคีย์ integrity มาใช้เพื่อตรวจสอบ hash แต่ GitHub ปฏิเสธคำขอเดียวกันว่าไม่มีแผน
  • ระบบ CI ที่รองรับ GitHub อย่าง Forgejo Actions ก็จำเป็นต้องคงโครงสร้างเดียวกัน ทำให้ข้อบกพร่องแพร่ไปทั่ว ecosystem

ข้อเสนอแนะการแก้ไขและสถานะปัจจุบัน

  • ชุมชนขอให้มีการรองรับ lockfile (issue #2195) แต่ GitHub ปิดข้อเสนอในปี 2022 ด้วยข้อความว่า “No plan”
  • การศึกษาโดย Palo Alto ยืนยันว่า การ pin เฉพาะ SHA อย่างเดียวไม่สามารถป้องกัน dependency แบบทรานซิทีฟได้
  • บางทีมเสริมด้วย การอัปเดตผ่าน Dependabot, vendor repository เอง, ตัวสแกนความปลอดภัย zizmor ฯลฯ
  • แนวทางแก้ไขเชิงโครงสร้างที่แท้จริงคือต้องนำ lockfile เข้ามาบันทึก SHA และ hash ความสมบูรณ์ของทุก Action และ dependency แบบทรานซิทีฟ
  • หาก GitHub ไม่ยอมรับแนวทางนี้ ความน่าเชื่อถือของซัพพลายเชน CI/CD ก็ไม่สามารถทำให้มั่นใจได้อย่างแท้จริง

2 ความคิดเห็น

 
holywork 2025-12-11

คงต้องโดนแฮ็กก่อนถึงจะได้สติสินะ

 
GN⁺ 2025-12-09
ความเห็นบน Hacker News
  • ไม่ได้อยากปกป้อง GHA (GitHub Actions) แต่ในเอกสารก็ระบุชัดว่าควร ตรึง commit SHA เพื่อความเสถียรและความปลอดภัย
    ถึงจะทำเองแบบไฟล์ lock ได้โดยตรง แต่ก็ไม่สมบูรณ์เพราะควบคุม transitive dependency ไม่ได้
    สุดท้ายก็ต้องแบกรับภาระในการติดตาม security patch และอัปเดตแฮช จึงดูเหมือนว่านี่เป็นเหตุผลที่การตรึงแบบอิงแฮชไม่ค่อยถูกใช้อย่างแพร่หลาย

    • GitHub รู้ปัญหานี้มาตั้งแต่ช่วงแรกหลังเปิดตัว Actions แต่ก็แทบไม่ได้ปรับปรุง ความสามารถในการตรึงเวอร์ชัน อย่างจริงจัง
      ผู้ใช้ส่วนใหญ่ไม่รู้ว่ามีปัญหา และแม้แต่คนที่รู้ก็แทบไม่ใช้ SHA
      ส่วนตัวฉันชอบ Actions และดูแลบางตัวอยู่ แต่พอดู public repository แล้วประมาณ 90% ใช้ @v1, 9% ใช้ @v1.2 และมีแค่ 1% ที่ใช้ commit SHA
      ถ้า GitHub ลงทุนอีกนิดก็น่าจะสร้าง โซลูชันแบบ lock file ได้
    • กลยุทธ์ในเอกสารแก้ปัญหา transitive dependency ไม่ได้ ดังนั้นในทางปฏิบัติจึงไม่ใช่วิธีแก้ที่ต้นเหตุ
    • คำพูดที่ว่าการตรึง commit SHA มีความเสถียรนั้น ในโลกความเป็นจริงไม่ถูกต้อง
      บ่อยครั้งมันขึ้นกับ Node เวอร์ชันหรือ API เวอร์ชันบางตัว จนมีประสบการณ์ว่าการใช้ @main กลับดีกว่าเสียอีก
    • ฉันมองว่าการใช้ SHA กลับเป็น anti-pattern
      มันทำให้เข้าใจผิดว่าได้ “เวอร์ชันที่ตรึงไว้” แต่จริง ๆ แล้วไม่ใช่
      เจอปัญหามาสองครั้งถึงได้ตระหนักว่า มันมีแค่สองแบบคือมี lock file หรือไม่มี
  • GitHub แทบจะ ไม่ดูแลรักษา Actions ของตัวเองแล้ว จนแม้แต่ฟีเจอร์พื้นฐานก็ต้องพึ่ง ฟอร์กไม่เป็นทางการ
    ให้ความรู้สึกว่า ecosystem ทั้งหมดกำลังอยู่ได้ด้วยการแก้ขัดไปวัน ๆ

    • สถานการณ์นี้คงไม่ดีขึ้นในเร็ว ๆ นี้
      เพราะ GitHub ประกาศว่าจะให้ความสำคัญกับ การย้ายระบบไป Azure มากกว่าการพัฒนาฟีเจอร์
      บทความที่เกี่ยวข้อง
    • จุดที่น่าสนใจก็คือ GitHub เป็นบริการที่ค่อนข้างแพง
      แม้แต่บริษัทเล็ก ๆ ของเราก็ยังจ่ายเกิน 200 ดอลลาร์ต่อเดือน
      ดูเหมือนว่าจะถูกมองเป็น แหล่งรายได้ใหม่ ที่สำคัญยิ่งกว่า Windows เสียอีก
    • คุณภาพของ setup- actions* ลดลงอย่างเห็นได้ชัด และมีการตัดสินใจแปลก ๆ มากขึ้น
      คนเขียนดั้งเดิมคงลาออกจากบริษัทไปแล้ว
    • เพิ่งเคยได้ยินเรื่องนี้เป็นครั้งแรก เลยสงสัยว่ามีตัวอย่างที่เป็นรูปธรรมไหม
    • ช่วงหลัง GitHub ไม่ได้ประกาศหรือว่า จะชะลอความเร็วในการพัฒนาฟีเจอร์ทั่วไปเพื่อ โฟกัสกับการพัฒนา AI หรอกหรือ?
  • สงสัยว่ามีใครเคยใช้ ArgoCD เป็น CI pipeline บ้างไหม

  • ฉันคิดว่า GHA เป็นตัวอย่างความล้มเหลวของปรัชญา ‘less is more
    ปัญหาใหญ่ที่สุดคือมันกลายเป็นมาตรฐานของวงการไปแล้ว
    ถ้าลงทุนอีกนิดก็ทำ CI ที่ดีกว่านี้ได้มาก แต่ให้ความรู้สึกว่า MS กำลังทำผิดซ้ำแบบ ยุค IE6
    ตอนนี้วิศวกรรุ่นใหม่ที่ไม่มีประสบการณ์เปรียบเทียบกลับไม่ทันตระหนักถึงข้อจำกัดของมัน

    • ทุกคนเห็นตรงกันว่า GHA แย่มาก แต่ก็ยังใช้กันต่อเพราะมี ทรัพยากรคอมพิวต์ฟรี ให้
      ฉันกำลังคิดจะเอาโน้ตบุ๊กที่ปลดระวางแล้วมารันเป็นเซิร์ฟเวอร์ Woodpecker อยากรู้ว่า CI ที่คนไม่เกลียดเป็นอย่างไร
    • ฉันเป็นคนรุ่นที่เคยต้องใช้ VSS มาก่อน ดังนั้นแม้แต่ GitHub ทุกวันนี้ก็ยังรู้สึกว่าดีกว่าสมัยนั้นมาก
    • ส่วนใหญ่ฉันทำงาน บนเครื่องตัวเองโดยตรง
      เมื่อเทียบกันแล้ว GHA ดูไม่มีคุณค่าอะไรเป็นพิเศษ
  • ตอนที่บริษัทพยายามย้ายจาก Jenkins/Ansible ไป GHA ฉันคัดค้านไว้ และตอนนี้ดูเหมือนว่าจะเป็นการตัดสินใจที่ถูกแล้ว
    CI มี ภาระในการดูแลรักษา สูงอยู่เสมอ และโดยเฉพาะบน Mac ก็ยังจัดการยากเหมือนเดิม

  • สำหรับคำถามว่า “เชื่อหรือไม่ว่า GitHub จะให้โค้ด SHA ที่ถูกต้อง”
    เมื่อมองจากความจริงที่ว่าคนส่วนใหญ่ใช้ GitHub-hosted runner กันอยู่แล้ว ถ้าเชื่อเรื่องนั้นไม่ได้ ก็คงมีปัญหาใหญ่กว่านั้นอยู่ก่อนแล้ว

  • ทำให้นึกสงสัยว่า ถ้า GitHub Actions เป็นสถาปัตยกรรมแบบ local-first และรองรับ การล็อกบนพื้นฐานของ Nix จะเป็นอย่างไร
    cachix/cloud.devenv.sh

    • น่าแดกดันที่แม้แต่โค้ดนั้นก็ยัง โฮสต์อยู่บน GitHub
  • หลาย ๆ third-party Actions อ้างถึง สาขา master โดยตรงในเอกสารหรือในตัวอย่าง
    แค่มีการ push ที่เป็นอันตรายครั้งเดียว ก็อาจทำให้เกิด ข้อมูลรั่วไหล ได้ใน repository จำนวนมาก
    ต่อให้ใช้ tag ก็ยังขยับได้ จึงไม่ใช่การป้องกันที่สมบูรณ์

  • พอเห็นที่นักวิจัยพูดถึงคุณสมบัติความปลอดภัยหลัก 4 ประการของ CI/CD (authentication, execution, code, secret access) ก็เกิดคำถามขึ้นมา
    CI/CD จำเป็นต้องเข้าถึง secrets จริงหรือ?
    ฉันคิดว่าแค่มีสิทธิ์เรียก API ก็น่าจะพอแล้ว
    ระบบในอุดมคติไม่ควรจัดการ secrets โดยตรง แต่ควรจัดการทางอ้อมผ่านตัวปรับแบบ secure enclave หรืออะไรทำนองนั้น

    • คำพูดที่ว่า “CI ที่ดีไม่ควรรองรับ secrets” สุดท้ายแล้วก็คือการเสนอ วิธีจัดการ secrets ที่ซับซ้อนกว่าเดิม
      ในโลกจริง ลูกค้าส่วนใหญ่ก็ยังต้องใช้ secrets อยู่ดี
    • ในทางทฤษฎีอาจถูกต้อง แต่ในความเป็นจริงคนก็เลี่ยงไม่ได้ที่จะต้องใส่ secrets ลงใน CI/CD
      อย่างน้อยแพลตฟอร์มก็ควรมี กลไกจัดการ secrets ที่ปลอดภัย ให้
      โดยเฉพาะโปรเจกต์โอเพนซอร์สที่ต้องการ deploy โดยตรงจาก CI
    • บริษัทเรามีการใช้ เครื่องมือเชิงพาณิชย์ อย่างคอมไพเลอร์ QNX หรือ Coverity ซึ่งต้องใช้ secrets เพื่อเข้าถึง license server
      เลยสงสัยว่า “แนวทาง secure enclave” นั้นต่างออกไปอย่างไรในทางปฏิบัติ
    • ถ้า CI/CD ถูกรวมเข้ากับโครงสร้างพื้นฐานแบบสมบูรณ์ การ deploy ก็อาจทำได้โดยไม่ต้องใช้ secrets
      แต่ในความเป็นจริงแต่ละสภาพแวดล้อมต่างกัน และต้นทุนการทำระบบก็สูง สุดท้ายคนส่วนใหญ่เลยจบที่วิธี container + environment variables
    • ถ้าจะทดสอบความเข้ากันได้กับ cloud DB หลายเจ้า ก็จำเป็นต้องมี ข้อมูลรับรอง เพื่อเข้าถึงแต่ละฐานข้อมูล
      ถ้าจะทำการทดสอบแบบนี้ให้อัตโนมัติ การมี secrets ก็หลีกเลี่ยงไม่ได้
  • ถ้าต้อง commit lock file เข้า repository ก็จะเกิด ปัญหา bootstrapping ตอนสร้างครั้งแรก
    ถ้าจะแก้เรื่องนี้ก็ควรมีความสามารถในการ รัน Actions บนเครื่องโลคัล ได้
    มีเครื่องมืออย่าง nektos/act แต่หลัก ๆ เอาไว้ใช้ดีบัก
    อาจจำเป็นต้องมีกลไกแยกต่างหากที่อิงกับ static analysis