บทความ › AI

รีวิวโค้ดที่ AI เขียน: จุดที่ AI พลาดบ่อย และ checklist ก่อน merge

AI เขียนโค้ดเร็ว แต่ชอบแต่ง package ที่ไม่มีจริง กลืน error เงียบ และเขียนเทสต์ที่ไม่ได้เทสต์อะไร checklist รีวิวทีละข้อ diff เล็ก รันก่อนอ่าน และคนเซ็นรับ

เริ่มต้น อ่าน 10 นาที 22 ตุลาคม 2569

อ่านจบแล้วจะรู้
  • AI แต่งชื่อ package ที่ไม่มีอยู่จริงได้ และชื่อที่แต่งมักซ้ำเดิม คนร้ายจึงจดชื่อนั้นรอไว้ได้ (slopsquatting)
  • ตรวจ dependency ใหม่ทุกตัวกับ registry ก่อนติดตั้ง ใช้คำสั่งเดียวจบ
  • ให้ AI ส่งงานเป็น diff เล็ก รันเทสต์และ linter ก่อนเริ่มอ่าน แล้วค่อยอ่านเฉพาะจุดเสี่ยง
  • คนที่กด merge คือคนรับผิดชอบโค้ด ไม่ใช่ AI

AI เขียนโค้ดได้เร็วกว่าคนหลายเท่า แต่ความเร็วนั้นย้ายภาระไปอยู่ที่คนรีวิว โค้ดที่ดูเรียบร้อยและรันผ่านอาจเรียก package ที่ไม่มีอยู่จริง กลืน error ทิ้ง หรือเปิดช่องโหว่ด้วยค่าเริ่มต้นที่ไม่ปลอดภัย บทความนี้รวมจุดที่ AI พลาดบ่อย พร้อม checklist ที่ใช้ได้ทันทีก่อนกด merge

ข้อเท็จจริงตรวจกับงานวิจัย USENIX Security 2025, ACM CCS 2023, รายงาน Veracode 2025 และแนวทางรีวิวโค้ดของ Google ส่วนคำสั่งทดสอบบน npm 10.9, pip 25.0, Python 3.12

ทำไมโค้ดจาก AI ต้องรีวิวต่างจากโค้ดคน

คนเขียนผิดมักผิดแบบมีร่องรอย ตั้งชื่อตัวแปรแปลก ๆ หรือเขียนไม่จบ แต่ AI ผิดแบบ ดูถูกต้อง โค้ดสวย มี comment ครบ ชื่อฟังก์ชันสมเหตุสมผล ทำให้คนรีวิวเผลอเชื่อ

ตัวเลขจากงานวิจัยที่ตรวจได้

  • Veracode 2025 ทดสอบโมเดลมากกว่า 100 ตัว กับโจทย์ 80 ข้อ พบว่า 45% ของกรณีทดสอบ มีช่องโหว่ Java แย่สุดเกิน 70% ส่วน Python, C#, JavaScript อยู่ที่ 38-45% และโมเดลใหญ่ไม่ได้ดีกว่าโมเดลเล็กอย่างมีนัยสำคัญ
  • Perry และคณะ (CCS 2023) คนที่ใช้ผู้ช่วย AI เขียนโค้ดปลอดภัยน้อยกว่ากลุ่มที่ไม่ใช้ และ มั่นใจว่าโค้ดตัวเองปลอดภัยมากกว่า ส่วนคนที่ไว้ใจ AI น้อยกว่าและแก้ prompt หลายรอบ ได้โค้ดที่มีช่องโหว่น้อยกว่า

ข้อสรุปคือ ปัญหาไม่ได้อยู่ที่โมเดลตัวไหน แต่อยู่ที่ขั้นตอนหลัง AI ส่งงาน

จุดที่ AI พลาดบ่อย

1. แต่ง API หรือ package ที่ไม่มีอยู่จริง

งานวิจัย “We Have a Package for You!” (USENIX Security 2025) ให้โมเดล 16 ตัวเขียนโค้ด Python และ JavaScript 576,000 ตัวอย่าง จาก package ที่แนะนำ 2.23 ล้านครั้ง มี 440,445 ครั้ง (19.7%) เป็นชื่อที่ไม่มีอยู่จริง รวม 205,474 ชื่อไม่ซ้ำ โมเดลเชิงพาณิชย์เฉลี่ยอย่างน้อย 5.2% โมเดล open-source 21.7%

ส่วนที่อันตรายคือ ชื่อที่แต่งมักซ้ำเดิม ถามซ้ำ 10 รอบ 43% ของชื่อปลอมโผล่ทุกรอบ และ 58% โผล่มากกว่าหนึ่งครั้ง คนร้ายจึงจดชื่อนั้นบน npm หรือ PyPI รอไว้ ใส่ malware แล้วรอให้มีคน npm install ตาม AI เรียกว่า slopsquatting (Seth Larson จาก Python Software Foundation ตั้งชื่อนี้ ล้อกับ typosquatting)

API ที่ไม่มีจริงก็เช่นกัน เช่น เรียก method ที่เวอร์ชันนั้นไม่มี หรือ option ที่ไม่เคยมีใน library จะพังตอนรัน ไม่ใช่ตอนอ่าน

2. ไม่คิดถึง edge case

AI เขียน happy path เก่ง แต่ลืม list ว่าง ค่า 0 ค่าติดลบ เวลาข้าม timezone ตัวอักษรไทยใน input หรือ request ที่ซ้ำสองครั้ง ถามตัวเองทุกครั้งว่า “ถ้า input ว่าง ใหญ่มาก หรือผิดรูปแบบ จะเกิดอะไร”

3. กลืน error เงียบ

try:
    save_order(order)
except Exception:
    pass  # บันทึกไม่สำเร็จ แต่ไม่มีใครรู้

โค้ดแบบนี้ทำให้เทสต์ผ่านและหน้าจอไม่ขึ้น error แต่ข้อมูลหาย ทุก except ต้องทำอย่างใดอย่างหนึ่ง: จัดการจริง, log แล้วโยนต่อ หรือคืนค่าที่ผู้เรียกรู้ว่าล้มเหลว

4. เทสต์ที่ไม่ได้เทสต์อะไร

def apply_discount(price, pct):
    return price * (1 - pct / 100)

def test_apply_discount():
    result = apply_discount(100, 10)
    assert result is not None   # ผ่านแม้ผลจะผิด

เทสต์นี้ผ่านแม้สูตรผิด ที่ต้องการคือ assert ค่าที่ถูกจริง และครอบ edge case

import pytest

def test_apply_discount():
    assert apply_discount(100, 10) == 90
    assert apply_discount(100, 0) == 100
    assert apply_discount(100, 100) == 0

def test_discount_over_100_is_rejected():
    with pytest.raises(ValueError):
        apply_discount(100, 150)   # จะ fail จนกว่าโค้ดจะเช็ก pct

อีกแบบที่เจอบ่อยคือ mock ตัวฟังก์ชันที่กำลังทดสอบเสียเอง หรือแก้ค่า expected ให้ตรงกับผลที่โค้ดผิดคืนมา ถ้า AI แก้เทสต์ให้ผ่าน ให้ดูว่ามันแก้โค้ดหรือแก้เทสต์

5. ค่าเริ่มต้นที่ไม่ปลอดภัย

Veracode พบว่าโมเดลป้องกัน cross-site scripting (CWE-80) ไม่ได้ใน 86% ของกรณี และ log injection (CWE-117) ใน 88% ของกรณี สิ่งที่เจอบ่อยในงานจริง

  • verify=False ตอนเรียก HTTPS เพื่อให้ “รันผ่าน”
  • CORS * หรือ debug=True ติดไปถึง production
  • ต่อ string เป็น SQL แทน parameterized query
  • เอา input ผู้ใช้ใส่ HTML หรือ log ตรง ๆ
  • key หรือ password ฝังในโค้ดเป็นตัวอย่าง แล้วลืมเอาออก

ตัวอย่างคำนวณ: โอกาสเจอ package ปลอมสักตัว

สมมติให้ AI เสนอ dependency ทั้งโปรเจกต์ 10 ตัว และแต่ละตัวมีโอกาสเป็นชื่อปลอม 5.2% (ค่าเฉลี่ยขั้นต่ำของโมเดลเชิงพาณิชย์ในงานวิจัย) และสมมติว่าแต่ละตัวเป็นอิสระต่อกัน ซึ่งเป็นการลดรูปเพื่อให้เห็นภาพ

  1. โอกาสที่ตัวหนึ่งเป็นของจริง = 1 − 0.052 = 0.948
  2. โอกาสที่ทั้ง 10 ตัวจริงหมด = 0.948¹⁰ ≈ 0.586
  3. โอกาสที่มีปลอมอย่างน้อยหนึ่งตัว = 1 − 0.586 ≈ 41%
dependency ที่ AI เสนออัตรา 5.2%อัตรา 21.7%
10 ตัว≈ 41%≈ 91%
20 ตัว≈ 66%≈ 99%

ตัวเลขจริงขึ้นกับโมเดลและโจทย์ แต่บทเรียนชัด ตรวจทุกตัว ไม่ใช่สุ่มตรวจ

ตรวจ package ก่อนติดตั้ง

ชื่อที่ไม่มีอยู่จะได้ 404 ทันที ชื่อที่มีอยู่ให้ดูวันที่สร้าง ถ้าเพิ่งสร้างไม่กี่วันและไม่มีใครใช้ ให้สงสัยไว้ก่อน

# npm: มีไหม สร้างเมื่อไร
npm view <ชื่อ-package> time.created

# PyPI: 404 = ไม่มีชื่อนี้
curl -s -o /dev/null -w "%{http_code}\n" https://pypi.org/pypi/<ชื่อ-package>/json

แล้วเปิดหน้า package ดู repo ต้นทาง ผู้ดูแล และจำนวนดาวน์โหลด รายละเอียดการล็อกเวอร์ชันและ lockfile อยู่ในบทความความปลอดภัยของ npm และ pip

Checklist ก่อน merge

#ตรวจอะไรวิธีเร็วที่สุด
1diff เล็กพอจะอ่านจบgit diff --stat ถ้าเกินหลายร้อยบรรทัด ให้ AI แบ่ง
2dependency ใหม่มีจริงและน่าเชื่อถือnpm view / PyPI JSON ทุกตัว
3รันผ่านจริงเทสต์ + linter + type check ก่อนอ่าน
4เทสต์ assert ค่าที่ถูกอ่านเทสต์ก่อนโค้ด หา is not None, mock ตัวเอง
5error ไม่ถูกกลืนค้น except: pass, catch {} ว่าง
6edge caseinput ว่าง / 0 / ใหญ่มาก / ซ้ำ
7ค่าความปลอดภัยค้น verify=False, * ใน CORS, debug, SQL ต่อ string, secret ในโค้ด
8API ที่เรียกมีจริงในเวอร์ชันที่ใช้เปิดเอกสารของเวอร์ชันที่ล็อกไว้
9คนเข้าใจทุกบรรทัดที่ mergeอธิบายให้ตัวเองฟังได้ ถ้าไม่ได้ ถาม AI หรือเขียนใหม่
diff เล็กราว 100 บรรทัดต่อรอบรันเทสต์ก่อนพัง = ส่งกลับ ไม่ต้องอ่านอ่านเทสต์มันทดสอบอะไรจริงไหมอ่านจุดเสี่ยงpackage ใหม่ error authคนเซ็นรับคนเป็นเจ้าของโค้ด
ลำดับรีวิวโค้ดจาก AI ถ้าพังตั้งแต่ขั้นรัน ไม่ต้องเสียเวลาอ่าน

diff เล็ก แล้วรันก่อนอ่าน

แนวทางรีวิวโค้ดของ Google บอกว่าราว 100 บรรทัดมักพอดี 1,000 บรรทัดมักใหญ่เกินไป การเปลี่ยนเล็กรีวิวได้ละเอียดกว่า หาบั๊กง่ายกว่า และย้อนกลับง่ายกว่า กับ AI ยิ่งสำคัญ เพราะมันพร้อมจะส่ง 1,000 บรรทัดในนาทีเดียว สั่งให้ทำทีละขั้น หนึ่งขั้นหนึ่ง commit

ลำดับที่ใช้จริง

  1. รันก่อน เทสต์, linter, type check, build ถ้าพังไม่ต้องอ่าน ส่งกลับให้ AI แก้
  2. อ่านเทสต์ ดูว่าเทสต์พิสูจน์สิ่งที่ต้องการจริง
  3. อ่านโค้ดเฉพาะจุดเสี่ยง dependency ใหม่, จุดรับ input, auth, เงิน, การลบข้อมูล
  4. ลองบนเครื่องจริง เปิดหน้าจอ ลองกรณีผิด ไม่ใช่แค่กรณีถูก

ถ้าโค้ดที่ AI เขียนรันได้บนเครื่องเราแต่พังบน server บทความรันได้บนเครื่องผมมีวิธีกันไว้

AI เขียนโค้ดได้ แต่เซ็นรับโค้ดไม่ได้ คนที่กด merge คือคนรับผิดชอบ

ข้อผิดพลาดที่เจอบ่อย

  • อ่านแค่ว่าโค้ดดูดี โค้ด AI ดูดีเสมอ ต้องรันและตรวจ assert
  • ติดตั้ง package ตามที่ AI บอกทันที ตรวจกับ registry ก่อนทุกครั้ง
  • ให้ AI แก้เทสต์จนผ่าน แล้วไม่ดูว่ามันแก้โค้ดหรือแก้ค่า expected
  • รับ diff ก้อนใหญ่เพราะรีบ ก้อนใหญ่ = รีวิวผ่าน ๆ = บั๊กหลุด
  • ไว้ใจ AI รีวิว AI ใช้เป็นด่านเสริมได้ แต่คนต้องเป็นด่านสุดท้าย
  • ลืมว่า AI อ่านเนื้อหาภายนอกได้ ถ้า agent อ่านเว็บหรือ issue แล้วเขียนโค้ด เนื้อหานั้นอาจสั่งมันได้ ดูการป้องกัน prompt injection

ด่านที่ถูกที่สุดคือ diff เล็ก ด่านที่ถูกรองลงมาคือรันก่อนอ่าน

แหล่งอ้างอิง

คำถามที่พบบ่อย

ให้ AI อีกตัวรีวิวแทนคนได้ไหม

ใช้เป็นด่านแรกได้ ช่วยจับเรื่องที่มองข้ามง่าย แต่ไม่ควรเป็นด่านสุดท้าย งานวิจัย CCS 2023 พบว่าคนที่ใช้ผู้ช่วย AI เขียนโค้ดที่ปลอดภัยน้อยกว่า และมั่นใจว่าโค้ดปลอดภัยมากกว่า ความมั่นใจเกินจริงนี้คือสิ่งที่คนรีวิวต้องกัน

diff ขนาดเท่าไรถึงเรียกว่าเล็ก

แนวทางรีวิวโค้ดของ Google บอกว่าราว 100 บรรทัดมักพอดี 1,000 บรรทัดมักใหญ่เกินไป และจำนวนไฟล์ก็มีผล 200 บรรทัดในไฟล์เดียวอาจโอเค แต่กระจาย 50 ไฟล์มักใหญ่ไป

เทสต์ผ่านหมดแล้ว ยังต้องอ่านโค้ดอีกไหม

ต้อง เพราะ AI เขียนทั้งโค้ดและเทสต์ ถ้าเทสต์แค่เช็กว่าผลไม่เป็น None มันจะผ่านแม้ตัวเลขผิด อ่านเทสต์ก่อนโค้ด ดูว่า assert ค่าที่ถูกจริงหรือเปล่า

คำสั่งและค่าตั้งในบทความทดสอบบนระบบตัวอย่าง ลองบนเครื่องทดสอบก่อนใช้กับระบบจริงเสมอ

อ่านต่อ

#AIกลาง

Sandbox ให้ AI เขียนโค้ด: จำกัดไฟล์และเน็ตด้วย bubblewrap กับ Seatbelt

ให้ AI coding agent รันคำสั่งได้เองโดยไม่ต้องกดอนุมัติทุกครั้ง ด้วย sandbox ระดับ OS ตั้งขอบเขตไฟล์และเน็ตยังไง ค่าเริ่มต้นที่ต้องรู้ และส่วนที่ sandbox ไม่ครอบ

อ่าน 8 นาที
#AIกลาง

ทดสอบฟีเจอร์ AI แบบเขียนเทส: ชุด eval 30-100 เคส รันทุกครั้งที่แก้ prompt

ทำชุดทดสอบ LLM จาก input จริง ตรวจด้วยโค้ดหรือ LLM-as-judge รันทุกครั้งที่เปลี่ยน prompt หรือโมเดล พร้อมคำนวณว่าต้องกี่เคสถึงจะเห็นคะแนนตก 10%

อ่าน 11 นาที
#AIเริ่มต้น

งานวิจัย METR: ใช้ AI เขียนโค้ดแล้วช้าลง 19% แต่รู้สึกว่าเร็วขึ้น 20%

การทดลองแบบสุ่มกับนักพัฒนา 16 คน 246 งาน พบว่าใช้ AI แล้วช้าลง ทั้งที่เชื่อว่าเร็วขึ้น ผลนี้บอกอะไร ไม่ได้บอกอะไร ผลรอบใหม่ปี 2026 และวิธีวัดงานตัวเองแบบไม่หลอกตัวเอง

อ่าน 7 นาที