ข้าม​ไป​ยัง​เนื้อหา

Found on Internet

คัด​ลอก code/คำ​แนะนำ​จาก​เน็ต​มา​ใช้ production ทันที​โดย​ไม่​พิจารณา

Found on Internet คือ​การนำ​คำ​แนะนำ​หรือ code sample จาก​อินเทอร์เน็ต — Stack Overflow, blog post, README ของ repo แปลก​หน้า, หรือ​แม้แต่​คำ​ตอบ​จาก AI chatbot — มา วาง​ลง​ใน code production ทันที​โดย​ไม่​พิจารณา​ผลกระทบ ไม่​ตรวจสอบ​ว่า​มัน​เหมาะ​กับ​บริบท​ของ​ระบบ​ตัวเอง​หรือ​ไม่ ไม่​เข้าใจ​ว่า​ทำไม code นั้น​ถึง​ทำงาน และ​ไม่​ทดสอบ​ก่อน​ว่า​ใช้ได้​จริง​ใน​สภาพ​แวดล้อม​ของ​ตัวเอง

จริง​อยู่​ที่​อินเทอร์เน็ต​เป็น​แหล่ง​ความ​รู้​มหาศาล​และ​เป็น​เครื่องมือ​เร่ง​ความเร็ว​ใน​การ​พัฒนา​ที่​ทรง​พลัง แต่​การ​เผยแพร่​บน​อินเทอร์เน็ต​ไม่ใช่​เรื่อง​ยาก และ​คำ​ตอบ​ส่วน​ใหญ่​ก็​ไม่​ผ่าน​กระบวนการ peer review แบบ​เดียว​กับ​งาน​วิชาการ​หรือ code review ภายใน​ทีม คำ​ตอบ​ที่​ได้ vote สูง​บน Stack Overflow อาจ​เขียน​ขึ้น​เมื่อ​หลาย​ปี​ก่อน ใช้ library version เก่า หรือ​แก้​ปัญหา​คนละ​บริบท​กับ​ที่​เรา​กำลัง​เจอ ก่อน​เชื่อถือ​ควร​พิจารณา​แหล่ง​ที่มา และ​ลอง​ใช้​ใน non-production ก่อน (ดู Read the Manual และ Cunningham’s Law)

แนวคิด​นี้​ใกล้​เคียง​กับ​สิ่ง​ที่​ชุมชน​เรียก​ว่า Cargo Cult Programming — การ​คัด​ลอก code หรือ​โครงสร้าง​โปรแกรม​มา​ใช้​โดย​ไม่​เข้าใจ​ว่า​ทำไม​มัน​ถึง​ทำงาน เพียง​เพราะ “ทำ​แบบ​นี้​แล้ว​มัน​เคย​ได้​ผล” คำ​นี้​มา​จาก​คำ​ว่า cargo cult ใน​มานุษยวิทยา ซึ่ง​ชุมชน​บน​เกาะ​แปซิฟิก​หลัง​สงครามโลก​ครั้ง​ที่ 2 สร้าง​รันเวย์​จำลอง​และ​วิทยุ​ไม้​เพื่อ “เรียก” เครื่องบิน​ขนส่ง​สินค้า​ให้​กลับ​มา โดย​เลียน​แบบ​รูปแบบ​ภายนอก​โดย​ไม่​เข้าใจ​กลไก​ที่แท้​จริง​เบื้องหลัง — เหมือน​โปรแกรมเมอร์​ที่ copy code มา​โดย​ไม่รู้​ว่า​มัน​ทำ​อะไร​จริง ๆ

  • เร็ว — เสิร์ช​แล้ว copy-paste ใช้​เวลา​ไม่​กี่​วินาที เทียบ​กับ​การ​อ่าน​เอกสาร ทำความ​เข้าใจ​ปัญหา แล้ว​เขียน​เอง
  • ดู​น่า​เชื่อถือ — คำ​ตอบ​มี upvote เยอะ, comment ยืนยัน​ว่า “ใช้ได้”, หรือ​มา​จาก repo ที่​มี star สูง ทำให้​รู้สึก​ว่า​ปลอดภัย​ที่​จะ​เชื่อ
  • แก้​ปัญหา​เฉพาะ​หน้า​ได้​จริง — ใน​หลาย​กรณี code ที่ copy มา​ก็​ทำงาน​ได้​ตาม​ที่​ต้องการ อย่าง​น้อย​ก็​ใน​ตอน​ที่​ทดสอบ​ผิวเผิน
  • แรง​กดดัน​เรื่อง​เวลา — ภาย​ใต้ deadline การ​หา​ทาง​ลัด​ที่ “ดูเหมือน​ใช้ได้” ย่อม​น่า​ดึงดูด​กว่า​การ​ค่อย ๆ เรียนรู้​และ​ออกแบบ​เอง (ดู Calendar Coder)
  • ยุค AI ยิ่ง​เร่ง​ปัญหา​นี้ — chatbot สร้าง code ที่ syntax ถูกต้อง อ่าน​ลื่น ให้​ความ​มั่นใจ​สูง แต่​ก็​สามารถ​พา​ผู้​ใช้​หลง​ทาง​ไป​ใน​ทิศทาง​ที่​ไม่​เหมาะ​กับ​บริบท​ได้​เหมือน​กัน เพียง​แต่​เร็ว​กว่า​และ​ดู​น่า​เชื่อถือ​กว่า​เดิม
  • ไม่​ผ่าน​การ​รีวิว — คำ​ตอบ​บน​อินเทอร์เน็ต​ส่วน​ใหญ่​ไม่มี​กระบวนการ peer review ที่​เข้มงวด แม้ upvote สูง​ก็​ไม่​ได้​แปล​ว่า code ปลอดภัย​หรือ​ถูกต้อง​สำหรับ​ทุก​บริบท
  • ช่อง​โหว่​ความ​ปลอดภัย​แพร่​กระจาย​ได้​จริง — งาน​วิจัย​ของ Fraunhofer AISEC พบ​ว่า​ใน app Android กว่า 1.3 ล้าน app ที่​มี code เกี่ยว​กับ​ความ​ปลอดภัย​จาก Stack Overflow ราว 97.9% มี code ที่​ไม่​ปลอดภัย​อย่าง​น้อยหนึ่ง​จุด และ​งาน​วิจัย​อีก​ชิ้น​พบ​ว่า code snippet ที่​มี​ช่อง​โหว่​เพียง 69 ชิ้น​จาก Stack Overflow ได้​แพร่​กระจาย​ไป​ยัง GitHub repository กว่า 2,800 repo
  • บริบท​ไม่​ตรง​กัน — code ตัวอย่าง​มัก​เขียน​ขึ้น​เพื่อ​สาธิต​แนวคิด ไม่ใช่​เพื่อ production ใช้ library คนละ version คนละ framework หรือ​ละเลย edge case, error handling, การ​จัดการ resource ที่​ระบบ​จริง​ต้อง​มี
  • สร้าง​หนี้​ทาง​เทคนิค​ที่​มอง​ไม่​เห็น — เมื่อ​ไม่​เข้าใจ​ว่า code ทำงาน​อย่างไร การ debug, maintain, หรือ​ขยาย​ใน​อนาคต​จะ​ยาก​ขึ้น​มาก เพราะ​ไม่มี​ใคร​ใน​ทีม​อธิบาย​ได้​ว่า​ทำไม​มัน​ถึง​เป็น​แบบ​นี้
  • ปัญหา​เรื่อง license และ​การ​อ้างอิง​แหล่ง​ที่มา — code ที่ copy มา​อาจ​มี license ที่​ไม่​เข้า​กัน​กับ project หรือ​ละเมิด​ลิขสิทธิ์​โดย​ไม่รู้ตัว
  • False sense of security — เพราะ code “รัน​ได้” และ​ผ่าน test ผิวเผิน ทีม​จึง​เข้าใจ​ผิด​ว่า​มัน​ถูกต้อง ทั้ง​ที่​ยัง​ไม่​ได้​ตรวจสอบ correctness หรือ security อย่าง​จริงจัง

สมมติ​ทีม​ต้องการ hash รหัส​ผ่าน​ผู้​ใช้ แล้วไป​เจอ code snippet ยอด​นิยม​บน​อินเทอร์เน็ต​ที่​ใช้ MD5 (ซึ่ง​เคย​เป็น​คำ​ตอบ​ยอด​นิยม​ใน​หลาย​กระทู้​เก่า) แล้ว copy มา​ใช้​ทันที​โดย​ไม่​ตรวจสอบ​ว่า​ปัจจุบัน MD5 ถือว่า​ไม่​ปลอดภัย​สำหรับ​การ​เก็บ​รหัส​ผ่าน​แล้ว:

// พบใน "answer" เก่าบนอินเทอร์เน็ต แล้ว copy มาใช้ทันที
// ไม่มีใครในทีมรู้ว่า MD5 ถูกพิสูจน์แล้วว่ามีช่องโหว่ collision
// และไม่เหมาะกับการ hash รหัสผ่านมาตั้งแต่ปี 2005
public class UserAccountService
{
public string HashPassword(string plainTextPassword)
{
using var md5 = System.Security.Cryptography.MD5.Create();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(plainTextPassword);
byte[] hash = md5.ComputeHash(bytes);
return Convert.ToHexString(hash);
// ไม่มี salt, ไม่มี work factor, hash เร็วเกินไปสำหรับ brute-force ป้องกัน
}
}

ปัญหา: code นี้ “ใช้งาน​ได้” ใน​ความหมาย​ที่​มัน compile และ​คืน hash ที่​ดู​สม​เหตุ​สม​ผล แต่​ไม่มี​ใคร​ใน​ทีม​ตรวจสอบ​ว่า MD5 ไม่​เหมาะ​กับ​การ​เก็บ​รหัส​ผ่าน ไม่มี salt ทำให้​เสี่ยง​ต่อ rainbow table attack และ​คำนวณ​เร็ว​เกิน​ไป​จน​โดน brute-force ได้​ง่าย — เป็น​ตัวอย่าง​คลาสสิก​ของ​ช่อง​โหว่​ที่​แพร่​จาก Stack Overflow ไป​สู่ production จริง

แนวทาง​แก้​ไม่ใช่​การ​ห้าม​ใช้​ทรัพยากร​จาก​อินเทอร์เน็ต แต่​คือ​การ​ใช้​อย่าง​มี​วิจารณญาณ:

  1. อ่าน​เอกสาร​ทางการ​ก่อน — ตรวจสอบ​ว่า​มี built-in API หรือ library ที่​ผ่าน​การ​รับรอง​อยู่​แล้ว​หรือ​ไม่ (ดู Read the Manual)
  2. เข้าใจ​ก่อน​ใช้ — อย่า copy code ที่​อธิบาย​ไม่​ได้​ว่า​ทำงาน​อย่างไร ถ้า​อธิบาย​ให้​เพื่อน​ร่วม​ทีม​ฟัง​ไม่​ได้ ก็​ยัง​ไม่​พร้อม​จะ merge
  3. ตรวจสอบ​วัน​ที่​และ​บริบท — คำ​ตอบ​เก่า​อาจ​อิง​กับ version library หรือ​แนวทาง​ที่​ล้าสมัย​ไป​แล้ว
  4. ทดสอบ​ใน non-production ก่อน — ลองใน sandbox, ผ่าน code review, และ​เขียน automated test ก่อน​ปล่อย​เข้า production
  5. ใช้ library มาตรฐาน​ที่​ได้​รับ​การ​ดูแล​และ​ตรวจสอบ​ด้าน​ความ​ปลอดภัย แทน​การ​เขียน​เอง​จาก snippet ที่​ไม่รู้​ที่มา
// ใช้ API มาตรฐานที่ผ่านการตรวจสอบ ออกแบบมาสำหรับ hash รหัสผ่านโดยเฉพาะ
// เข้าใจได้ว่าทำไมถึงปลอดภัย: adaptive work factor + salt อัตโนมัติ
using Microsoft.AspNetCore.Identity;
public class UserAccountService
{
private readonly PasswordHasher<User> _passwordHasher = new();
public string HashPassword(User user, string plainTextPassword)
{
// PasswordHasher ใช้ PBKDF2 พร้อม salt แบบสุ่มและ iteration count ที่ปรับได้
// เป็นส่วนหนึ่งของ ASP.NET Core Identity ที่ได้รับการรีวิวและดูแลโดยทีม .NET
return _passwordHasher.HashPassword(user, plainTextPassword);
}
public bool VerifyPassword(User user, string hashedPassword, string providedPassword)
{
var result = _passwordHasher.VerifyHashedPassword(user, hashedPassword, providedPassword);
return result == PasswordVerificationResult.Success;
}
}

ก่อน​นำ​เข้า production ทีม​ควร​ถาม​คำถาม​พื้นฐาน​เสมอ: code นี้​มา​จาก​ไหน ทำไม​มัน​ถึง​ทำงาน มัน​เหมาะ​กับ​บริบท​ของ​เรา​หรือ​ไม่ และ​มี​ทาง​เลือก​ที่​ผ่าน​การ​ตรวจสอบ​มากกว่า​นี้​หรือ​ไม่

flowchart TD
    Search[เจอ code ตัวอย่างบนอินเทอร์เน็ต]
    Understand{เข้าใจว่าทำไมมันทำงานไหม}
    Source{ตรวจสอบแหล่งที่มาและความทันสมัยแล้วหรือยัง}
    Sandbox[ทดลองใน non-production ก่อน]
    Review[ผ่าน code review และ automated test]
    Prod[นำเข้า production]
    Rework[ศึกษาเพิ่มหรือหาทางเลือกอื่น]

    Search --> Understand
    Understand -->|ไม่| Rework
    Understand -->|ใช่| Source
    Source -->|ยัง| Rework
    Source -->|แล้ว| Sandbox
    Sandbox --> Review
    Review --> Prod
    Rework --> Search