3 คะแนน โดย GN⁺ 2025-08-29 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • มีการเผยแพร่เวอร์ชันอันตรายของ แพ็กเกจ Nx และปลั๊กอิน ไปยัง npm โดยทำการสแกนระบบไฟล์ รวบรวม ข้อมูลรับรอง แล้วส่งไปยังรีโพซิทอรีในบัญชี Github ของผู้ใช้
  • หากต้องการตรวจสอบว่าได้รับผลกระทบหรือไม่ ต้องตรวจสอบว่ามีการสร้าง รีโพซิทอรี s1ngularity-repository ในบัญชี Github หรือไม่
  • หากติดเชื้อ จำเป็นต้อง เปลี่ยนโทเค็นและรหัสผ่าน ลบรีโพซิทอรีอันตราย และตรวจสอบไฟล์ตั้งค่าเชลล์ โดยทันที
  • เวอร์ชันอันตรายส่งผลต่อระบบผ่าน สคริปต์ postinstall และมีความเสี่ยงที่จะถูกรันโดยไม่รู้ตัวเพิ่มขึ้น โดยเฉพาะเมื่อใช้งานปลั๊กอิน VSCode Nx Console
  • ฝั่ง Nx ได้ดำเนินการ ป้องกันการเกิดซ้ำและเพิ่มมาตรการความปลอดภัย แล้ว และเวอร์ชันที่เกี่ยวข้องถูกลบออกจาก npm แล้ว

ภาพรวมและสรุป

  • คำแนะนำด้านความปลอดภัยครั้งนี้เกี่ยวข้องกับการโจมตีแบบ supply chain ร้ายแรงต่อ แพ็กเกจ Nx และปลั๊กอินที่เกี่ยวข้องบางส่วน โดยมีการเผยแพร่โค้ดอันตรายผ่าน npm
  • เวอร์ชันอันตรายดังกล่าวจะ สแกนระบบไฟล์ ของผู้ใช้เพื่อรวบรวมข้อมูลรับรอง พาธ และข้อมูลอื่น ๆ แล้วอัปโหลดไปยังรีโพซิทอรี Github (s1ngularity-repository)
  • สคริปต์ postinstall อันตรายยังแก้ไขไฟล์ตั้งค่าเชลล์ของผู้ใช้ (.zshrc, .bashrc) เพื่อเพิ่มคำสั่งปิดระบบเข้าไป
  • มีการสรุปอย่างละเอียดถึงช่องทางการโจมตีและลำดับการโจมตี เวอร์ชันที่ได้รับผลกระทบ มาตรการเร่งด่วนที่ผู้ใช้ควรทำ และแนวทางป้องกันไม่ให้เกิดซ้ำ

วิธีดำเนินการเร่งด่วน

สิ่งที่ทุกคนต้องตรวจสอบ

  1. ตรวจสอบในรายการรีโพซิทอรีของบัญชี Github ของตนว่ามีการสร้าง s1ngularity-repository หรือไม่
  2. ดาวน์โหลดไฟล์ที่อยู่ในรีโพซิทอรีนั้นเพื่อเก็บไว้เป็นหลักฐาน
  3. ลบรีโพซิทอรีออกจาก Github
  4. ส่งอีเมลไปที่ security@nrwl.io เพื่อขอคำแนะนำวิธีถอดรหัสข้อมูลที่รั่วไหล
  5. เปลี่ยนข้อมูลรับรองและโทเค็นของทุกบัญชีทันที

วิธีเปลี่ยน Github token

  • ไปที่ https://github.com/settings/connections/…
  • เพิกถอนสิทธิ์การเข้าถึงของแอปที่เชื่อมต่อเพื่อทำให้โทเค็นเดิมใช้งานไม่ได้
  • หากใช้ gh CLI ให้ยืนยันตัวตนใหม่เพื่อสร้างโทเค็นใหม่
  • หากไม่ดำเนินการ โทเค็นเดิมอาจถูกนำไปใช้ในทางที่ผิด

หยุดใช้และจัดการเวอร์ชัน Nx ที่เป็นอันตราย

  • ตรวจสอบว่าเวอร์ชัน Nx ที่ใช้อยู่เป็นเวอร์ชันอันตรายหรือไม่ด้วยคำสั่ง npm ls nx
  • หากเป็นเวอร์ชันที่ติดเชื้อ ให้อัปเดตด้วย npm uninstall nx && npm install nx@latest
  • ล้างแคชด้วย npm cache clean --force

ผู้ใช้ที่ติดเชื้อแล้ว

  • เปลี่ยน npm และ Github token
  • รีเซ็ตรหัสผ่านและข้อมูลรับรองทั้งหมดของ Github และบริการที่เกี่ยวข้อง
  • ตรวจสอบไฟล์ .zshrc, .bashrc ว่ามีการแทรกคำสั่งแปลกปลอมหรือไม่ แล้วลบออก

กรณีเป็นผู้ดูแลรีโพซิทอรีแพ็กเกจภายในองค์กร

  • จำเป็นต้องลบเวอร์ชันอันตรายออกจาก proxy ใน registry ภายในองค์กรทันทีเพื่อป้องกันการแพร่กระจายเพิ่มเติม

เวอร์ชันที่ได้รับผลกระทบ

แพ็กเกจ Nx

  • 21.5.0, 20.9.0, 20.10.0, 21.6.0, 20.11.0, 21.7.0, 21.8.0, 20.12.0
  • ถูกลบออกจาก npm แล้ว ณ เวลา 10:44 PM EDT

@nx/devkit, @nx/js, @nx/workspace, @nx/node, @nx/eslint, @nx/key, @nx/enterprise-cloud

  • ถูกลบออกจาก npm แล้ว ณ เวลา 10:44 PM, 6:20 AM EDT

รายละเอียดช่องทางการโจมตี

สาเหตุของ Workflow ที่มีช่องโหว่

  • มีการนำ ช่องโหว่ที่ทำให้รันโค้ดตามอำเภอใจได้ เข้ามาใน workflow ของ Github Actions
  • หากแทรก bash code บางอย่างลงในชื่อ PR จะเกิดช่องโหว่ที่ทำให้ workflow รันคำสั่งระบบได้ (Bash Injection)
  • มีการนำไปใช้ผ่าน trigger pull_request_target ซึ่งทำให้ได้สิทธิ์ที่สูงขึ้น เช่น GITHUB_TOKEN
  • ก่อนถูกลบ workflow ที่มีช่องโหว่ยังคงอยู่ใน branch เก่าที่ไม่ใช่ main ทำให้ผู้โจมตีสามารถรัน workflow ผ่าน PR อันตรายและขโมย secrets ได้สำเร็จ

กระบวนการขโมย npm token

  • บังคับให้มีการรัน publish.yml ผ่าน workflow ที่มีช่องโหว่
  • publish.yml เก็บ npm token ไว้ใน Github Secrets และในขั้นตอนนี้มีการส่งโทเค็นออกไปยัง webhook ภายนอก
  • ท้ายที่สุดผู้โจมตีใช้โทเค็นนี้อัปโหลดเวอร์ชันอันตรายของ Nx และแพ็กเกจที่รองรับไปยัง npm

พฤติกรรมของแพ็กเกจอันตราย

รวบรวมข้อมูลรวมถึงข้อมูลรับรองและเผยแพร่ไปยังรีโพซิทอรี Github

  • เมื่อสคริปต์ postinstall ของแพ็กเกจ Nx ที่ติดเชื้อทำงาน จะมีการรวบรวมตำแหน่งของไฟล์ข้อความต่าง ๆ และข้อมูลรับรอง
  • เข้ารหัสเป็น base64 แล้วอัปโหลดไปยังรีโพซิทอรี Github ชื่อ s1ngularity-repository
  • แม้รีโพซิทอรีจริงจะถูกลบไปแล้ว แต่ก่อนหน้านี้เคยเป็นสาธารณะ จึงต้องคำนึงถึงความเป็นไปได้ของข้อมูลรั่วไหล

การแก้ไข shell profile (.zshrc, .bashrc)

  • postinstall แทรกคำสั่ง sudo shutdown -h 0 เพื่อทำให้ระบบปิดเมื่อเปิดเทอร์มินัล และอาจทำให้รหัสผ่านรั่วไหลได้

สถานการณ์หลากหลายที่ postinstall สามารถทำงานได้

  • นอกจากการรัน npm install/yarn/pnpm install โดยตรงแล้ว ยังสามารถทำงานได้ในหลายสถานการณ์ เช่น transitive dependency, ส่วนขยาย editor, การรันสคริปต์

  • โดยเฉพาะส่วนขยาย Nx Console สำหรับ VSCode (เวอร์ชัน 18.6.30 ~ 18.65.1) อาจติดตั้ง nx@latest อัตโนมัติเมื่อเปิด editor และทำให้ postinstall ทำงาน

  • โดยพื้นฐานแล้วต้องระวังว่าอาจมีการติดตั้งโมดูล NPM ในหลายจุดแม้ไม่ได้ตั้งใจ

  • ตั้งแต่ Nx Console (18.66.0) เป็นต้นไป กระบวนการติดตั้ง latest nx ถูกลบออกแล้ว

ไทม์ไลน์การโจมตีและการตอบสนอง

21 สิงหาคม

  • 4:31 PM: PR ที่มีช่องโหว่ Bash injection ถูก merge
  • 10:48 PM: โพสต์ชี้ช่องโหว่ถูกเผยแพร่บน X (เดิมคือ Twitter)

22 สิงหาคม

  • ช่วงบ่าย: เริ่มการสอบสวนภายใน และ rollback workflow ที่มีช่องโหว่ (ยังไม่สมบูรณ์)
  • มีการนำ CodeQL มาใช้เพื่อตรวจจับช่องโหว่ลักษณะเดียวกันใน PR ต่อไป

24 สิงหาคม

  • มี commit ใน fork ของผู้โจมตีที่บ่งชี้ว่ามีการรั่วไหลของ npm token
  • มีการสร้างและลบ PR อันตราย และ publish.yml ถูกรันโดย PR นี้

26 ~ 27 สิงหาคม (เผยแพร่เวอร์ชันอันตรายและตอบสนอง)

  • มีการเผยแพร่เวอร์ชันอันตรายของ Nx และปลั๊กอินหลายเวอร์ชันไปยัง npm ตามลำดับ
  • มีการรายงาน issue ไปยังชุมชน Github/NPM
  • 10:44 PM: ฝั่ง NPM ดำเนินการลบเวอร์ชันดังกล่าวทั้งหมดและมาตรการอื่น ๆ
  • 11:57 PM: โทเค็นสำหรับเผยแพร่แพ็กเกจที่เกี่ยวข้องกับ Nx ทั้งหมดถูกทำให้ใช้งานไม่ได้
  • 27 สิงหาคม: ออกแพตช์ Nx Console, เปิดใช้ 2FA, เปลี่ยนไปใช้ Trusted Publisher และมาตรการเพิ่มเติมอื่น ๆ

มาตรการป้องกันล่วงหน้าและการตอบสนองหลังจากนี้

  • บังคับใช้ 2FA กับ maintainer ทุกคนในองค์กร nrwl
  • ใช้กลไก Trusted Publisher ห้าม deploy แบบใช้ npm token
  • แพ็กเกจในอนาคตจะเผยแพร่หลังผ่านการตรวจสอบด้วย 2FA และกลไกความน่าเชื่อถือเท่านั้น
  • จะทยอยเพิ่มมาตรการตรวจจับความเสี่ยงเพิ่มเติม การอนุมัติ PR การป้องกัน branch และขั้นตอนอื่น ๆ

บทเรียนและแผนในอนาคต

  • เป็นการตอกย้ำความสำคัญทั้งในและต่างประเทศของ supply chain, CI/CD pipeline และการจำกัดสิทธิ์ของ workflow ให้เหลือน้อยที่สุด
  • หลังทบทวนภายในทีมแล้ว มีแผนจะแชร์สิ่งที่ได้เรียนรู้กับชุมชน

ช่องทางติดต่อ

  • สามารถติดต่อได้ที่ security@nrwl.io

อ้างอิงและภาคผนวก

  • มี issue สำคัญของ Github, ไทม์ไลน์ และโพสต์ที่เกี่ยวข้อง
  • มีตัวอย่างสคริปต์ telemetry.js ภายในแพ็กเกจที่ติดเชื้อ
  • สคริปต์นี้รวบรวมพาธของไฟล์ข้อความสำคัญในระบบไฟล์เพื่อสร้าง inventory

สรุปท้ายเรื่อง

  • ควรอัปเดตและติดตั้งแพตช์ล่าสุดของ Nx และปลั๊กอินที่เกี่ยวข้อง
  • แนะนำให้เปลี่ยนข้อมูลยืนยันตัวตนสำคัญ เช่น npm, Github ทันที
  • เหตุการณ์นี้เตือนให้เห็นว่าความหละหลวมด้าน supply chain security และการจัดการสิทธิ์ของ workflow อาจนำไปสู่เหตุร้ายแรงขนาดใหญ่ได้

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

 
GN⁺ 2025-08-29
ความคิดเห็นบน Hacker News
  • อยากเตือนเป็นระยะ ๆ ให้ปิดการทำงานของสคริปต์ npm install

    • ตัวอย่างคือใช้คำสั่งนี้:

        npm config set ignore-scripts true [--global]
      
    • ตั้งค่านี้ได้ง่ายทั้งระดับโปรเจกต์หรือแบบ global

    • ทุกวันนี้แทบไม่มีแพ็กเกจที่ถูกต้องตามปกติซึ่งทำงานไม่ได้หากไม่มีสคริปต์ ดังนั้นส่วนใหญ่จึงไม่มีปัญหา

    • ถ้ามีแพ็กเกจที่จำเป็นต้องใช้จริง ๆ ก็รับมือได้ด้วยการทำสคริปต์ติดตั้งแยกไว้ แล้วรันด้วยตนเองในโฟลเดอร์นั้น

    • มันไม่ใช่วิธีแก้ supply chain attack แบบครอบจักรวาล แต่ก็ช่วยบล็อกการโจมตีจำนวนมากที่มาทาง npm ได้อย่างมีประสิทธิภาพ

    • ดูรายละเอียดเพิ่มเติมได้ในเอกสารทางการของ npm config

    • ผมเองก็ใช้ bubblewrap แยก npm, pnpm, yarn และทุกเซสชันที่พวกมันรัน ออกจากระบบด้วย

      • ซอร์สโค้ดของผมมีอยู่แค่ใต้ ~/code และผมบันทึก bash script ด้านล่างไว้เป็น npm ต้น ๆ ของ PATH
      • แพ็กเกจแมนেজเจอร์ตัวอื่นก็ลิงก์ด้วย symlink/hardlink:
        #!/usr/bin/bash
        bin=$(basename "$0")
        exec bwrap \
          --bind ~/.cache/nodejs ~/.cache \
          --bind ~/code ~/code \
          --dev /dev \
          --die-with-parent \
          --disable-userns \
          --new-session \
          --proc /proc \
          --ro-bind /etc/ca-certificates /etc/ca-certificates \
          --ro-bind /etc/resolv.conf /etc/resolv.conf \
          --ro-bind /etc/ssl /etc/ssl \
          --ro-bind /usr /usr \
          --setenv PATH /usr/bin \
          --share-net \
          --symlink /tmp /var/tmp \
          --symlink /usr/bin /bin \
          --symlink /usr/bin /sbin \
          --symlink /usr/lib /lib \
          --symlink /usr/lib /lib64 \
          --tmpfs /tmp \
          --unshare-all \
          --unshare-user \
          "/usr/bin/$bin" "$@"
        
      • ถ้าทำแบบนี้ แพ็กเกจแมนেজเจอร์จะเข้าถึงได้แค่ ~/code และไลบรารีของระบบแบบอ่านอย่างเดียว
      • bubblewrap มีความเสถียร และเป็นเครื่องมือที่ใช้ใน Steam กับ flatpak เป็นต้น
    • ใช้ pnpm ก็เป็นอีกทางเลือก รุ่นล่าสุดจะเพิกเฉยต่อ lifecycle scripts ทั้งหมดโดยค่าเริ่มต้น และจะรันได้ก็ต่อเมื่อเพิ่มเข้า allowlist ทีละตัว

    • ทุกครั้งที่ได้ยินคำแนะนำนี้ ผมจะนึกถามอยู่ข้อหนึ่ง: ในความเป็นจริงก็ไม่มีนักพัฒนาคนไหนอ่านโค้ดเป็นหลักสิบถึงหลักร้อยล้านบรรทัดที่ npm ติดตั้งมาให้อยู่แล้ว

      • เวิร์กโฟลว์ของนักพัฒนาส่วนใหญ่จะเป็นแบบนี้
        1. git clone
        2. npm install (ตรงนี้มีความเสี่ยงว่าจะติดตั้งแพ็กเกจอันตราย ถึงจะเพิกเฉย post-install script ก็กันได้แค่ชั่วคราว)
        3. npm run (ตรงนี้แพ็กเกจอันตรายจะถูกรันและเครื่องก็ติด)
      • ถ้าจะให้คำแนะนำนี้ช่วยได้จริง ก็ต้องมีการเฝ้าดู/ตรวจสอบ node_modules ทั้งหมดระหว่างข้อ 2 กับ 3 แต่ไม่มีใครทำแบบนั้น
    • ผมรันทุกเครื่องมือที่อิง npm ภายใน Docker container โดยไม่ให้เข้าถึงอะไรนอกจากไดเรกทอรีปัจจุบัน

      • มันช่วยลด attack surface ได้มาก
      • วิธีทำดูได้ที่บล็อกนี้
    • ผมสงสัยว่าทำไมคำแนะนำแบบนี้ถึงไม่ถูกใช้กับ setup.py (Python) หรือ build.rs (Rust) เหมือนกัน

      • ผมสงสัยว่าเป็นเพราะ npm มักถูกใช้ผิดวัตถุประสงค์ไปถึงขั้นแจกจ่ายซอฟต์แวร์ด้วย (เช่น แจกโปรแกรมแยก) ขณะที่ package manager ของภาษาอื่นใช้จัดการไลบรารีอย่างเดียวหรือเปล่า
      • ดูการถกเถียงที่เกี่ยวข้องได้ที่นี่
  • เวลาจะเพิ่ม dependency ใหม่ ต้องมีวัฒนธรรมที่คิดทบทวนอีกครั้งจริง ๆ

    • ปีนี้เกิด supply chain attack เยอะมากจริง ๆ

    • สัปดาห์นี้ผมจะเพิ่ม progress bar ที่มีตัวนับสถิติ 8 ตัวลงในโปรเจกต์ Go

    • พอไปค้นไลบรารีก็เจอว่าโค้ดยาวเกิน 3,000 บรรทัด เลยให้ LLM ช่วยสร้างโค้ด UI ง่าย ๆ แล้วจบได้ในไม่ถึง 150 บรรทัด

    • มันทำงานตรงตามที่ต้องการโดยไม่มี dependency และเรียบง่ายมากจนทุกคนอ่านและปรับปรุงได้ง่าย

    • ฟังก์ชันก็มีแค่ลบเอาต์พุตบนเทอร์มินัลแล้ววาดใหม่ทุกวินาที พร้อมรองรับ thread-safe

    • รวมทั้งลงมือใช้และรีวิวก็ใช้เวลาแค่ 25 นาที

    • ถ้าไม่ต้องการฟีเจอร์สถิติซับซ้อน ใช้โค้ดราว 30 บรรทัดก็ทำ progress bar ได้แล้ว

    • ต่อไปเวลาเลือกว่าเพิ่ม dependency ดีไหม การเขียนเองน่าจะเหมาะกับผมมากกว่า

    • ผมไม่มีทรัพยากรมากพอจะคอยเฝ้าดูทุกการอัปเดตของทุกแพ็กเกจ

    • เห็นด้วยกับประเด็นนี้ และต้องบอกว่าตอนช่วงแรกที่ “package manager รายภาษา” เริ่มแพร่หลาย ผมรู้สึกไม่สบายใจมาก

      • ผมทำงานสาย system programming เลยมอง pip, npm ฯลฯ อยู่ห่าง ๆ
      • แต่พอย้ายมาโปรเจกต์ Rust แล้วเห็นว่าแค่ตั้งค่า Cargo บรรทัดเดียวก็ไปดึง dependency ที่ไม่ผ่านการตรวจสอบเป็นสิบ ๆ ตัวจากอินเทอร์เน็ตมาใช้ได้เลย ก็รู้สึกว่าอันตราย
      • แล้วมันก็เกิดขึ้นจริง ผมไม่คิดว่านี่เป็นทิศทางที่ดี (แต่ก็ไม่ได้คาดหวังว่าเราจะย้อนกลับ เพราะความปลอดภัยคอมพิวเตอร์ก็แทบไม่มีอยู่จริงอยู่แล้ว...)
    • ผมคิดว่าแนวทางแบบ cargo vet น่าจะเป็นทิศทางในอนาคต: แนะนำ cargo vet

      • แน่นอนว่าการต้องมีระบบแบบนี้ในทุก ecosystem ของทุกภาษา ย่อมมี overhead สูง
      • อินเทอร์เน็ตยุคแรกหรืออีเมลก็เคยมีช่วงเวลาดี ๆ แต่สุดท้ายก็พังเพราะสแปมและการค้า
      • ตอนนี้แม้แต่ห่วงโซ่ dependency ก็เริ่มโดนผลกระทบแบบเดียวกัน
      • นี่จึงเป็นอีกเหตุผลที่เรารักษาสภาพแวดล้อมดี ๆ ไว้ไม่ได้
    • ความต่างระหว่างการลงมือเขียนเองกับการใช้ไลบรารีเป็นเรื่องธรรมดาอยู่แล้ว

      • โดยธรรมชาติแล้วไลบรารีต้องเป็นของใช้ทั่วไป รองรับหลายสภาพแวดล้อม ยืดหยุ่น และตั้งค่าได้ จึงเลี่ยงไม่ได้ที่จะมีโค้ดยาว
    • ผมเกลียดไลบรารี progress bar พวกนี้มาก โดยเฉพาะตัวที่ทำ emacs shell พัง (expo, eas ฯลฯ)

      • ไม่เข้าใจว่าทำไมไม่พิมพ์แบบง่าย ๆ อย่าง ..10%..20%..30% หรือ Uploading…
      • ผมคิดว่า terminal control code ควรใช้เฉพาะกับ TUI หรืออินเทอร์เฟซแบบโต้ตอบเท่านั้น
    • ทีมของเราที่บริษัทประกันรายใหญ่ดูแล monorepo ขนาดใหญ่และไลบรารีต่าง ๆ โดยมี NX เป็นศูนย์กลาง

      • เราจัดการแอปอิสระมากกว่า 10 ตัวและไลบรารีมากกว่า 25 ตัวใน monorepo เดียว และผูกกับ CI/CD หนักมาก
      • เราเคยลองทั้ง lerna, rushjs, yarn workspaces ฯลฯ แต่ยังไม่มีเครื่องมือไหนทำงานได้ดีเท่า NX (แม้แต่ lerna ก็สุดท้ายถูก NX ซื้อไป ส่วน rushjs ก็แทบไม่ถูกดูแลแล้ว)
      • ถ้าใครมีวิธีหรือทางเลือกที่ช่วยจัดการความซับซ้อนของ frontend monorepo ได้จริง อยากให้ช่วยแนะนำ
      • จากเหตุการณ์ความปลอดภัยครั้งนี้ คนที่สนใจทางเลือกน่าจะมีเยอะ เลยอยากฟังความเห็นหลากหลาย
  • แทนที่จะโทษ Nx หรือ Anthropic หรือแค่ตัวแพลตฟอร์ม เราควรกลับไปคิดถึงสาเหตุจริง

    • สาเหตุโดยตรงของการโจมตีครั้งนี้คือใช้ “token” ที่ถูกขโมยมาอัปโหลดแพ็กเกจอันตรายได้
    • แต่นั่นเป็นแค่วิธีส่งมอบ ส่วนสาเหตุรากที่ทำให้สำเร็จคือเรื่องต่อไปนี้:
      1. repository ของ package manager ไม่บังคับให้มี artifact signing จึงตรวจสอบไม่ได้ว่าเป็นสิ่งที่นักพัฒนาที่มีสิทธิ์สร้างขึ้นจริง
      2. code signing ก็ไม่ได้บังคับเช่นกัน
      3. (คาดว่า) ไม่มี heuristic ป้องกันการอัปโหลดผิดปกติ เช่น ตรวจจับพฤติกรรมผิดปกติ, IP ใหม่, เปลี่ยนประเทศ ฯลฯ
      4. (คาดว่า) การใช้ token ที่ถูกขโมยไม่จำเป็นต้องผ่าน MFA
      5. (คาดว่า) token ไม่ใช่แบบใช้ครั้งเดียว
      6. (คาดว่า) token ไม่ได้ถูกเก็บไว้ใน password manager ที่บังคับให้มีการอนุมัติแบบ manual หากจะใช้จากแอปหรือเซสชันใหม่
    • ทั้งหมดนี้คือสิ่งที่ป้องกันได้อย่างสมบูรณ์
    • ถ้าคุณเป็นผู้เสียหายจริงและมี repository ใหม่ถูกสร้างขึ้นใน GitHub ของตัวเอง ก็แปลว่าคุณเองก็ปกป้อง authentication token ของตัวเองได้ไม่ดีพอเช่นกัน
    • การที่มาตรการป้องกันเหล่านี้ยังไม่กลายเป็นค่าตั้งต้นพื้นฐาน ถือเป็นความล้มเหลวครั้งใหญ่ของทั้งอุตสาหกรรมซอฟต์แวร์
      • การโจมตีแบบนี้เกิดซ้ำต่อเนื่องมาหลายปีแล้ว
      • เราเป็นนักพัฒนาเองแท้ ๆ แต่กลับไม่ยอมแก้มัน
    • เพราะแบบนี้ผมจึงสนับสนุนให้ซอฟต์แวร์มี “กฎหมายควบคุมงานก่อสร้าง” แบบเดียวกับวงการอาคาร ที่มีทั้งการตรวจสอบและค่าปรับ
      • การโจมตีนี้อาจสร้างความเสียหายร้ายแรงกับองค์กรนับหมื่นแห่งในภาคการเงิน พลังงาน โทรคมนาคม โรงพยาบาล ทหาร ฯลฯ

      • เมื่อ AI แพร่หลาย ขนาดและผลกระทบของการโจมตีก็จะยิ่งใหญ่ขึ้น

      • เราไม่ได้เขียนซอฟต์แวร์อย่างมีความรับผิดชอบพอ จึงอาจต้องถูกบังคับให้ทำตามมาตรฐานความปลอดภัยและความมั่นคงแบบเดียวกับกฎหมายอาคาร

      • พอสังเกตก็รู้ว่าการที่สภาพแวดล้อมคอมพิวเตอร์ส่วนบุคคลทุกอย่างถูกรวมอยู่ในพื้นที่เดียว เป็นเรื่องอันตรายกว่าที่คิด

        • ทั้งบน Mac, Windows, Linux ล้วนมี crypto wallet, credential file และแอปหลายตัวปะปนอยู่ด้วยกัน
        • ตอนนี้เครื่องมือที่ช่วยแยกสิ่งเหล่านี้ให้ดี ๆ ยังแย่มาก
        • บางครั้งเวลาเปิด Windows VM หลายตัวบน macOS ผมก็จินตนาการถึงอนาคตที่เราสามารถ Alt-Tab เข้าไปใน container หรือ VM ที่แยกตามงานได้อย่างสะอาดและลื่นไหล
        • เช่น gaming container, container สำหรับงานคริปโตโดยเฉพาะ, container แยกตามโปรเจกต์โค้ดหลักแต่ละตัว เป็นต้น
        • การที่แค่ติดตั้ง VSCode extension ตัวเดียวก็อาจทำให้ Bitcoin key รั่วได้ เป็นความจริงที่เหลวไหลมาก
        • ผมคิดว่ากฎแบบ “กฎหมายอาคารซอฟต์แวร์” คงแก้ปัญหารากแบบนี้ไม่ได้ทั้งหมด
        • เราจำเป็นต้องมีข้อกำหนดระดับระบบปฏิบัติการที่ควบคุมการเข้าถึงข้อมูลระหว่างแอปด้วย และต้องถกกันต่อทั้งเรื่องการออกแบบและการบังคับใช้จริง
      • ผู้เสียหาย 50% ถูกโจมตีผ่าน VS Code และทำงานเฉพาะบน Linux กับ macOS

        • ดูการวิเคราะห์รายละเอียดการโจมตีนี้ได้ที่บทวิเคราะห์ในบล็อก
        • เมื่อติดแล้ว:
          • ในขั้น postinstall จะเก็บ asset สำคัญ เช่น credential ของผู้ใช้ (crypto wallet, GitHub และ npm token, SSH key ฯลฯ)
          • ใช้เครื่องมือ AI command line (Claude, Gemini, Q ฯลฯ) เพื่อเก็บข้อมูลและทำการสอดแนมเชิงรุก
          • ข้อมูลที่ขโมยได้จะถูกเข้ารหัส base64 ซ้อนสองชั้นสามชั้นก่อนอัปโหลดไปยัง repository บน GitHub ของผู้โจมตี (เช่น s1ngularity-repository)
          • พบ repository หลายพันรายการ
          • มี GitHub token มากกว่า 1000 รายการ, credential ของ cloud และ NPM หลายสิบรายการ, และไฟล์ราว 20,000 ไฟล์ถูกขโมย
          • ส่วนใหญ่ถูกรันผ่าน NX VSCode extension หรือใน build pipeline (เช่น GitHub Actions)
          • เวลา 9AM UTC ของวันที่ 27 สิงหาคม GitHub ปิดการใช้งาน repository ของผู้โจมตีทั้งหมด แต่ข้อมูลก็รั่วออกไปในช่วงเวลาสูงสุดราว 8 ชั่วโมงแล้ว
          • การเข้ารหัส base64 สามารถกู้ข้อมูลต้นฉบับกลับมาได้ง่าย ดังนั้นต้องถือว่าข้อมูลเหล่านี้ถูกเปิดเผยไปแล้วทั้งหมด
      • การที่ GitHub token/credential ไม่ได้ถูกเก็บในเครื่องมือจัดการรหัสผ่านแบบต้องปลดล็อกเอง ก็เป็นส่วนหนึ่งที่ต้องโทษ GH CLI ด้วย

        • GH CLI พอล็อกอินครั้งเดียวก็มีสิทธิ์อัปโหลด repository และแทบไม่ค่อยบังคับ re-authenticate
        • AWS CLI แล้วแต่นโยบาย แต่โดยทั่วไปจะหมดอายุอัตโนมัติทุก 18 ชั่วโมง
        • อย่างไรก็ตาม ทั้งสองแพลตฟอร์มล้วนทำให้ token แบบ plaintext ค้างอยู่ในเครื่องโลคัลได้ง่ายเป็นค่าเริ่มต้น
      • ผมไม่ได้ชอบไอเดีย “กฎหมายอาคารซอฟต์แวร์” นัก แต่ก็เห็นด้วยว่าอุตสาหกรรมนี้เปราะบางมากเกินไป

        • บางทีเราอาจต้องมีการกำกับดูแลจริง ๆ
      • ผมคิดว่าการจะเอาผิดเพราะมีคนใช้ไลบรารีโอเพนซอร์สฟรี เป็นแนวคิดที่หยิ่งยโส

        • ถ้าต้องการการรับประกันจริง ๆ ก็ควรซื้อลิขสิทธิ์
        • มันเหมือนนโยบายตรวจสอบเชิงศัตรูของ Google ต่อซอฟต์แวร์ฟรีที่พยายามจะโยนความรับผิดชอบให้คนทำ
  • ช่วงนี้งานพัฒนาส่วนใหญ่ของผมทำอยู่ใน VM

    • ผมรู้สึกว่าระดับความปลอดภัยของสภาพแวดล้อมทุกวันนี้ต่ำจนยอมรับไม่ได้

    • โอกาสที่ agent (ซอฟต์แวร์แบบเอเจนต์) จะกลายเป็นเวกเตอร์มัลแวร์เพิ่มขึ้นมหาศาล

    • หากผู้โจมตีเจาะเข้ามาในเครื่องได้แล้ว นี่ก็เป็นยุคที่พวกเขาจะเล่นงานข้อมูลมูลค่าเกิน 1,000 ดอลลาร์, crypto key, password, ข้อมูลส่วนตัว, ข้อมูลการเงิน ฯลฯ ได้ทุกเมื่อ

      • ผมก็ทำคล้ายกัน โดยทำงานใน Podman container และไม่แชร์อะไรกับโฮสต์นอกจากไดเรกทอรีซอร์สโค้ด

      • ปัญหาส่วนหนึ่งมาจากโมเดลความปลอดภัยของพีซีแบบดั้งเดิม (Linux/Windows)

        • มันเป็นโมเดลที่ถือว่า executable นั้นเชื่อถือได้ และเปิดให้ไฟล์เหล่านี้เข้าถึงข้อมูลส่วนตัวทั้งหมดของผม ซึ่งไม่เหมาะกับโลกปี 2025 แล้ว
        • ฝั่งมือถือ (Android) แก้เรื่องนี้ได้เป็นส่วนใหญ่ แต่บนพีซีนอกจาก SELinux ก็ยังไม่มีทางเลือกเชิงลึกที่เด่นชัดนัก
      • ถ้าคุณชอบแนวทางแบบนี้ ผมอยากแนะนำ Qubes OS มันให้ UX ที่ดีสำหรับการทำทุกอย่างใน VM

        • มันเป็น daily driver ของผม และขอแนะนำอย่างแรง
      • แต่ต้องบอกไว้ว่า การตั้งค่าสภาพแวดล้อมแบบนี้ทำได้ยากมากหรือมีต้นทุนค่อนข้างสูง เพราะข้อจำกัดจาก ecosystem และประวัติศาสตร์ของซอฟต์แวร์

  • Claude Code เป็นเครื่องมือปฏิวัติด้าน productivity

    • แต่ในทางกลับกันก็มีประเด็นความปลอดภัยดังนี้:

      • เป็นแอป NodeJS
      • ตอนติดตั้งใช้วิธี curl แล้ว pipe เข้า bash (มีความเสี่ยง remote code execution)
      • LLM สามารถแตะได้ทั้ง file system, คำสั่ง และอย่างอื่นอีกมาก
    • มีช่องโหว่ด้านความปลอดภัยอย่างน้อย 3 ข้อนี้ ผมจึงไม่อยากรันมันนอก sandbox อย่าง VM/container/dev box เฉพาะทาง

      • ผมก็เห็นด้วยว่าควรรัน agent อยู่ใน sandbox

        • แต่อีกด้านหนึ่ง Claude code ก็ไม่ได้สั่งรันคำสั่งมั่ว ๆ ตั้งแต่แรกโดยไม่มีการอนุญาตแยกต่างหาก
      • แต่แล้วไงล่ะ?

        • ผู้ใช้ต้องกดปุ่มรันเองถึงจะทำงาน
        • โปรแกรมส่วนใหญ่ก็มีสิทธิ์เหมือนกันอยู่แล้ว
        • เทอร์มินัลก็แตะไฟล์ซิสเต็มได้เหมือนกัน แต่ก็ไม่ได้รันเองสุ่ม ๆ
        • Claude Code ไม่ได้ทำตัวเหมือน daemon ที่ลุกขึ้นมาพังเครื่องผมเอง และจะไม่ทำอะไรหากไม่มีคำสั่งชัดเจน
        • สำหรับผม Claude Code คือเครื่องมือที่ดีที่สุดที่เคยใช้มาในรอบ 30 ปี
        • ผมไม่ค่อยสนใจด้วยซ้ำว่า “attack vector” คืออะไร ถ้ามีใครเข้าคอมผมโดยไม่ได้รับอนุญาต มันก็ไม่ใช่ปัญหาของ Claude Code อย่างเดียวอยู่แล้ว
      • จุดที่อันตรายจริงคือมันอัปเดตอัตโนมัติโดยที่ผู้ใช้ไม่เกี่ยว และเท่ากับให้สิทธิ์ Anthropic ทำ RCE ระหว่างรันได้

  • ผมสงสัยว่า package manager ควรมีการตั้งค่าอย่าง ‘minimum package age’ ไหม

    • ตัวอย่างเช่น ให้เพิกเฉยแพ็กเกจที่เพิ่งเผยแพร่ไม่ถึง 24~36 ชั่วโมง

    • ก่อนหน้านี้ผมเคยเจอเคสคล้ายกัน แพ็กเกจอัปเดตมาพังทุกอย่าง แล้วไม่กี่ชั่วโมงต่อมาก็ถูกแก้/ลบทันที

      • GitHub dependabot เพิ่งเพิ่มฟีเจอร์แบบนี้มาหมาด ๆ

      • Renovate bot ก็มีตัวเลือกนี้มานานแล้ว (minimumReleaseAge) และตอนนี้ dependabot ก็รองรับแล้ว

        • package manager สนใจแค่ติดตั้งเวอร์ชันล่าสุด แต่คุณใช้เครื่องมือฟรีพวกนี้มาจัดการการอัปเดตตามรอบเวลาที่เหมาะสมได้
        • ecosystem ของ JavaScript กำลังค่อย ๆ ไปสู่การรวมศูนย์มากขึ้น และเครื่องมือรับมือ supply chain attack ก็เริ่มมีทีละน้อย
        • NPM, PNPM, Bun รุ่นล่าสุดจะไม่รัน postinstall script โดยค่าเริ่มต้น และจะรันเมื่อระบุชัดเจนเท่านั้น (แต่สุดท้ายก็ยังเป็นการรันโค้ดของคนอื่นอยู่ดี)
      • ไม่ถึงระดับ OS แต่เครื่องมือ uv ของ Astral ก็มีตัวเลือกแบบนี้สำหรับแพ็กเกจ Python

      • ใน npm install เองก็มีแฟลกสำหรับติดตั้ง dependency ที่มีอยู่ก่อนช่วงเวลาหรือวันที่กำหนดเท่านั้น

        • npm install --before (วันที่ย้อนหลังไป 2 วัน) จะไม่ติดตั้ง dependency ที่เกิดหลังจากวันนั้น
      • ผมตั้ง save-exact=true ไว้ใน .npmrc และใช้แค่ lockfile กับการอัปเดตด้วยตนเอง

        • ไม่จำเป็นต้องอัปเดตแพ็กเกจบ่อยนัก
        • หลังผ่านเหตุการณ์ fakerjs มาก็รู้สึกว่าควรระวังให้มาก
  • ผมสงสัยว่า claude code จะรันพรอมป์ต์แบบนั้นจริงไหม เลยลองทดสอบ

    • ผลออกมาเป็นแบบนี้:
      • “คำขอนี้ดูเหมือนเป็นการค้นหา/จัดรายการไฟล์อ่อนไหว เช่น crypto wallet, private key ฯลฯ ซึ่งอาจถูกนำไปใช้ในทางที่ผิด จึงไม่สามารถช่วยได้”

      • มันแนะนำได้เฉพาะคำขอที่ชอบด้วยกฎหมาย เช่น การตรวจความปลอดภัย, การวิเคราะห์ช่องโหว่, การเขียนเครื่องมือมอนิเตอร์, การทำความเข้าใจสิทธิ์ไฟล์, การออกแบบขั้นตอนสำรองข้อมูล เป็นต้น

      • เรามีเคสสำเร็จอย่างน้อย 250 เคสแล้ว (แปลว่าบางพรอมป์ต์ผ่านได้)

        • โดยเฉลี่ยแล้ว Claude ปฏิเสธมากกว่าชัดเจน และ Q ก็ปฏิเสธได้ดีเหมือนกัน (เพราะอิง Claude จึงคล้ายกัน)
        • อ้างอิงไว้ว่า ผมรับมือประเด็นพวกนี้ทั้งวันและได้เขียนรายงานวิเคราะห์นี้ด้วย
      • ในสถานการณ์จริง ทุกครั้งที่ผมเห็น Claude กับโมเดลอื่นแข่งกันเรื่องการปฏิเสธ Claude จะเหนือกว่ามากในด้าน refusal/safeguard

        • ตัวอย่างดัง: ChatGPT เคยปล่อยให้ผู้ใช้ที่มีปัญหาสุขภาพจิตถูกเรียกว่า “The Oracle” ต่อไปเรื่อย ๆ ขณะที่ Claude จะปฏิเสธและแนะนำให้ไปปรึกษาผู้เชี่ยวชาญ
        • แน่นอนว่าคำตอบแนว “ถูกต้องครับ/ค่ะ!” ซ้ำ ๆ ก็น่าหงุดหงิด แต่ก็ต้องยอมรับและชื่นชมว่า Anthropic ใส่ใจกับการปฏิเสธและความปลอดภัยมากกว่าคู่แข่งหลายรายจริง
  • ระบบปฏิบัติการควรทำให้แอปไม่สามารถเข้าถึงทั้ง file system ได้แบบไร้ขีดจำกัดเป็นค่าเริ่มต้น

    • บางแอปมี apparmor/selinux profile ให้ใช้ และ firejail ก็ใช้ได้เช่นกัน

    • แต่ในแง่ UX มันจำเป็นต้องเปลี่ยน

      • นี่เป็นปัญหาใหญ่จริง ๆ มันคือผลจากการออกแบบยุคเดสก์ท็อปเมื่อ 30 ปีก่อน

        • ตรงข้ามกับ mobile OS สมัยใหม่ (เช่น iOS) ที่มี sandbox รายแอปและระบบอนุมัติสิทธิ์ที่ดีมากเป็นค่าเริ่มต้น
        • ฝั่งเดสก์ท็อปมีความพยายามหลายแบบ เช่น Qubes (OS), Firejail, bubblewrap, AppArmor ฯลฯ แต่ยังซับซ้อนหรือยากเกินไปสำหรับผู้ใช้ทั่วไป
        • OpenSnitch ก็มี แต่จำกัดเฉพาะเรื่องเครือข่าย
        • สำหรับผู้ใช้ปลายทาง การต้องมานั่งปรับสิทธิ์ละเอียดเป็นรายโปรแกรมถือเป็นภาระ
        • สุดท้ายหัวใจสำคัญคือการมีโปรไฟล์สำหรับแอปที่คนใช้กันแพร่หลายและได้รับการดูแลอย่างต่อเนื่อง
        • ผมตกใจกับความอ่อนแอของความปลอดภัยบนเดสก์ท็อป แต่โดยพื้นฐานแล้วมันเป็นปัญหาที่ยาก และถึงจะแก้ได้ก็มีแรงจูงใจทางการเงินน้อย
      • บน Linux ผมกำลังทำเครื่องมือที่โฟกัสการแยกสภาพแวดล้อมรายโปรเจกต์ด้วย Podman อยู่: probox

        • พยายามปรับปรุง UX อย่างมาก
        • ผมใช้บ่อย และอยากได้คนช่วยทำ security review
      • เรื่องความปลอดภัยของไฟล์บน Android ต้องยอมรับว่า Google ทำได้ดี

      • ผมแนะนำให้ลองเรียนรู้การใช้ bubblewrap กับสภาพแวดล้อม chroot เล็ก ๆ ด้วย

      • ผมไม่คิดว่าระบบปฏิบัติการไหนตั้งค่าเริ่มต้นให้แอป “เข้าถึงทั้งไฟล์ซิสเต็มแบบไร้ขีดจำกัด” จริง ๆ

        • ทั้ง Linux, BSD, MacOS, Windows ต่างก็มีข้อจำกัดที่เข้มแข็งอยู่
        • โดยค่าเริ่มต้นมันปลอดภัยอยู่แล้ว ตราบใดที่ผู้ใช้ทั่วไปไม่ยกระดับสิทธิ์บัญชีขึ้นไปรันอะไรอย่างเสี่ยง ๆ เอง
  • เมื่อก่อนยังพอมีความมั่นใจเลือนรางว่า “ผู้โจมตีต้องเดาสภาพแวดล้อมของฉันให้ถูกก่อน” แต่ตอนนี้พวกเขาใช้ LLM มาเรียนรู้และลงมือโจมตีให้เหมาะกับสภาพแวดล้อมได้แล้ว

    • ผมยังแอบคิดว่าตัวเองเคยคาดการณ์แนวโน้มนี้ไว้จริง ๆ

    • ดูการถกเถียงที่น่าสนใจได้จากกระทู้ก่อนหน้า

      • (ล้อเล่น) ผมคือผู้โจมตี มีไอเดียใหม่ ๆ ไหม? (/s)
  • ส่วนที่น่าขนลุกจริง ๆ คือ ตอนนี้มันใช้ local LLM ค้นหา secret ได้แล้ว

    • ปัญหา “postinstall” ยังเหมือนเดิม แต่ payload เป็นคนละยุคไปแล้ว

    • ตรรกะอันตรายถูกซ่อนอยู่ในพรอมป์ต์แทนที่จะอยู่ในโค้ด จึงทำให้ static analysis แบบเดิมตรวจจับได้ยาก

    • เลยอดคิดไม่ได้ว่าควรป้องกัน malicious prompt พวกนี้อย่างไร

      • ดูเหมือนว่าทางออกมีแค่รัน Claude Code ใน container/VM ที่แยกขาดจริง ๆ และรีวิวโค้ดทุกชิ้นที่จะ commit ด้วยตนเอง