BrassCoders ค้นพบความลับที่ถูกฝังไว้ในโค้ด (hard-coded secrets) ในสคริปต์ Python ที่สร้างโดย AI จำนวน 2 จาก 15 สคริปต์ที่พวกเขาตรวจสอบ ซึ่งเผยให้เห็นความเสี่ยงที่เป็นรูปธรรมสำหรับนักพัฒนาที่คัดลอกและวางโค้ดโดยตรงจากผลลัพธ์ของโมเดลภาษาขนาดใหญ่ (Large Language Model) ผลการวิจัยแสดงให้เห็นว่า เพียงแค่คีย์หรือรหัสผ่านที่วางผิดที่เพียงจุดเดียว ก็สามารถเปลี่ยนโค้ดตัวอย่างที่มีประโยชน์ให้กลายเป็นการรั่วไหลของข้อมูลประจำตัว (credential leak) ไปทั่วทั้งระบบควบคุมเวอร์ชัน (version control) และสภาพแวดล้อมการทำงานจริง (production environments) ได้
สิ่งที่การทดสอบเผยให้เห็น
สคริปต์แรก token_check.py ถูกสร้างขึ้นจากพรอมต์ที่ขอฟังก์ชันสำหรับลงลายเซ็น session tokens และให้รวม "ตัวอย่างที่นำไปใช้งานได้จริง" (usable example) เพื่อให้โค้ดสามารถรันได้ โมเดลจึงใส่คีย์สำหรับลงลายเซ็น HMAC ลงไปในไฟล์ซอร์สโค้ดโดยตรง
- ปัญหา: คีย์ลับถูกเก็บไว้ในฐานโค้ด (code base)
- ความเสี่ยง: ใครก็ตามที่มีสิทธิ์อ่านใน repository สามารถเห็นคีย์ได้ และการติดตั้งใช้งาน (deployment) ใดๆ ที่ดึงไฟล์นี้ไปจะได้รับความลับนั้นไปด้วย
- ผลกระทบ: ผู้โจมตีที่ได้คีย์ไปจะสามารถปลอมแปลง session tokens ที่ถูกต้อง เพื่อข้ามผ่านการตรวจสอบการยืนยันตัวตนได้
สคริปต์ที่สอง email_sender.py ตอบสนองต่อคำขอฟังก์ชันสำหรับส่งอีเมลผ่าน SMTP โมเดลได้ให้รหัสผ่านแบบตรงตัวมาอีกครั้งเพื่อให้ตัวอย่างสามารถทำงานได้ทันที
- ปัญหา: รหัสผ่านปรากฏเป็นข้อความธรรมดา (plain-text string) ในการเรียกใช้ฟังก์ชัน
- ความเสี่ยง: การเปลี่ยนรหัสผ่าน (rotating the password) จำเป็นต้องแก้ไขโค้ดและทำการ deployment ใหม่ และข้อมูลประจำตัวจะแพร่กระจายไปยังทุกสภาพแวดล้อมที่ใช้ไฟล์นี้
- ผลกระทบ: รหัสผ่านสามารถถูกดึงออกมาจากระบบควบคุมซอร์สโค้ด (source control), ล็อก (logs) หรือแพ็กเกจที่คอมไพล์แล้ว ทำให้ผู้ไม่หวังดีสามารถเข้าถึงเซิร์ฟเวอร์เมลโดยไม่ได้รับอนุญาต
ทำไม AI ถึงแสดงข้อมูลความลับออกมา
โมเดลภาษาขนาดใหญ่สร้างข้อความโดยการเติมเต็มพรอมต์ เมื่อผู้ใช้ขอ "ตัวอย่างที่นำไปใช้งานได้จริง" โมเดลจะตีความว่านั่นคือ "โค้ดที่รันได้โดยไม่ต้องตั้งค่าเพิ่มเติม" ดังนั้นมันจึงเติมค่าที่ขาดหายไป เช่น API keys, รหัสผ่าน หรือ tokens ด้วยค่าตัวแทน (placeholders) ที่ดูสมจริง โมเดลไม่มีความตระหนักถึงแนวทางปฏิบัติที่ดีที่สุดในการจัดการความลับ (secret-management best practices) เว้นแต่จะมีการระบุไว้ในพรอมต์อย่างชัดเจน
การวิเคราะห์โค้ดที่สร้างโดย AI ของ Veracode เมื่อเร็วๆ นี้พบว่า 45% ของโค้ดตัวอย่างมีช่องโหว่อย่างน้อยหนึ่งอย่างที่ระบุไว้ใน OWASP Top 10 โดยการเปิดเผยข้อมูลประจำตัว (credential exposure) คิดเป็นสัดส่วนที่สำคัญ สถิตินี้ตอกย้ำว่าปัญหานี้ไม่ได้เกิดขึ้นเพียงแค่บางกรณี แต่เป็นผลพลอยได้เชิงระบบจากวิธีการฝึกฝนและวิธีการเขียนพรอมต์ของโมเดลเหล่านี้
ขั้นตอนการบรรเทาความเสี่ยงที่นักพัฒนาสามารถทำได้ทันที
การป้องกันที่ง่ายที่สุดคือการเก็บความลับใดๆ ไว้ภายนอกไฟล์โค้ด ตัวแปรสภาพแวดล้อม (Environment variables) เป็นวิธีที่นิยมที่สุดและไม่ขึ้นกับภาษาใดภาษาหนึ่ง:
# token_check.py – secure version
import os
import hmac
import hashlib
SECRET_KEY = os.environ["HMAC_SECRET_KEY"]
def sign_token(data: bytes) -> str:
return hmac.new(SECRET_KEY.encode(), data, hashlib.sha256).hexdigest()
# email_sender.py – secure version
import os
import smtplib
smtp_password = os.environ["SMTP_PASSWORD"]
server = smtplib.SMTP("smtp.example.com", 587)
server.starttls()
server.login("noreply@example.com", smtp_password)
การใช้ os.environ จะเป็นการดึงค่าจากสภาพแวดล้อมขณะรัน (runtime environment) ซึ่งช่วยให้ความลับไม่หลุดเข้าไปในระบบควบคุมเวอร์ชัน และช่วยให้สามารถเปลี่ยนรหัสผ่านได้โดยไม่ต้องแก้ไขไฟล์ซอร์สโค้ด รูปแบบเดียวกันนี้ยังใช้ได้กับไฟล์กำหนดค่า (configuration files) ที่ถูกยกเว้นจากการ commit, บริการจัดการความลับ (secret-management services) หรือความลับที่จัดการผ่านระบบ Container orchestration
มาตรการป้องกันเพิ่มเติม
- การรีวิวโค้ด (Code reviews) ที่คอยตรวจสอบข้อความ (strings) ที่ตรงกับรูปแบบความลับทั่วไป (เช่น ลำดับตัวอักษรและตัวเลขที่ยาว)
- เครื่องมือวิเคราะห์แบบ Static (Static analysis tools) ที่ปรับแต่งมาเพื่อตรวจหาข้อมูลประจำตัวที่ถูกฝังไว้ในไฟล์ที่เพิ่มเข้ามาใหม่
- การวิศวกรรมพรอมต์ (Prompt engineering): ระบุอย่างชัดเจนในพรอมต์ว่าให้ "ใช้ environment variables สำหรับความลับทั้งหมด" หรือ "ไม่ต้องใส่ข้อมูลประจำตัวจริง"
- การทำ Linting หลังการสร้างโค้ด: รันสคริปต์อย่างรวดเร็วเพื่อค้นหาค่า literal ที่น่าสงสัยก่อนที่จะคัดลอกโค้ดลงในโปรเจกต์
มุมมองแย้ง: นี่หมายความว่าโค้ดจาก AI ไม่ปลอดภัยใช่หรือไม่?
การพบความลับที่ถูกฝังไว้ในโค้ดไม่ได้หมายความว่าโค้ดที่สร้างโดย AI จะไม่ปลอดภัยเสมอไป ในหลายกรณี โมเดลสามารถสร้างตรรกะที่สะอาดและมีโครงสร้างที่ดีซึ่งช่วยเร่งการพัฒนาได้ ความเสี่ยงจะเกิดขึ้นเมื่อนักพัฒนาปฏิบัติกับผลลัพธ์เสมือนว่าพร้อมใช้งานในระดับโปรดักชัน (production-ready) โดยไม่มีการตรวจสอบความปลอดภัย ให้มองว่า AI เป็นเพียงผู้ช่วยร่างงาน ไม่ใช่สิ่งที่จะมาแทนที่แนวทางปฏิบัติทางด้านความปลอดภัยที่กำหนดไว้แล้ว
สิ่งที่ควรจับตามองต่อไป
- การอัปเดตเครื่องมือ: แพลตฟอร์ม AI เริ่มมีการนำตัวกรองความปลอดภัยมาใช้เพื่อแทนที่ความลับด้วยค่าตัวแทน (placeholders) การติดตามการเปลี่ยนแปลงเหล่านี้สามารถช่วยลดความเสี่ยงได้
- การเปลี่ยนแปลงด้านนโยบาย: องค์กรต่างๆ อาจกำหนดแนวทางปฏิบัติสำหรับการเขียนโค้ดโดยใช้ AI อย่างเป็นทางการ โดยกำหนดให้มีการตรวจสอบการจัดการความลับเป็นส่วนหนึ่งของ CI pipeline
- รูปแบบการใช้งานในชุมชน: เมื่อนักพัฒนาแบ่งปัน "พรอมต์ที่ปลอดภัย" (secure prompts) มากขึ้น เทมเพลตที่เป็นแนวทางปฏิบัติที่ดีที่สุดอาจกลายเป็นผลลัพธ์มาตรฐานสำหรับงานทั่วไป เช่น การลงลายเซ็น token หรือการส่งอีเมล
สรุปประเด็นสำคัญ: AI สามารถสร้างโค้ดที่ใช้งานได้จริงภายในไม่กี่วินาที แต่หากนักพัฒนาไม่บังคับใช้ระเบียบวินัยในการจัดการความลับ (secret-management) ความสะดวกสบายนี้จะมาพร้อมกับต้นทุนที่แฝงอยู่ นั่นคือการเปิดเผยข้อมูลประจำตัว (credentials) ที่อาจทำให้ทั้งระบบตกอยู่ในอันตราย จงปฏิบัติกับโค้ดทุกชุดเสมือนเป็นเพียงร่างชั่วคราว ลบข้อมูลความลับที่ระบุไว้ในโค้ดโดยตรงออก และแทนที่ด้วยการใช้ environment variables หรือระบบ vault โดยเฉพาะก่อนที่จะทำการ commit
