- เกิดการโจมตีแบบ supply chain ในระบบนิเวศ NPM โดยมีการฝัง มัลแวร์แบบแพร่กระจายตัวเอง ลงในแพ็กเกจมากกว่า 40 รายการ รวมถึง @ctrl/tinycolor ที่ได้รับความนิยม ทำให้ซีเคร็ตในสภาพแวดล้อมการพัฒนาและแม้แต่ข้อมูลรับรองของ CI/CD สามารถติดเชื้อแบบลูกโซ่ได้ โดยเวอร์ชันที่ติดเชื้อถูกลบออกจาก npm แล้ว
- เพย์โหลดของการโจมตีจะรัน Webpack bundle (
bundle.js, ~3.6MB) แบบอะซิงก์ระหว่างขั้นตอนติดตั้ง npm และทำ การเก็บรวบรวม credentials ในวงกว้าง ผ่านตัวแปรสภาพแวดล้อม ระบบไฟล์ และ cloud SDK - ลอจิกอันตรายใช้ NpmModule.updatePackage เพื่อบังคับแพตช์และเผยแพร่แพ็กเกจอื่น ทำให้เกิด การแพร่กระจายแบบต่อเนื่อง, และฉีดเวิร์กโฟลว์ shai-hulud เข้าไปใน GitHub Actions เพื่อขโมยซีเคร็ตขององค์กรด้วย
toJSON(secrets) - ข้อมูลที่รวบรวมได้จะถูกส่งออกโดยการสร้าง ที่เก็บ GitHub แบบสาธารณะชื่อ ‘Shai-Hulud’ ทำให้ข้อมูลรั่วไหลภายใต้ภาพลักษณ์ของกิจกรรมการพัฒนาปกติ และมีความสามารถในการหลบเลี่ยงการตรวจจับสูง
- มีการเข้าถึงโทเค็นและ metadata endpoint ของ AWS/GCP/Azure/NPM/GitHub รวมถึงการค้นหาซีเคร็ตโดยอาศัย TruffleHog อย่างแนบเนียน
- จำเป็นต้องลบแพ็กเกจทันที ทำความสะอาดรีโพซิทอรี เปลี่ยนข้อมูลรับรองทั้งหมด พร้อมทั้ง ตรวจสอบ CloudTrail/GCP Audit logs, บล็อก webhook, และนำ branch protection/Secret Scanning/นโยบาย cooldown มาใช้
Affected Packages
- มีรายงานว่าได้รับผลกระทบ รวม 195 แพ็กเกจ/เวอร์ชัน โดยตัวอย่างสำคัญได้แก่ @ctrl/tinycolor(4.1.1, 4.1.2), หลายแพ็กเกจในเนมสเปซ @ctrl/, กลุ่มโมดูล @crowdstrike/, ngx-bootstrap/ngx-toastr/ng2-file-upload/ngx-color ครอบคลุมทั้งระบบนิเวศ Angular/เว็บ UI, สแตกมือถือ @nativescript-community/ และ @nstudio/, ทูลเชนด้านชีววิทยาศาสตร์ของ teselagen/, รวมถึง ember-*, koa2-swagger-ui, pm2-gelf-json, wdio-web-reporter
- สำหรับ เวอร์ชันที่แน่นอน ของแต่ละแพ็กเกจ ควรอ้างอิงตารางในต้นฉบับและ ตรวจสอบไขว้อย่างละเอียด ว่ามีการใช้งานเวอร์ชันดังกล่าวหรือไม่
- ตัวอย่าง:
@ctrl/ngx-emoji-mart 9.2.1, 9.2.2,@ctrl/qbittorrent 9.7.1, 9.7.2,ngx-bootstrap 18.1.4, 19.0.3–20.0.5,ng2-file-upload 7.0.2–9.0.1เป็นต้น ซึ่งครอบคลุมในวงกว้าง
- ตัวอย่าง:
Immediate Actions Required
Identify and Remove Compromised Packages
- ตรวจสอบว่ามีแพ็กเกจที่ติดเชื้อในโปรเจกต์หรือไม่: เช่นใช้
npm ls @ctrl/tinycolorเพื่อตรวจสอบ - ลบแพ็กเกจที่ติดเชื้อทันที: เช่นรัน
npm uninstall @ctrl/tinycolor - ตรวจสอบร่องรอยในเครื่องจากการค้นหาแฮชของ
bundle.jsที่ทราบแล้ว: ใช้sha256sum | grep 46faab8a...
Clean Infected Repositories
- ลบเวิร์กโฟลว์ GitHub Actions ที่เป็นอันตราย: ลบ
.github/workflows/shai-hulud-workflow.yml - ตรวจหาและลบบรันช์
shai-huludที่ถูกสร้างบนรีโมต: ใช้git ls-remote ... | grep shai-huludแล้วตามด้วยgit push origin --delete shai-hulud
Rotate All Credentials Immediately
- จำเป็นต้อง เปลี่ยนข้อมูลรับรองทั้งหมด ได้แก่ NPM token, GitHub PAT/Actions secrets, SSH key, ข้อมูลรับรอง AWS/GCP/Azure, DB connection string, third-party token, CI/CD secrets เป็นต้น
- ต้อง หมุนเวียนทั้งหมด รวมถึงรายการที่เก็บไว้ใน AWS Secrets Manager/GCP Secret Manager
Audit Cloud Infrastructure for Compromise
- AWS: ตรวจสอบเวลาและรูปแบบของการเรียก
BatchGetSecretValue,ListSecrets,GetSecretValueใน CloudTrail และใช้ IAM Credential Report เพื่อตรวจหาการสร้างหรือใช้งานคีย์ที่ผิดปกติ - GCP: ตรวจสอบบันทึกการเข้าถึง Secret Manager ผ่าน Audit Logs และตรวจดูว่ามีเหตุการณ์ CreateServiceAccountKey หรือไม่
1 ความคิดเห็น
ความคิดเห็นใน Hacker News
ในฐานะคนที่ใช้แพ็กเกจที่โฮสต์บน npm รู้สึกว่ามันไม่ใช่วิธีที่ทำได้จริงในการเฝ้าดูทุก dependency รวมถึง dependency ของ dependency ทั้งหมดด้วยตัวเอง และเพราะไม่ได้เป็นผู้เชี่ยวชาญ TypeScript/JavaScript ก็คิดว่าคงตรวจพบมัลแวร์ที่ผู้โจมตีซ่อนไว้ได้ไม่ง่าย ช่วงนี้เลยกำลังกังวลเรื่องวิธีอัปเดตแบบ “โหมดหน่วงเวลา” คืออัปเดตเฉพาะเวอร์ชันที่ไม่ได้ใหม่ล่าสุด แต่เป็นเวอร์ชันที่ออกมานานพอสมควร โดยมองว่าถ้าแพ็กเกจถูกเปิดเผยสู่ภายนอกมาราว 6 สัปดาห์แล้ว โอกาสที่มัลแวร์จะถูกเปิดโปงก็น่าจะสูงขึ้น แต่มันก็ไม่ใช่วิธีที่สมบูรณ์แบบ และถ้าเป็นกรณีประเด็นด้านความปลอดภัยก็อยากให้มีเครื่องมือที่ตั้งข้อยกเว้นให้อัปเดตเป็นเวอร์ชันล่าสุดได้ทันที
มีฟีเจอร์ที่บทความพูดถึงตรง ๆ เลยคือ NPM Package Cooldown Check ถ้ามีการเพิ่มเวอร์ชันแพ็กเกจที่เพิ่งรีลีสภายในช่วงเวลาที่องค์กรตั้งไว้ (ค่าเริ่มต้น 2 วัน) เข้าไปใน pull request ระบบจะทำให้บิลด์ล้มเหลวอัตโนมัติ เนื่องจากการโจมตี supply chain ส่วนใหญ่ถูกตรวจพบภายใน 24 ชั่วโมง แค่รอช่วงสั้น ๆ ก็ช่วยลดความเสี่ยงด้านความปลอดภัยได้มาก
เพราะการตรวจสอบ dependency ทั้งหมดทำได้ยาก เลยอยากเสนอว่าควรลดจำนวน dependency ให้มากที่สุด และใช้เฉพาะแพ็กเกจที่เป็นที่รู้จักและน่าเชื่อถือ เท่าที่จะทำได้ ถ้าไม่ได้อยู่ในสภาพแวดล้อมที่ควบคุมได้จนเชื่อใจผู้เขียนทุกคนได้ การรักษาแนวคิด 'not-invented-here' ไว้ในระดับหนึ่งก็ดูเป็นทางเลือกที่สมเหตุสมผล
ปกติมีนิสัย pin เวอร์ชันไว้ชัดเจนใน package.json และใช้ npm ci เพื่อให้ติดตั้งเฉพาะเวอร์ชันที่ระบุใน package-lock.json ใน CI ก็รัน npm audit เพื่อรับการแจ้งเตือนถ้ามีช่องโหว่ในแพ็กเกจ แบบนี้แพ็กเกจจะอยู่ในสภาพแทบจะ “แช่แข็ง” และอายุของแพ็กเกจเองก็ช่วยลดโอกาสการติดเชื้อได้ด้วย
สำหรับผมไปไกลกว่านั้นอีก คือจะอัปเดต dependency เฉพาะตอนที่บั๊กส่งผลกับสภาพแวดล้อมการใช้งานจริงของผมเท่านั้น ต่อให้มีช่องโหว่ด้านความปลอดภัย ถ้ามันไม่กระทบก็จะปล่อยผ่านไป คิดว่านักพัฒนาส่วนใหญ่อัปเดต dependency บ่อยเกินจำเป็น ทั้งที่จริงควรทำเฉพาะเมื่อจำเป็น ถ้าต้องอัปเดตบ่อยหรือมันซับซ้อน ก็จะไม่ใช้แพ็กเกจนั้นไปเลย หรือไม่ก็ “แช่แข็ง” มันตามเกณฑ์ของผม
ใน Python ก็จำกัดการอัปเดตในลักษณะคล้ายกันได้ด้วย uv เช่นใช้คำสั่ง
uv lock --exclude-newer $(date --iso -d "2 days ago")เพื่อยกเว้นเวอร์ชันที่รีลีสภายใน 2 วันที่ผ่านมาปัญหาแบบนี้เกิดขึ้นเพราะแพ็กเกจหรือเวอร์ชันใหม่ ๆ ไม่ได้ถูกเฝ้าระวัง ทางที่ดีที่สุดคือแยกการใช้งานแบบ Debian ออกเป็นดิสทริบิวชันเสถียรที่รับเฉพาะ security patch กับ bugfix และดิสทริบิวชัน testing/unstable ที่ package maintainer คอยเฝ้าดู ทุกคนที่ทำงานกับคลังแพ็กเกจโอเพนแบบรวมศูนย์ (NPM, Python, Rust ฯลฯ) ล้วนเจอปัญหาเดียวกัน
ปัญหาอยู่ที่วัฒนธรรมของนักพัฒนา การมี dependency (รวมถึง transitive dependency) เป็นร้อย ๆ ตัวแล้วปล่อยให้อัปเดตอัตโนมัติโดยไม่คิดอะไร คือปัญหาในตัวมันเอง การเลือกเปิดให้สภาพแวดล้อม build/run ของตัวเองรับโค้ดจากบุคคลที่สามมหาศาลขนาดนั้น ย่อมต้องมาพร้อมความรับผิดชอบ
ฝั่งดิสทริบิวชันเองก็ยิ่งรู้สึกหนักกับจำนวนแพ็กเกจที่ต้องดูแลมากขึ้นเรื่อย ๆ จริง ๆ แล้วนี่ก็เป็นเหตุผลที่ ecosystem รายภาษา (เช่น CPAN, Maven, RubyGems ฯลฯ) เติบโตขึ้นมา เพราะลินุกซ์ดิสทริบิวชันอย่างเดียวให้แอปที่ผู้ใช้ต้องการได้ไม่พอ จึงเกิดช่องทางอย่าง freshmeat, linuxbrew, flatpak, PPA และอื่น ๆ ขึ้นมา ไม่คิดว่าชุมชนไหนจะมีศักยภาพมากพอจะเฝ้าดูและซัพพอร์ตหลายสาขาของไลบรารีจำนวนมหาศาลได้ทั้งหมด
ในฐานะ Debian developer รู้สึกว่าก่อนจะรวม upstream code เข้าไป ตอนนี้มี “noise” เพิ่มขึ้นเรื่อย ๆ มากจนยากมากที่จะมองเห็นการเปลี่ยนแปลงจริง โดยเฉพาะการเปลี่ยนสไตล์เล็ก ๆ น้อย ๆ หรือการอัปเดต tooling อยากให้หลีกเลี่ยงการเปลี่ยนแบบนี้ เว้นแต่จะเป็น refactoring, bug fix, การเพิ่มฟีเจอร์ หรือผลจาก tooling ที่ช่วยค้นหาโค้ดมีปัญหา ซึ่งเป็นสิ่งที่ต้องให้คนตรวจจริง ๆ
ใน Rust มีระบบชื่อ cargo vet ที่บริษัทอย่าง Google และ Mozilla เข้าร่วมเพื่อแชร์และตรวจสอบแพ็กเกจร่วมกันแบบอัตโนมัติ
คิดว่าน่าจะมีวิธีคงความกระจายศูนย์ไว้ พร้อมมีราวกันตกด้านความปลอดภัยได้ เช่น แพ็กเกจที่มีขนาดใหญ่พอควรอาจบังคับให้ต้องได้รับอนุมัติจาก 2 บัญชีที่เปิดใช้ 2FA หรือแพ็กเกจยอดนิยมอาจให้อัปโหลดขึ้น npm ได้เฉพาะผ่านระบบ reproducible build เท่านั้น แบบนี้ไม่จำเป็นต้องทิ้งความกระจายศูนย์ทั้งหมด แค่เพิ่มความยุ่งยากอีกนิดสำหรับโปรเจกต์ขนาดใหญ่
การโจมตี supply chain ที่เกิดขึ้นต่อเนื่องช่วงหลังทำให้ผมเริ่มคิดเรื่อง server rendering อย่างจริงจังมากขึ้น (โดยไม่ใช้ JavaScript) พอมี HTMX ก็รู้สึกว่าจริง ๆ แล้วไปได้ไกลมากโดยไม่ต้องใช้ JavaScript และแอปก็น่าจะเร็วและเสถียรกว่าด้วย
อยากเน้นว่าสภาพแวดล้อม JS แบบดั้งเดิมจริง ๆ แล้วคือ sandbox ที่ปลอดภัยที่สุด ตลอดเกือบ 30 ปีที่ผ่านมา มีการรันโค้ด JS ที่ไม่น่าเชื่อถือบนอุปกรณ์นับพันล้านเครื่อง แต่กรณีโจมตีวงกว้างที่สำเร็จผ่าน browser engine มีน้อยมาก อย่างไรก็ตาม สภาพแวดล้อม NodeJS และ npm นั้นอยู่ในสภาพที่ต้องออกแบบใหม่ด้านความปลอดภัยทั้งระบบ เรื่องอย่าง leftpad ก็มีต้นตอมาจากวัฒนธรรมที่เอาแม้แต่โค้ด snippet ง่าย ๆ ไปลง npm
รู้สึกแปลกที่การโจมตีแบบนี้มักถูกลดทอนให้กลายเป็นปัญหาเฉพาะของบางสภาพแวดล้อม (JavaScript) โดยอัตโนมัติ ทั้งที่จริงแม้แต่ npm เองยังมีมาตรการเสริมความปลอดภัยบางอย่างที่สภาพแวดล้อมอื่น (PyPI, Crates ฯลฯ) ยังไม่มีเลย ซึ่งดูเป็นปัญหาใหญ่กว่า
การ vendor โค้ดอาจช่วยลดความเสี่ยงได้ แต่ไม่ใช่คำตอบของปัญหาระดับรากฐาน ถ้า NPM จริงจังกับความปลอดภัย ก็ควรบังคับใช้ 2FA ในการ publish และสแกนแพ็กเกจล่วงหน้า รวมถึงบังคับให้มีการเซ็นด้วย hardware key ด้วย semver หรือ CRC อย่างเดียวไม่พอ และทั้งหมดนี้ควรถูกติดตั้งมาเป็นค่าเริ่มต้นในระบบจัดการแพ็กเกจเลย
จริง ๆ แล้วการโจมตีแบบนี้ไม่ใช่ปัญหาเฉพาะของ JavaScript แต่เกิดจากการที่นักพัฒนาไม่ได้ตรวจสอบมากพอเวลาเพิ่ม dependency ใหม่ ซึ่งใช้ได้เหมือนกันกับ ecosystem ของภาษาอื่นอย่าง Rust หรือ Go
ทุกภาษาที่พึ่งพา package manager มากและมี standard library บาง ต่างก็เปราะบางเหมือนกัน ในระยะยาวเลยคิดว่าน่าจะกลับไปใช้ vanilla JavaScript มากขึ้น Rust ก็มีการพึ่งพาแพ็กเกจสูงเหมือนกัน ตรงกันข้าม Go ดูเป็นตัวอย่างที่ดีในเรื่องนี้
คิดว่าเราต้องมีระบบที่ติดตามโค้ดขนาดเล็กที่ทำหน้าที่ติดตั้งและตรวจสอบได้ พร้อมทั้งเซ็น commit/release ด้วยกุญแจที่เชื่อถือได้และตรวจสอบยืนยันได้ ตอนนี้มีแนวทาง npm provenance ที่ใช้ sigstore อยู่แล้ว แต่ดูเหมือนว่ายังไม่ถูกใช้อย่างแพร่หลาย และยังจำกัดอยู่แค่ระดับการยืนยันผู้เผยแพร่เป็นหลัก
ตั้งแต่ปี 2016 ก็มีการ รายงานช่องโหว่นี้ต่อ NPM แล้ว (คำแนะนำจาก CERT) แต่คำตอบของ NPM คือ WAI (working as intended)
เผื่อใครไม่รู้ว่า WAI คืออะไร: ปกติเป็นตัวย่อของ “working as intended”
ต่อให้ไม่มี postinstall script เลย ก็ดูเหมือนว่าในขั้นตอน build, การสตาร์ตเซิร์ฟเวอร์, การทดสอบ ฯลฯ ถ้ามีการ import โมดูลเมื่อไร มัลแวร์ก็น่าจะถูกรันอยู่ดี สุดท้ายหลัง npm install แล้วก็ต้องมีสักช่วงที่มีการรันอะไรจริง ๆ อยู่แล้ว...
ทำให้นึกถึงคอมเมนต์ที่เคยเห็นที่นี่ตอนเหตุการณ์ left-pad มีการพูดถึง maintainer npm ชื่อดังคนหนึ่งที่มี npm package 600 ตัวและโค้ด JavaScript 1,200 บรรทัด เคสที่อยากยกเป็นตัวอย่างคือ esbuild ซึ่งแทบไม่มี dependency ภายนอกและใช้แค่ Go standard library
โปรเจกต์อื่นที่ถูกเรียกว่า “next-gen” ถ้าดู dependency chain ก็มีไม่มากเหมือนกัน เช่น biomejs, swc แต่ถ้าดู Rust ต้นฉบับจริง ๆ แล้ว biomejs, swc ก็ยังมี dependency จำนวนมาก คาดว่าถ้าโปรเจกต์แบบนี้แพร่หลาย ecosystem ของ cargo ก็คงเดินตามรอยเดิม ถ้าใครรู้จักโปรเจกต์ใหญ่ที่เขียนด้วยแนวเข้มงวดแบบ esbuild ก็อยากให้แนะนำ
หนึ่งในเหตุผลที่ย้ายไป Go คือกระแสไลบรารีแบบ purego ซึ่งมักพึ่งพาแค่ standard library กับ golang.org/x และคอมไพล์ได้โดยไม่ต้องใช้ CGO ทำให้พกพาได้ดี go mod vendor ช่วยบริหารความเสี่ยงระยะสั้นได้ แต่ไม่ใช่คำตอบระยะยาว Go เองก็ยังไม่มีการตรวจสอบแพ็กเกจแบบ end-to-end (เช่น การเซ็น/ตรวจคีย์) จึงยังมีช่องโหว่อยู่ โดยเฉพาะตอนนี้จุดสนใจไปอยู่ที่โครงสร้าง CI/CD มาก แต่ถ้าสามารถ build และ deploy ได้โดยไม่ต้องส่งต่อ signing key ก็น่าจะเพิ่มความปลอดภัยได้ ระบบจัดการแพ็กเกจน่าจะสนับสนุนลายเซ็น GPG และการเซ็น git commit แล้วค่อยนำไปใช้ในการเผยแพร่
กรณีของ eslint เป็นตัวอย่างที่น่าอึดอัดมาก ถ้าดู dependency graph จะเห็นว่ามหาศาล และถ้าผู้ดูแลไม่ให้ความสำคัญกับการลด dependency สุดท้ายก็เหลือแค่เปลี่ยนไปใช้ทางเลือกอื่น (oxlint)
ทางออกคือฟีเจอร์ที่ทำได้ง่าย ๆ ให้เขียนเองเพื่อลด dependency ภายนอก ปกติแค่นี้ก็ตัด dependency รวมได้ราว 2/3 แล้ว โดยเฉพาะอะไรที่ง่ายแบบ left-pad ก็ควรทำเองและเก็บไว้ในมือด้วยยูนิตเล็ก ๆ พร้อมการทดสอบ ภาระในการดูแลไม่ได้สูงขนาดนั้น dependency ที่ไม่จำเป็นควรถูกตัดทิ้งอย่างเด็ดขาด
สิ่งที่เห็นใน root Cargo.toml ของโปรเจกต์ Rust เป็นของทั้ง workspace และ dependency จริงของแต่ละ crate จะตื้นกว่านั้นมาก ต้องขุดลึกลงไปอีกถึงจะเห็นโครงสร้าง dependency จริง
ข้อเสียคือถ้าจะตรวจโปรเจกต์ JavaScript ตอนนี้ก็ต้องอ่าน Golang ได้ด้วย แถมยังมี post-install ที่ไปเรียก node install.js อีก สุดท้ายก็มีแค่ทางเลือกว่าจะเชื่อทั้งหมดหรืออ่านโค้ดเองทั้งหมด
ยังไม่อยากเชื่อว่า npm ยังรัน postinstall script ของทุก dependency เป็นค่าเริ่มต้นอยู่เลย Pnpm หรือ Bun จะรันเฉพาะกรณีที่อยู่ใน allowlist เท่านั้น ส่วน Composer ไม่รัน lifecycle script ของ dependency เลย คิดว่าวิธีพวกนี้ปลอดภัยกว่าเพราะ dependency package ในสภาพแวดล้อม build หรือ development มีความเสี่ยงจริง
สงสัยว่าทำไมการโจมตีใหญ่ ๆ แบบนี้ถึงไม่ค่อยได้ยินใน package manager อื่น (เช่น Rust build.rs, Python, Java ฯลฯ) ทั้งที่ไม่ใช่แค่ postinstall แต่แทบทุก ecosystem ก็ทำได้ในทางหลักการเหมือนกัน ดูเหมือนเหตุการณ์จะไปกระจุกอยู่ที่ npm เป็นหลัก
เห็นแล้วว่า ค่าเริ่มต้นของ Pnpm เปลี่ยนเป็นบล็อกสคริปต์ เลยอยากรู้ปฏิกิริยาของชุมชน (ทั้งเรื่องประสบการณ์ใช้งานจากการอนุญาตสคริปต์ และการใช้คำสั่ง allow แบบพร่ำเพรื่อ) และในชุมชน Python packaging ก็มีการถกคล้ายกันเกี่ยวกับ wheel variants อยู่ด้วย อยากอ้างอิงประสบการณ์จาก ecosystem อื่น
การโจมตีครั้งนี้แพร่ไปถึงมากกว่า 180 แพ็กเกจแล้ว ดู บล็อกของ Aikido Security
สงสัยว่าใครเป็นคนแรกที่พบการโจมตีนี้ แต่ละบล็อกให้เครดิตกันไม่เหมือนกันจนน่าสนใจ Aikido บอกว่า “เราเป็นคนค้นพบการโจมตีขนาดใหญ่” ส่วน Socket, Ox, Safety, Phoenix, Semgrep ฯลฯ ก็อธิบายกันไปคนละแบบ
ผมคือ Mackenzie ที่ทำงานอยู่ Aikido คนที่รายงานเรื่องนี้เป็นคนแรกคือ Daniel Pereira ซึ่งเป็นนักพัฒนา เขาส่งเรื่องต่อให้ Socket และ Socket ก็เป็นคนแรกที่วิเคราะห์ 40 แพ็กเกจแรกกับตัวมัลแวร์ จากนั้น Aikido พบเพิ่มอีก 147 แพ็กเกจและแพ็กเกจของ Crowdstrike ส่วน Step เป็นเจ้าแรกที่ระบุได้ว่ามัลแวร์นี้เป็นเวิร์มที่แพร่กระจายตัวเองได้ สิ่งที่น่าสนใจคือหลายองค์กรต่างก็มีบทบาทต่างกันอย่างอิสระ
ดูเหมือนว่านักพัฒนาหลายคนจะตรวจพบในเวลาใกล้เคียงกันมาก และ Step กับ Socket ก็อ้างถึงคนละคน สุดท้ายแล้วดูเหมือนว่าผู้ขายเครื่องมือความปลอดภัยในอุตสาหกรรมต่างก็จับได้ด้วยวิธีของตัวเอง ไม่ว่าจะเป็นการวิเคราะห์โค้ดด้วย AI (Socket, Aikido) หรือการมอนิเตอร์ pipeline ด้วย eBPF (Step)
ถ้ามีผู้ขายจำนวนมากตรวจพบได้อย่างอิสระแบบนี้ ก็อดสงสัยไม่ได้ว่าถ้าเอาเทคนิคพวกนั้นไปแชร์ให้ npm ตรง ๆ จะกันไม่ให้แพ็กเกจอันตรายถูกเผยแพร่ได้ตั้งแต่แรกไหม แต่ถ้าทำอย่างนั้นผู้ขายก็อาจขายระบบเตือนภัยล่วงหน้าไม่ได้ เลยดูเหมือนจะไม่อยากปล่อยออกมา
บทความต้นฉบับอ้างข้อความตรง ๆ ว่า “@franky47 พบพฤติกรรมนี้และได้แจ้งเตือนชุมชนทันทีผ่าน GitHub issue”
คิดว่าชื่อที่ผู้โจมตีตั้งว่า 'Shai Hulud' ค่อนข้างมีไหวพริบ เอาชื่อหนอนยักษ์มาตั้งให้มัลแวร์แบบเวิร์มจริง ๆ แถม bundle.js หลักก็ใหญ่ถึง 3.6MB แม้แต่มัลแวร์กลายพันธุ์ก็ยังตัวโตแบบสไตล์ npm
มีลางว่าคงอีกไม่นานสักการโจมตี supply chain ครั้งหนึ่งจะไปดึงอีกการโจมตี supply chain เข้ามาโดยบังเอิญ
มัลแวร์เองก็เดินตามกฎของมัวร์เหมือนกัน ปี 1991 tequila virus มีขนาด 2.6KB แต่ตอนนี้กลายเป็นระดับหลาย MB แล้ว