ซึ่งต้องรีบแก้ด่วน แต่พอไปดูจริงๆ กลับพบว่าเป็น Library ที่เราแทบไม่ได้เรียกใช้ฟังก์ชันนั้นเลย หรือบางทีพออัปเกรดตามที่บอก โปรเจกต์ก็พังทันที (Breaking Change)
ในโลกของ Node.js และ npm ที่มีการอัปเดต dependencies กันรายวัน ปัญหา “Vulnerability Fatigue” หรือความเหนื่อยล้าจากการไล่ตามแก้ช่องโหว่ เป็นเรื่องปกติที่ Developer ต้องเจอ
วันนี้ผมจะพาคุณไปรู้จักกับ OSV.dev (Open Source Vulnerability) และเครื่องมือ OSV-Scanner จาก Google ที่จะเปลี่ยนการจัดการช่องโหว่บน Local Machine ของคุณให้แม่นยำขึ้น ง่ายขึ้น และลดปัญหา False Positive ได้จริง
ทำไมต้อง OSV.dev? (แตกต่างจาก npm audit อย่างไร?)
หลายคนอาจสงสัยว่า ในเมื่อเรามี npm audit อยู่แล้ว ทำไมต้องหาเครื่องมืออื่น?
คำตอบคือ “ความแม่นยำ” ครับ
-
npm audit มักจะแจ้งเตือนในระดับ Package Version (แค่คุณใช้เวอร์ชันนี้ ก็ถือว่าเสี่ยงแล้ว) ทำให้เกิด False Positive สูง
-
OSV.dev ถูกออกแบบมาให้เป็น Distributed Database ที่มีความฉลาดกว่า โดยจุดเด่นที่สุดคือรองรับการระบุช่องโหว่ระดับ Function-level (ในบางภาษา) นั่นหมายความว่า ถ้าคุณใช้ Library เวอร์ชันที่มีช่องโหว่ แต่ไม่ได้เรียกใช้ฟังก์ชันที่เป็นอันตรายนั้น OSV อาจจะฉลาดพอที่จะบอกว่า “คุณปลอดภัย” (หรืออย่างน้อยก็ช่วยให้เราจัดลำดับความสำคัญได้ดีขึ้น)
Tutorial: เริ่มต้นทำ Vulnerability Scanner บนเครื่อง Dev (Local)
เราจะมาลองทำ Security Scan บนโปรเจกต์ Node.js ของคุณจริงๆ กันครับ โดยจำลองสถานการณ์ว่าคุณกำลังทำงานอยู่บนเครื่องตัวเองก่อนจะ Push Code ขึ้น Git
Step 1: ติดตั้ง OSV-Scanner
แม้เราจะสแกนโปรเจกต์ npm แต่ตัว OSV-Scanner ถูกเขียนด้วยภาษา Go เพื่อความรวดเร็ว คุณสามารถติดตั้งได้หลายวิธี:
สำหรับ macOS (ผ่าน Homebrew):
brew install osv-scanner
สำหรับ Windows (ผ่าน Winget):
winget install Google.OSV-Scanner
สำหรับ Linux/General (ผ่าน Go):
go install [github.com/google/osv-scanner/cmd/osv-scanner@v1](https://github.com/google/osv-scanner/cmd/osv-scanner@v1)
Step 2: เตรียมโปรเจกต์ Node.js
ตรวจสอบให้แน่ใจว่าในโปรเจกต์ของคุณมีไฟล์ package-lock.json หรือ yarn.lock อยู่ เพราะ OSV-Scanner จะใช้ไฟล์เหล่านี้ในการวิเคราะห์ Dependency Tree ทั้งหมดของคุณ
Step 3: รันคำสั่ง Scan
เปิด Terminal เข้าไปที่ Root Folder ของโปรเจกต์ แล้วรันคำสั่งง่ายๆ:
osv-scanner -r .
(Option -r คือ recursive ให้สแกนทุกโฟลเดอร์ย่อย)
ผลลัพธ์ที่คุณจะเห็น: ระบบจะแสดงตารางสรุปว่าเจอ Vulnerability กี่ตัว ระดับความรุนแรง (Severity) เป็นอย่างไร และลิงก์ไปยังรายละเอียดของ CVE นั้นๆ
ตัวอย่าง Output:
Scanned /path/to/my-project/package-lock.json
+-------------------------------------+------+-----------+--------------------------------+
| OSV URL | CVSS | ECOSYSTEM | PACKAGE |
+-------------------------------------+------+-----------+--------------------------------+
| [https://osv.dev/vulnerability/GHSA-](https://osv.dev/vulnerability/GHSA-) | 7.5 | npm | lodash |
| ... | ... | ... | ... |
+-------------------------------------+------+-----------+--------------------------------+
วิธีอ่านผลและทำ Patching (Remediation)
เมื่อเจอช่องโหว่แล้ว อย่าเพิ่งตระหนกครับ ให้ทำตามขั้นตอนดังนี้:
1. วิเคราะห์ความเสี่ยงจริง
คลิกที่ลิงก์ OSV URL ที่ได้จากการสแกน เพื่อเข้าไปดูรายละเอียด ในหน้านั้นจะบอกว่า:
-
Affected Versions: เวอร์ชันไหนบ้างที่โดน
-
Fixed Versions: เวอร์ชันไหนที่แก้แล้ว
2. การแก้ไข (Remediation)
สำหรับ Node.js การแก้ไขส่วนใหญ่ทำได้ 2 แบบ:
-
แบบ Auto: ลองรัน
npm audit fixดูก่อน เพื่อให้ npm พยายามอัปเกรด Minor version ที่ปลอดภัยให้ -
แบบ Manual (แนะนำ): หาก
npm audit fixไม่ได้ผล หรือเสี่ยงต่อการพัง ให้คุณแก้เวอร์ชันในpackage.jsonให้เป็นเวอร์ชันที่ระบุในช่อง Fixed ของ OSV แล้วรันnpm installใหม่
💡 Pro Tip: OSV-Scanner มีฟีเจอร์ทดลอง (Experimental) ในการช่วยแก้ปัญหาด้วยครับ ลองใช้คำสั่ง:
osv-scanner --experimental-call-analysis .(เฉพาะภาษาที่รองรับ) เพื่อดูว่าโค้ดเราเรียกใช้ฟังก์ชันที่มีปัญหาจริงไหม
🚀 Advance: แก้ช่องโหว่อัตโนมัติด้วย Guided Remediation (Experimental)
หากการไล่แก้ทีละตัว (Manual) มันยุ่งยากเกินไป หรือ npm audit fix แก้ปัญหาได้ไม่หมด ล่าสุด OSV-Scanner ได้ปล่อยฟีเจอร์ไม้ตายออกมาในชื่อ Guided Remediation หรือคำสั่ง osv-scanner fix ครับ
ฟีเจอร์นี้ฉลาดกว่าการอัปเกรดปกติ เพราะมันจะช่วย คำนวณ Dependency Graph ทั้งก้อน เพื่อหา “ทางเลือกที่ดีที่สุด” (Best Patch Set) ที่จะลบจำนวนช่องโหว่ให้ได้มากที่สุด โดยพยายามให้กระทบกับโปรเจกต์น้อยที่สุดครับ
รองรับ Ecosystem ไหนบ้าง?
ปัจจุบันฟีเจอร์นี้ยังเป็น Experimental และรองรับหลักๆ คือ npm (JavaScript) และ Maven (Java) โดยมีกลยุทธ์ (Strategy) การแก้ปัญหาดังนี้:
-
In-place (npm): แก้ไฟล์
package-lock.jsonโดยตรง เปลี่ยนเวอร์ชันเฉพาะจุดที่ปลอดภัย โดยยังเคารพเงื่อนไข (Constraint) เดิมอยู่ (ความเสี่ยงต่ำ แนะนำให้ลองก่อน) -
Relock & Relax (npm): ยอมรื้อสร้าง lockfile ใหม่ หรือขยับ Constraint ใน
package.jsonเพื่อหาเวอร์ชันที่ปลอดภัยกว่า (แก้ช่องโหว่ได้เยอะกว่า แต่เสี่ยง Breaking Change สูงกว่า) -
Override (Maven): เพิ่ม section override ใน
pom.xmlเพื่อบังคับใช้เวอร์ชันที่ปลอดภัย
วิธีใช้งาน (Step-by-Step)
⚠️ คำเตือนสำคัญ: เนื่องจากเป็นฟีเจอร์ทดลองและมีการแก้ไขไฟล์จริง คุณต้อง Backup ไฟล์หรือ Commit Code ลง Git ให้เรียบร้อยก่อนรันคำสั่งทุกครั้ง เพื่อให้สามารถ Rollback ได้หากโปรเจกต์พังครับ
1. โหมด Interactive (แนะนำสำหรับมือใหม่)
เฉพาะ npm เท่านั้นที่มีหน้าจอ Graphic (TUI) ให้เลือกกดง่ายๆ เหมือนเล่นเกม:
osv-scanner fix --interactive
หน้าจอจะขึ้นมาให้คุณเลือก Filter ได้ละเอียดมาก เช่น:
-
อยากแก้ลึกแค่ไหน (
--max-depth) -
ความรุนแรงขั้นต่ำที่สนใจ (
--min-severity) -
จะข้าม devDependencies หรือไม่ (
--ignore-dev)
เมื่อเลือกเสร็จ ระบบจะแสดงรายการ Patch ที่แนะนำ คุณสามารถกดเลือกและสั่ง Write ลงไฟล์ได้ทันที
2. โหมด Non-Interactive (สำหรับ Automation)
หากคุณต้องการเขียน Script หรือรันใน CI/CD สามารถระบุ Strategy ผ่าน Command Line ได้เลย:
ท่ามาตรฐาน: แก้ lockfile แบบ In-place (เสี่ยงต่ำ):
osv-scanner fix --strategy=in-place -L package-lock.json
ท่าไม้ตาย: แก้แบบ Relock + Relax Direct Dependencies (แก้ได้เยอะสุด):
osv-scanner fix --strategy=relax -M package.json -L package-lock.json
ข้อจำกัดที่ต้องรู้ (Known Issues)
-
ยังไม่สมบูรณ์ 100%: ยังมีปัญหากับ
peerDependenciesใน npm ที่อาจถูกจัดการได้ไม่ครบ -
Maven: ยังมีปัญหากับ dependency ที่ใช้ตัวแปร (Properties) ใน groupId/artifactId
-
Config: ปัจจุบันคำสั่ง fix ยังไม่อ่านค่าจากไฟล์ config
osv-scanner.toml
🐳 Bonus: สแกน Container Image (Docker) โดยไม่ต้องพึ่งเครื่องมือแพงๆ
ในยุค Cloud Native การสแกนแค่ Source Code อาจไม่พอครับ เพราะบ่อยครั้งช่องโหว่แฝงมากับ Base Image (เช่น node:14 หรือ ubuntu:latest) ที่เรานำมาใช้
OSV-Scanner มีคำสั่ง scan image ที่ช่วยให้คุณสแกนหาช่องโหว่ใน OS Packages (เช่น Debian/Alpine packages) และ Dependencies ภายใน Image ได้ฟรีๆ โดยรองรับ 2 วิธีหลัก:
1. สแกนจากชื่อ Image โดยตรง (Requires Docker)
วิธีนี้เหมาะสำหรับเครื่อง Local ที่มี Docker ติดตั้งอยู่แล้ว เพียงแค่ระบุชื่อ Image (ระบบจะ Pull และจัดการสร้างไฟล์ชั่วคราวให้เองโดยอัตโนมัติ)
วิธีทำ:
# รูปแบบ: osv-scanner scan image <image_name>
osv-scanner scan image my-app:latest
(Note: เครื่องมือจะทำการ docker save เบื้องหลังเพื่อวิเคราะห์ไฟล์ โดยไม่ได้รัน Container ขึ้นมาจริงๆ จึงปลอดภัยจากการรันโค้ดอันตราย)
2. สแกนจากไฟล์ .tar (No Docker Required! ⭐)
นี่คือ Killer Feature ครับ! เพราะคุณสามารถสแกน Image ได้ โดยไม่ต้องมี Docker Daemon ติดตั้งอยู่ในเครื่อง เหมาะมากสำหรับ environment ที่จำกัดสิทธิ์ หรือใน CI/CD Pipeline บางประเภท
Step 1: Export Image เป็นไฟล์ .tar มาก่อน คุณสามารถเตรียมไฟล์จากเครื่องอื่น หรือใช้ Podman ก็ได้:
# ใช้ Docker
docker save my-image:latest > my-image.tar
# หรือใช้ Podman
podman save --format=docker-archive my-image:latest > my-image.tar
Step 2: สั่งสแกนไฟล์ Archive
osv-scanner scan image --archive ./my-image.tar
💡 Trick: การดูผลลัพธ์ให้รู้เรื่อง
เนื่องจาก Container Image มักจะมี Library เป็นร้อยๆ ตัว การดูผลลัพธ์ผ่าน Terminal อาจจะตาลายได้ ผมแนะนำให้ใช้ Option --serve เพื่อดูเป็น HTML Report ครับ:
osv-scanner scan image --serve my-app:latest
คำสั่งนี้จะเปิด Web Server เล็กๆ บน localhost:8000 ให้คุณคลิกดูรายละเอียดช่องโหว่แบบ Interactive ได้ง่ายๆ เลย
⚠️ ข้อควรรู้: คำสั่ง
scan imageใช้สำหรับสแกน Image เท่านั้น ไม่สามารถใส่ path โฟลเดอร์ Source Code ผสมลงไปในคำสั่งเดียวกันได้นะครับ ต้องแยกกันรัน
⚖️ Compliance: ตรวจจับ License ที่ผิด Policy ก่อนโดนฟ้อง
นอกจากเรื่องช่องโหว่ความปลอดภัยแล้ว “ลิขสิทธิ์ซอฟต์แวร์” (Software License) ก็เป็นกับดักที่ทำให้นักพัฒนาตกม้าตายมาเยอะแล้วครับ (เช่น เผลอใช้ Library ที่เป็น GPL ในโปรเจกต์ปิดของบริษัท)
OSV-Scanner มีฟีเจอร์ลับที่ช่วยสแกน License ของ Dependency ทั้งหมดในโปรเจกต์ โดยดึงข้อมูลจาก deps.dev API มาตรวจสอบเทียบกับ Policy ของเราได้ครับ
1. ดูภาพรวม License ทั้งหมด (Basic Scan)
หากแค่อยากรู้ว่าโปรเจกต์เราใช้ License อะไรบ้าง ให้ใช้คำสั่ง:
osv-scanner --licenses path/to/repository
ระบบจะสรุปรายการ License ทั้งหมดที่พบมาให้ดูครับ
2. ตั้งกฎเหล็ก (Allowlist) ห้ามใช้ License แปลกปลอม
เราสามารถกำหนด “White List” ของ License ที่อนุญาตให้ใช้ได้ (เช่น MIT, Apache-2.0) หาก Scanner ไปเจอตัวอื่นนอกเหนือจากนี้ จะแจ้งเตือนเป็น Violation ทันที
คำสั่งตัวอย่าง (ใช้รหัส SPDX identifier):
# อนุญาตแค่ BSD-3-Clause, Apache-2.0 และ MIT เท่านั้น
osv-scanner --licenses="BSD-3-Clause,Apache-2.0,MIT" .
Note: ต้องใช้ชื่อ License ตามมาตรฐาน SPDX เท่านั้นนะครับ (เช่นใช้
Apache-2.0ห้ามใช้Apache 2.0)
3. แนวทางใช้งานจริง (Real-world Workflow)
เพื่อให้ได้ผลดีที่สุด ผมแนะนำให้คุยกับทีมกฎหมายหรือ Lead Developer เพื่อกำหนด Central Policy ครับ:
-
กำหนด List กลาง: เช่น “องค์กรเราอนุญาต
BSD-3-Clause,Apache-2.0,MITเท่านั้น” -
ฝังใน CI/CD: เพิ่ม Step ใน GitHub Actions หรือ GitLab CI ให้รันคำสั่งเช็ค License ทุกครั้งที่มีการ Pull Request
-
Fail Pipeline: ตั้งค่าให้ Pipeline พังทันทีถ้าเจอ License นอกเหนือ Policy เพื่อกันไม่ให้ Code ที่มีความเสี่ยงทางกฎหมายหลุดเข้าสู่ Main Branch
(กรณีที่เจอ License ผิดพลาด หรือต้องการยกเว้นบาง Package เป็นกรณีพิเศษ สามารถตั้งค่า Override ได้ในไฟล์ Config ของ OSV-Scanner ครับ)
📊 Reporting: เจาะลึกผลสแกนด้วย OSV-Reporter (Experimental)
การสแกนเจอช่องโหว่เป็นเรื่องดีครับ แต่ถ้าโปรเจกต์เรามีช่องโหว่เก่าค้างอยู่เป็นร้อย (Legacy Code) การรันสแกนทุกครั้งแล้วเจอลิสต์เดิมๆ อาจทำให้ทีม “ตาบอด” (Alert Fatigue) จนมองไม่เห็นช่องโหว่ ใหม่ ที่เพิ่งเข้ามาได้
Google จึงพัฒนาเครื่องมือเสริมชื่อ OSV-Reporter มาช่วยแก้ปัญหานี้ โดยเน้นการเปรียบเทียบผลลัพธ์ (Diff) และแปลงร่างไฟล์ Report ครับ
1. การติดตั้ง (Installation)
เนื่องจากยังเป็นฟีเจอร์ Experimental จึงไม่มี Binary สำเร็จรูปให้โหลด ต้องติดตั้งผ่าน Go (From Source) เท่านั้นครับ:
# ติดตั้ง OSV-Reporter เวอร์ชั่นล่าสุด
go install [github.com/google/osv-scanner/v2/cmd/osv-reporter@latest](https://github.com/google/osv-scanner/v2/cmd/osv-reporter@latest)
(เมื่อติดตั้งเสร็จ คุณจะได้คำสั่ง osv-reporter มาเรียกใช้ผ่าน Terminal ได้ทันที)
2. ฟีเจอร์เด็ด: Diff Scan Results (เทียบเก่า-ใหม่)
นี่คือไม้ตายสำหรับทีมที่ทำ CI/CD ครับ คุณสามารถเปรียบเทียบผลสแกนของ “Branch ปัจจุบัน” กับ “ผลสแกนเก่า” (เช่นจาก Main Branch) เพื่อดูเฉพาะ ช่องโหว่ที่เพิ่มขึ้นมาใหม่ ได้
วิธีใช้:
osv-reporter --old previous-scan.json --new current-scan.json
ประโยชน์: ช่วยลด Noise จากช่องโหว่เก่าที่รู้อยู่แล้ว ทำให้ Reviewer โฟกัสแค่ว่า “PR นี้ทำอะไรพังเพิ่มไหม?”
3. ฟีเจอร์เด็ด: สร้างหลายรายงานในคำสั่งเดียว
หากทีมคุณมีหลายฝ่าย (Dev อยากได้ JSON ไปทำบอท, Manager อยากได้ Markdown ไว้อ่าน) คุณไม่ต้องรันสแกนหลายรอบครับ ใช้ reporter แปลงเอาได้เลย
วิธีใช้:
# Output ออกมาเป็นไฟล์ JSON Summary และ Markdown Report พร้อมกัน
osv-reporter --new scan.json --output=json:summary.json,markdown:report.md
💡 Idea: การนำไปใช้ใน CI/CD Pipeline
เพื่อให้เห็นภาพชัดขึ้น ลองดู Workflow นี้ครับ:
-
Scan: รัน
osv-scannerแล้วเก็บผลเป็น JSON (current-scan.json) -
Fetch: ไปดึงไฟล์ผลสแกนเก่าจาก Artifact ของ Main Branch (
previous-scan.json) -
Diff: ใช้
osv-reporter --old ... --new ...เพื่อตัด Noise -
Action: ถ้า Output ออกมาว่ามีช่องโหว่ใหม่ -> ให้ Fail Pipeline หรือ Comment เตือนใน PR ทันที
🛡️ Real-World Insight: บทเรียนจากสนามจริง (Experience)
ในฐานะที่ผมคลุกคลีกับการทำ App Security มา การใช้เครื่องมือสแกนเป็นแค่จุดเริ่มต้นครับ ความท้าทายจริงๆ อยู่ที่การ “ตัดสินใจ”
ปัญหา “False Positive” ที่ต้องเจอ
บ่อยครั้งที่ Scanner (รวมถึง OSV) แจ้งเตือนช่องโหว่ระดับ High ใน Library ที่เป็น Dependency ของ Dependency อีกที (Nested Dependency)
แชร์ประสบการณ์ของคุณตรงนี้$$H u m a n N o t e : แ ช ร ์ ป ร ะ ส บ ก า ร ณ ์ ข อ ง ค ุ ณ ต ร ง น ี ้$$
“ส่วนตัวผมเคยเจอกรณีที่สแกนเจอช่องโหว่ใน Utility Library ตัวหนึ่งที่แจ้งว่ารุนแรงมาก (Critical) แต่เมื่อไปไล่ดูโค้ดจริงๆ ปรากฏว่าฟังก์ชันนั้นถูกใช้แค่ในขั้นตอน Build Process ไม่ได้ถูกรันบน Production Server เลย กรณีแบบนี้ถ้าเราบ้าจี้อัปเดตตามโดยไม่ดูบริบท อาจทำให้ Build Pipeline พังได้โดยไม่จำเป็น การมี OSV ช่วยให้ผมเห็นข้อมูลละเอียดขึ้นว่าช่องโหว่นั้นกระทบส่วนไหนกันแน่”
กับดักของ “Patch แล้วพัง”
การรีบอัปเกรด Library เพื่อปิดช่องโหว่ คือดาบสองคม โดยเฉพาะใน ecosystem ของ npm
-
คำแนะนำ: อย่าเชื่อตัวเลขเวอร์ชันเสมอไป แม้จะเป็น Minor Update ก็อาจมี Breaking Change แฝงมาได้
-
ทางแก้: ต้องมี Test Case ที่ครอบคลุม ก่อนจะ Patch ช่องโหว่ใดๆ ให้รัน Unit Test ในเครื่อง Local ให้ผ่าน 100% ก่อนเสมอ
สรุป (Conclusion)
การรักษาความปลอดภัยไม่ใช่แค่การซื้อเครื่องมือแพงๆ แต่คือการสร้าง Routine ที่ดีในการตรวจสอบโค้ด OSV.dev เป็นตัวเลือกที่ยอดเยี่ยมสำหรับ Developer ที่ต้องการความรวดเร็ว แม่นยำ และฟรี
Next Action สำหรับคุณ:
-
ติดตั้ง
osv-scannerวันนี้ -
ลองรันกับโปรเจกต์ปัจจุบันของคุณ 1 ครั้ง
-
ถ้าเจอช่องโหว่ ให้ลองอ่าน Detail ก่อนกดอัปเดต
เริ่มทำตั้งแต่วันนี้ ดีกว่าต้องมานั่งแก้ตอนโดนแฮกไปแล้วครับ!
บทความนี้เขียนขึ้นเพื่อเป็นแนวทางปฏิบัติเบื้องต้น หากคุณทำงานในองค์กรขนาดใหญ่ ควรปรึกษาทีม Security เพื่อวางแผนการทำ DevSecOps ในระดับ Pipeline เพิ่มเติม