กัน API key หลุดขึ้น GitHub: 4 ชั้นป้องกัน และสิ่งที่ต้องทำเมื่อหลุดไปแล้ว
API key ที่หลุดขึ้น GitHub ถูกบอทสแกนเจอได้เร็วมาก บางคนโดนใช้ key จนบิลบาน บางคนโดนยึดบัญชีบอท และการลบไฟล์ออกใน commit ถัดไปไม่ได้ทำให้ key หายจากประวัติ git บทความนี้รวมวิธีกัน secret หลุดที่ผมใช้กับโปรเจกต์บอทและเว็บทุกตัว
secret คืออะไรบ้าง
- API key ของ AI (Claude, OpenAI)
- Channel access token / channel secret ของ LINE
- Page token และ App secret ของ Meta
- Client secret ของ TikTok, Google
- service_role key ของ Supabase, รหัสฐานข้อมูล
- เลขพร้อมเพย์หรือข้อมูลการเงินที่ไม่อยากให้ใครเห็นในโค้ด
ชั้นที่ 1: secret อยู่ในตัวแปรสภาพแวดล้อมเท่านั้น
import os
ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
if not ANTHROPIC_API_KEY:
print("⚠️ ไม่ได้ตั้ง ANTHROPIC_API_KEY — ฟีเจอร์ AI ปิดอยู่")
บนเครื่องตัวเองเก็บในไฟล์ .env บนเซิร์ฟเวอร์ใส่ในหน้า Environment ของผู้ให้บริการ
ทำไฟล์ .env.example ที่มีแต่ชื่อตัวแปร (ไม่มีค่า) ไว้ใน repo ให้รู้ว่าต้องตั้งอะไรบ้าง
ข้อดีอีกอย่าง: เมื่อไม่ได้ตั้งตัวแปร ฟีเจอร์นั้นปิดตัวเองเงียบๆ เครื่องทดสอบจึงไม่ยิงไปหาระบบจริงโดยไม่ตั้งใจ
ชั้นที่ 2: .gitignore ตั้งแต่วันแรก
.env
*.env.local
secrets.local.*
__pycache__/
โปรเจกต์ที่มีไฟล์หลากหลายและเสี่ยงสูง ผมใช้แบบกลับด้าน (whitelist): ignore ทุกอย่าง แล้วระบุเฉพาะไฟล์ที่อนุญาตให้ commit ไฟล์ใหม่ที่ไม่ได้ตั้งใจจะไม่หลุดเข้า repo เอง
# ignore ทั้งหมด
*
# ยกเว้นที่ระบุ (บรรทัด !*/ ให้ git ยังเข้าไปดูในโฟลเดอร์ย่อยได้)
!*/
!.gitignore
!*.py
!*.html
!requirements.txt
ชั้นที่ 3: สคริปต์ตรวจก่อน commit
คนลืมได้ ให้เครื่องตรวจแทน สคริปต์ง่ายๆ ค้นหารูปแบบที่หน้าตาเหมือน key ในไฟล์ที่กำลังจะ commit
import re, subprocess, sys
PATTERNS = [
r"sk-ant-[A-Za-z0-9_\-]{20,}", # Anthropic
r"sk-[A-Za-z0-9]{32,}", # รูปแบบ key ทั่วไป
r"EAA[A-Za-z0-9]{50,}", # Meta access token
r"eyJ[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}", # JWT เช่น service_role
]
files = subprocess.run(["git", "diff", "--cached", "--name-only"],
capture_output=True, text=True).stdout.split()
bad = []
for f in files:
try:
text = open(f, encoding="utf-8", errors="ignore").read()
except OSError:
continue
for p in PATTERNS:
if re.search(p, text):
bad.append((f, p))
if bad:
for f, p in bad:
print(f"❌ อาจมี secret ใน {f} (ตรงรูปแบบ {p})")
sys.exit(1)
ตั้งเป็น pre-commit hook หรือรันก่อน commit ทุกครั้ง รูปแบบ key ของแต่ละเจ้าเปลี่ยนได้ ปรับรายการให้ตรงกับบริการที่ใช้จริง หรือใช้เครื่องมือสำเร็จรูปอย่าง gitleaks ก็ได้
ชั้นที่ 4: ระวังที่อื่นนอกจาก git
- แชทกับคนหรือ AI — ถ้าวาง key ลงแชท ถือว่าหลุดแล้ว รีเซ็ตใหม่
- ภาพหน้าจอและคลิปสาธิต — ตอนอัดคลิปยื่นรีวิวแอป ระวังหน้าตั้งค่าที่มี token โผล่
- ไฟล์คู่มือและโน้ต — โน้ตที่เขียนค่าจริงไว้เพื่อความสะดวก มักถูกแชร์ต่อโดยลืม
- log — อย่า print header หรือ token ทั้งก้อนลง log ที่คนอื่นเปิดดูได้
ถ้าหลุดไปแล้วทำยังไง
- รีเซ็ต/เพิกถอน key ทันที ที่หน้าของผู้ให้บริการ นี่คือขั้นที่สำคัญที่สุด
- อัปเดตค่าใหม่ในตัวแปรสภาพแวดล้อม แล้วเช็คว่าระบบกลับมาทำงาน
- ดูประวัติการใช้งานของ key ว่ามีการเรียกที่ไม่ใช่ของเราหรือเปล่า
- ล้างออกจากประวัติ git ถ้าจำเป็น (การ rewrite history ทำให้ทุกคนที่ clone ไปต้องจัดการต่อ และ key ที่ถูกคัดลอกไปแล้วก็ยังใช้ได้ถ้าไม่ได้รีเซ็ต ข้อ 1 จึงต้องมาก่อน)
ตั้งวันหมดอายุให้ key ได้ แต่ระวังตั้งสั้นเกินโดยไม่มีระบบเตือน ระบบจะตายเงียบ (เคสจริงอยู่ใน API key หมดอายุแล้วระบบเงียบ)