BotKit
บทความ › เขียนโค้ด & ดูแลระบบ

กัน 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 ที่คนอื่นเปิดดูได้

ถ้าหลุดไปแล้วทำยังไง

  1. รีเซ็ต/เพิกถอน key ทันที ที่หน้าของผู้ให้บริการ นี่คือขั้นที่สำคัญที่สุด
  2. อัปเดตค่าใหม่ในตัวแปรสภาพแวดล้อม แล้วเช็คว่าระบบกลับมาทำงาน
  3. ดูประวัติการใช้งานของ key ว่ามีการเรียกที่ไม่ใช่ของเราหรือเปล่า
  4. ล้างออกจากประวัติ git ถ้าจำเป็น (การ rewrite history ทำให้ทุกคนที่ clone ไปต้องจัดการต่อ และ key ที่ถูกคัดลอกไปแล้วก็ยังใช้ได้ถ้าไม่ได้รีเซ็ต ข้อ 1 จึงต้องมาก่อน)

ตั้งวันหมดอายุให้ key ได้ แต่ระวังตั้งสั้นเกินโดยไม่มีระบบเตือน ระบบจะตายเงียบ (เคสจริงอยู่ใน API key หมดอายุแล้วระบบเงียบ)

เกี่ยวกับผู้เขียน — Jark นักพัฒนา LINE Bot และระบบ AI อัตโนมัติ อยู่เชียงใหม่ ทำระบบตอบแชทและจองคิวให้ร้านค้าจริง บทความในเว็บนี้มาจากงานที่ลงมือทำเอง อ่านเพิ่ม