ซีรีส์ เขียนโปรแกรมพื้นฐาน · ตอนที่ 7 จาก 7
6 ข้อห้ามกับไฟล์ .env เพื่อไม่ให้คีย์หลุด โดยเฉพาะตอนให้ AI เขียนโค้ด
30 ต.ค. 2569 · อ่าน 14 นาที
ไฟล์ .env เก็บคีย์ที่ใช้บริการในนามบัญชีของคุณ คีย์หลุดได้หลายทาง ทั้งตอน commit ตอนวางในแชต ตอนแชร์จอ และตอนให้ AI อ่านไฟล์ในโปรเจกต์ บทความนี้สรุป 6 ข้อห้ามพร้อมสิ่งที่ต้องทำแทน ลำดับสิ่งที่ต้องทำเมื่อคีย์หลุด คำสั่งสำเร็จรูปให้ AI ตรวจโปรเจกต์โดยไม่แสดงค่าคีย์ และเช็กลิสต์ก่อน push หรือแชร์จอ

สมมติคุณให้ AI ต่อระบบส่งอีเมลยืนยันออเดอร์ให้ร้าน AI บอกให้สร้างไฟล์ .env แล้ววางคีย์ของบริการส่งอีเมลลงไป ขั้นต่อไปคือส่งโค้ดขึ้น GitHub หรือแชร์จอให้เพื่อนช่วยดู จังหวะนี้คีย์หลุดได้ง่าย
บทความนี้รวม 6 ข้อห้ามกับไฟล์ .env พร้อมสิ่งที่ควรทำแทน คำสั่งสำเร็จรูปให้ AI ตรวจโปรเจกต์ และเช็กลิสต์ก่อน push หรือแชร์จอ
นี่คือตอนสุดท้ายของซีรีส์ "เขียนโปรแกรมพื้นฐาน" ต่อจาก ไฟล์ .env คืออะไร ซึ่งอธิบายว่า .env เก็บค่าตั้งค่าและความลับแยกจากโค้ด ทำไมต้องแยก และค่าเหล่านี้อยู่ที่ไหนเมื่อเว็บขึ้นใช้งานจริง
ข้อมูล ณ ตุลาคม 2569 จากเอกสารของ GitHub, Git, Claude Code, Vite, Next.js และ Google Cloud
ทำไมคีย์ใน .env ต้องระวังเป็นพิเศษ
คีย์ของบริการ (API key) คือรหัสที่บอกบริการว่า "คำขอนี้มาจากบัญชีนี้" ใครได้คีย์ไปก็ส่งคำขอในนามบัญชีของคุณได้ เช่น ส่งอีเมลจากระบบของร้าน หรือเรียกใช้บริการที่คิดเงินตามการใช้งาน
ในบทความนี้ "ความลับ" หมายถึงคีย์ รหัสผ่าน และ token ส่วน "คีย์" หมายถึง API key เอกสารของ GitHub แนะนำว่า อย่าเขียนความลับไว้ในโค้ดตรงๆ ให้เก็บในตัวแปรสภาพแวดล้อม (environment variables) แทน ไฟล์ .env จึงเป็นที่รวมความลับของโปรเจกต์
6 ข้อห้ามกับไฟล์ .env
ข้อ 1: ห้าม commit หรืออัปโหลดไฟล์ .env ขึ้น Git หรือ GitHub
Git จำทุกอย่างที่ commit ไว้ในประวัติ ลบไฟล์ทีหลังคีย์ก็ไม่หายจากประวัติ เราทดลองให้ดูแล้วใน Git คืออะไร: จุดเซฟเกมของคนที่ให้ AI แก้โค้ด
ทำแบบนี้แทน
-
เขียนบรรทัด
.envไว้ในไฟล์.gitignoreตั้งแต่เริ่มโปรเจกต์ Git จะไม่เอาไฟล์นี้เข้าเซฟ -
ก่อน commit ทุกครั้ง ดู
git status --shortว่าไม่มี.envอยู่ในรายการ -
ถ้าไม่แน่ใจว่า Git เก็บ
.envไปแล้วหรือยัง ใช้git ls-files .envซึ่งแสดงไฟล์ที่ Git เก็บอยู่ เราลองในโปรเจกต์ตัวอย่างที่เผลอ commit.envไปแล้ว (โปรเจกต์เดียวกับหัวข้อ "ให้ AI ตรวจโปรเจกต์ของคุณ" ข้างล่าง) ได้ผลดังนี้ผลลัพธ์$ git ls-files .env .env
คำสั่งพิมพ์
.envออกมา แปลว่าไฟล์อยู่ในเซฟแล้ว ถ้าไม่พิมพ์อะไรเลย แปลว่ายังไม่อยู่ กรณีนี้.gitignoreช่วยไม่ได้แล้ว เพราะเอกสารของ Git บอกว่าไม่มีผลกับไฟล์ที่ Git เก็บอยู่ ให้ใช้git rm --cached .envซึ่งเลิกเก็บไฟล์ใน Git แต่ไฟล์ในเครื่องยังอยู่ เราลองต่อโดยเพิ่ม.envใน.gitignoreสั่งคำสั่งนี้ แล้ว commit ได้ผลดังนี้ผลลัพธ์$ git rm --cached .env rm '.env' $ git ls-files .env $ git show HEAD~1:.env PAYMENT_SECRET_KEY=fake_secret_0000_demo_only EMAIL_API_KEY=fake_email_key_0000_demo_only
หลัง commit
git ls-files .envไม่พิมพ์อะไรแล้ว แต่git show HEAD~1:.envซึ่งเปิดไฟล์จากเซฟก่อนหน้า ยังแสดงคีย์ปลอมครบ วิธีนี้จึงหยุดได้แค่เซฟใหม่ ถ้าเคย push ขึ้น GitHub แล้ว ให้ทำข้อ 5 ทันที
GitHub มีระบบกันการ push ความลับขึ้น repo สาธารณะ (push protection) เปิดไว้เป็นค่าเริ่มต้นสำหรับบัญชีผู้ใช้ แต่จับได้เฉพาะคีย์ชนิดที่รองรับ จึงเป็นแค่ตาข่ายรองรับ ไม่ใช่ด่านหลัก
ข้อ 2: ห้ามวางคีย์จริงในแชต AI, LINE, ภาพหน้าจอ หรือตอนแชร์จอ
เอกสารของ GitHub เขียนว่า อย่าส่งความลับทางอีเมลหรือแชต ข้อความที่ส่งไปแล้วอยู่ในระบบของคนอื่น เราตามไปลบเองไม่ได้ ภาพหน้าจอและคลิปก็เหมือนกัน
ทำแบบนี้แทน
- บอกชื่อตัวแปร ไม่ต้องบอกค่า AI แก้โค้ดได้โดยรู้แค่ว่าคีย์ชื่ออะไร
- ถ้าต้องให้ดูหน้าตาไฟล์ ใช้ค่าปลอม เช่น
EMAIL_API_KEY=ใส่คีย์ตรงนี้ - อ่านข้อความ error ก่อนวาง ถ้ามีคีย์ติดมา ให้ลบส่วนนั้นออก
- ก่อนแชร์จอ แคปจอ หรืออัดคลิป ปิดแท็บไฟล์
.envและหน้าตั้งค่าคีย์ของผู้ให้บริการ
ตัวอย่างการขอให้ AI ช่วยโดยไม่วางคีย์
ระบบส่งอีเมลขึ้น error ว่า unauthorized คีย์อยู่ในไฟล์ .env ชื่อตัวแปร EMAIL_API_KEY (ไม่ส่งค่าให้ดูนะ) ช่วยดูว่าโค้ดใน server.js อ่านตัวแปรนี้ถูกชื่อไหม และโหลดไฟล์ .env ก่อนใช้งานหรือยัง
คำขอนี้มีชื่อตัวแปร ไฟล์ และอาการครบพอให้ AI ตรวจได้ โดยไม่มีค่าคีย์ในแชต
ข้อ 3: ห้ามใส่คีย์ลับในโค้ดหน้าเว็บ หรือในตัวแปรที่ถูกส่งไปเบราว์เซอร์
โค้ดหน้าเว็บถูกส่งไปที่เบราว์เซอร์ของผู้ใช้ทุกคน ใครเปิดดูก็เห็น ตัวแปรใน .env ที่ขึ้นต้นด้วย NEXT_PUBLIC_ (Next.js) และ VITE_ (Vite) ก็ถูกฝังลงในโค้ดหน้าเว็บด้วย เอกสารของ Vite เขียนชัดว่าตัวแปรแบบนี้ไม่ควรมีข้อมูลลับอย่าง API key
ทำแบบนี้แทน: ใช้คีย์ลับที่ฝั่งเซิร์ฟเวอร์เท่านั้น ให้หน้าเว็บขอให้เซิร์ฟเวอร์ทำงานที่ต้องใช้คีย์แทน รายละเอียดอยู่ใน หน้าเว็บกับหลังบ้าน: ทำไมต้องแยก และคุยกันผ่าน API อย่างไร และ ที่วางเว็บ โดเมน และ HTTPS: ทำให้คนเข้าเว็บได้ (ทั้ง 2 บทความสำหรับสมาชิกฟรี)
ข้อ 4: ห้ามสั่ง AI ที่อ่านไฟล์ในเครื่องได้ ให้เปิดหรือแสดงไฟล์ .env
เครื่องมือ AI เขียนโค้ดอย่าง Claude Code อ่านไฟล์ในโปรเจกต์ได้เอง สิ่งที่ AI อ่านจะกลายเป็นส่วนหนึ่งของบทสนทนา ถ้าสั่งว่า "เปิด .env ให้ดูหน่อย" คีย์ทั้งหมดก็เข้าไปอยู่ในแชตทันที
ทำแบบนี้แทน
- ถ้า AI ต้องรู้ว่าโปรเจกต์มีตัวแปรอะไร ให้ดูจาก
.env.exampleซึ่งมีแต่ชื่อตัวแปร ไม่มีค่าจริง (อ่านเพิ่มในตอนที่แล้ว) - ถ้าใช้ Claude Code ให้ตั้งค่าห้ามอ่านไฟล์
.envไว้เลย
เอกสารของ Claude Code มีตัวอย่างการตั้งค่านี้ ให้เพิ่มส่วน deny ในไฟล์ ~/.claude/settings.json (มีผลกับทุกโปรเจกต์ในเครื่องนี้)
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
}
}บรรทัดแรกห้ามอ่าน .env บรรทัดที่สองห้ามอ่านไฟล์ที่ชื่อขึ้นต้นด้วย .env. เช่น .env.local ซึ่งรวม .env.example ด้วย ถ้าอยากให้ AI อ่าน .env.example ได้ ให้ใส่แค่บรรทัดแรก
กฎเหล่านี้นับจากโฟลเดอร์ที่เปิด Claude Code ถ้าโปรเจกต์มี .env อยู่ในโฟลเดอร์ย่อยด้วย เอกสารบอกว่า Read(**/.env) กันไฟล์ .env ทุกตัวในโฟลเดอร์นั้นและโฟลเดอร์ย่อยทั้งหมด ถ้าไฟล์ตั้งค่ามีค่าอื่นอยู่แล้ว ให้เพิ่มเฉพาะส่วน deny เข้าไปใน permissions เดิม แล้วพิมพ์ /status ใน Claude Code เพื่อดูว่าไฟล์ถูกโหลดแล้ว
การตั้งค่านี้เป็นด่านแรก ไม่ใช่กำแพง เอกสารของ Claude Code บอกว่ากฎห้ามอ่านใช้กับเครื่องมืออ่านไฟล์ของ Claude และคำสั่งที่ระบุชื่อไฟล์ เช่น cat แต่ไม่ครอบคลุมคำสั่งที่ค้นทั้งโฟลเดอร์โดยไม่ระบุชื่อไฟล์ หรือสคริปต์ที่เปิดไฟล์เอง ถ้าต้องกันทุกทาง เอกสารแนะนำให้เปิดโหมด sandbox แม้ตั้งค่าแล้วจึงยังไม่ควรสั่งงานที่ต้องเปิด .env
กฎนี้ยังช่วยลดความเสี่ยงเมื่อ AI อ่านเจอคำสั่งแฝงให้ส่งคีย์ออกไป อ่านเรื่องนี้ได้ที่ Prompt Injection คืออะไร: เมื่อ AI ทำตามคำสั่งที่ซ่อนอยู่ในไฟล์ของคนอื่น
ข้อ 5: คีย์หลุดแล้ว ห้ามแค่ลบไฟล์ ให้ยกเลิกคีย์ที่ผู้ให้บริการก่อน
เอกสารของ GitHub บอกให้ ถือว่าความลับนั้นรั่วแล้ว แม้จะหลุดออกไปแค่วินาทีเดียว และขั้นแรกต้องยกเลิกหรือเปลี่ยนคีย์ เพราะถึงจะเขียนประวัติ Git ใหม่ ข้อมูลก็ยังเข้าถึงได้จาก repo ที่ถูก clone หรือ fork ไปแล้ว และจาก pull request ที่อ้างถึง commit นั้น
ลำดับที่ต้องทำมีดังนี้
-
ยกเลิกคีย์เดิม (revoke) หรือสร้างคีย์ใหม่แทน (rotate) ที่หน้าตั้งค่าของผู้ให้บริการ เมื่อคีย์เดิมถูกยกเลิก คนที่ได้คีย์ไปก็ใช้ไม่ได้แล้ว
-
ใส่คีย์ใหม่ในไฟล์
.envและในหน้าตั้งค่าของที่วางเว็บ ระบบที่ใช้คีย์เดิมจะหยุดทำงานจนกว่าจะใส่คีย์ใหม่ -
เปิดหน้าการใช้งานและหน้าบิลของผู้ให้บริการ ดูว่ามีการใช้งานช่วงที่เราไม่ได้ใช้ไหม ถ้ามี ให้ติดต่อผู้ให้บริการ
-
เก็บกวาดทีหลัง เอาไฟล์ออกจาก Git ตามข้อ 1 GitHub บอกว่าเมื่อยกเลิกคีย์แล้ว การเขียนประวัติ Git ใหม่เพื่อลบคีย์อาจไม่จำเป็น
ลำดับนี้ใช้กับทุกช่องทาง ถ้าเผลอวางคีย์จริงในแชตหรือคลิปที่โพสต์ไปแล้ว ให้เริ่มที่ขั้นที่ 1 เหมือนกัน
ข้อ 6: ห้ามใช้บริการที่คิดเงินตามการใช้งาน โดยไม่ตั้งเพดานหรือการแจ้งเตือน
ถ้าคีย์หลุดโดยไม่มีใครรู้ การแจ้งเตือนค่าใช้จ่ายช่วยให้รู้ตัวเร็ว ถ้าผู้ให้บริการมีให้ตั้งเพดานค่าใช้จ่ายหรือการแจ้งเตือน ให้ตั้งไว้ตั้งแต่วันแรกที่ใส่บัตร
อ่านให้ชัดว่าตัวที่ตั้งเป็นแค่ การแจ้งเตือน หรือเป็น เพดานที่หยุดการใช้งานจริง เช่น เอกสารของ Google Cloud เขียนว่างบประมาณแบบแจ้งเตือนอย่างเดียว ไม่ได้หยุดการใช้งานหรือการใช้จ่ายให้อัตโนมัติ ถ้าตั้งแค่การแจ้งเตือน ต้องมีคนอ่านอีเมลแล้วลงมือเอง
ให้ AI ตรวจโปรเจกต์ของคุณ โดยไม่แสดงค่าคีย์
โปรเจกต์ตัวอย่างที่มีจุดผิด 3 จุด
เราสร้างโปรเจกต์ตัวอย่างของร้านสมมติขึ้นมา 4 ไฟล์ ค่าคีย์ทั้งหมดเป็นของปลอม (ข้อมูลสมมติ)
ไฟล์ .env
PAYMENT_SECRET_KEY=fake_secret_0000_demo_only EMAIL_API_KEY=fake_email_key_0000_demo_only
ไฟล์ .gitignore
node_modules/
ไฟล์ server.js (ฝั่งเซิร์ฟเวอร์)
// ร้านสมมติ: ส่งอีเมลยืนยันออเดอร์
const emailApiKey = "fake_email_key_0000_demo_only";
function sendOrderEmail(order) {
return { to: order.email, key: emailApiKey };
}
module.exports = { sendOrderEmail };ไฟล์ src/checkout.js (โค้ดหน้าเว็บ)
// หน้าเว็บ: ปุ่มจ่ายเงิน (ร้านสมมติ)
const paymentKey = import.meta.env.VITE_PAYMENT_SECRET_KEY;
export function pay(amount) {
return { amount, paymentKey };
}โปรเจกต์นี้ผิด 3 จุด คือ .gitignore ไม่มีบรรทัด .env (ผิดข้อ 1) server.js เขียนคีย์ไว้ในโค้ดตรงๆ และ checkout.js ใช้คีย์ลับผ่านตัวแปร VITE_ (ผิดข้อ 3)
เราลองค้นเอง: การค้นหาคีย์มีกับดัก 2 ข้อ
เราลองค้นคำว่า key, secret, token และ password ในโปรเจกต์ตัวอย่าง การค้นแบบธรรมดาเจอคีย์ใน server.js, checkout.js และ .env (แต่บอกไม่ได้ว่า .gitignore ขาดบรรทัด .env) และแสดงค่าคีย์ออกมาทั้งบรรทัด ถ้า AI ค้นแบบนี้ คีย์จะเข้าไปอยู่ในแชตทันที
การค้นแบบแสดงแค่ชื่อตัวแปรตามแบบที่เราใช้ทดลอง ไม่มีค่าคีย์ออกมา แต่หาบรรทัดที่ใช้ VITE_ ใน checkout.js ไม่เจอ ต้องค้น VITE_ และ NEXT_PUBLIC_ แยกอีกรอบ คำสั่งสำเร็จรูปข้างล่างจึงสั่งให้ค้นแบบไม่แสดงค่า และแยกตรวจเป็น 3 เรื่อง
คำสั่งสำเร็จรูปสำหรับตรวจความลับในโปรเจกต์
วางคำสั่งนี้ในเครื่องมือ AI ที่อ่านไฟล์ในโปรเจกต์ได้ เช่น Claude Code
ช่วยตรวจโปรเจกต์นี้ว่ามีความลับ (คีย์ รหัสผ่าน token) หลุดอยู่ตรงไหนบ้าง แยกตรวจ 3 เรื่อง 1. ไฟล์ .env และไฟล์ env ที่มีค่าจริง (เช่น .env.local, .env.production) ถูก Git เก็บอยู่หรือไม่ (ดูจาก git ls-files) และ .gitignore กันไฟล์เหล่านี้หรือยัง ไม่ต้องนับ .env.example เพราะไฟล์นี้มีแต่ชื่อตัวแปร และ commit ได้ตามปกติ 2. มีคีย์ รหัสผ่าน หรือ token เขียนไว้ในโค้ดตรงๆ หรือไม่ 3. มีความลับอยู่ในตัวแปรที่ถูกส่งไปเบราว์เซอร์หรือไม่ เช่น ตัวแปรที่ขึ้นต้นด้วย NEXT_PUBLIC_ หรือ VITE_ หรืออยู่ในโค้ดหน้าเว็บ กติกา - ห้ามเปิดอ่านหรือแสดงเนื้อหาไฟล์ .env และไฟล์ env ที่มีค่าจริง เวลาค้นทั้งโฟลเดอร์ให้ข้ามไฟล์เหล่านี้ ส่วน .env.example อ่านได้ - ห้ามแสดงค่าของความลับในคำตอบ แม้แต่บางส่วน ค้นด้วยวิธีที่แสดงแค่ชื่อไฟล์ เลขบรรทัด และชื่อตัวแปร - ยังไม่ต้องแก้ไฟล์ใดๆ รายงานเป็นตาราง: ไฟล์ | บรรทัด | ชื่อตัวแปร | ปัญหา | วิธีแก้ที่เสนอ ถ้าพบว่า .env หรือไฟล์ env ที่มีค่าจริงเคยถูก commit ไปแล้ว ให้แยกบอกไว้บนสุด เพราะต้องยกเลิกคีย์ที่ผู้ให้บริการก่อน
คำสั่งนี้ให้ข้ามไฟล์ที่มีค่าจริงตอนค้น เพราะกฎห้ามอ่านของ Claude Code ไม่ครอบคลุมการค้นทั้งโฟลเดอร์ ส่วน .env.example อ่านได้ เพราะตั้งใจ commit และแชร์อยู่แล้ว
ถ้าใช้กับโปรเจกต์ตัวอย่างตอนก่อนแก้ (ยัง commit .env อยู่ และ .gitignore มีแค่ node_modules/) รายงานที่ถูกต้องต้องบอกเรื่องนี้ไว้บนสุด และมีอย่างน้อย 3 แถว คือ .gitignore ที่ไม่มีบรรทัด .env บรรทัดที่ 2 ของ server.js และบรรทัดที่ 2 ของ src/checkout.js คำตอบที่คุณได้จะใช้คำต่างไป ให้ดูว่าครบทุกจุด ไม่มีค่าคีย์ในคำตอบ และไม่รายงาน .env.example ว่าเป็นปัญหา
เช็กลิสต์ก่อน push หรือแชร์จอ
ใช้ 4 ข้อนี้ทุกครั้งก่อน push ขึ้น GitHub แชร์จอ แคปจอ หรืออัดคลิป
-
.envอยู่ใน.gitignoreและไม่โผล่ในgit statusใช่ไหม ถ้าไม่ใช่ ให้เพิ่มบรรทัด.envก่อน commit ถ้า Git เก็บไฟล์ไปแล้ว ทำตามข้อ 1 ถ้าเคย push แล้ว ทำข้อ 5 -
ไม่มีคีย์เขียนไว้ในโค้ดตรงๆ ใช่ไหม ถ้ามี ให้ AI ย้ายค่าไปไว้ใน
.envแล้วแก้โค้ดให้อ่านจากตัวแปร ถ้าโค้ดนั้นเคย commit แล้ว ทำข้อ 5 -
ไม่มีคีย์ลับในตัวแปรที่ส่งไปเบราว์เซอร์ใช่ไหม ถ้ามี ให้ AI ย้ายงานที่ใช้คีย์ไปทำที่ฝั่งเซิร์ฟเวอร์ ถ้าเว็บเคยขึ้นไปแล้ว ทำข้อ 5
-
บนจอไม่มีไฟล์
.envหรือหน้าตั้งค่าคีย์เปิดอยู่ใช่ไหม ถ้ามี ให้ปิดก่อนเริ่มแชร์ ถ้าภาพหรือคลิปที่มีคีย์โพสต์ไปแล้ว ทำข้อ 5
ผ่านครบ 4 ข้อแล้ว จึง push หรือเริ่มแชร์จอได้
สรุป
ไฟล์ .env ห้ามเข้า Git ห้ามวางในแชตหรือโชว์บนจอ ห้ามส่งไปเบราว์เซอร์ และห้ามให้ AI เปิดอ่าน ถ้าคีย์หลุด ให้ยกเลิกคีย์ที่ผู้ให้บริการก่อน และตั้งการแจ้งเตือนค่าใช้จ่ายไว้ให้รู้ตัวเร็ว
นี่คือตอนสุดท้ายของซีรีส์ "เขียนโปรแกรมพื้นฐาน" ถ้าอยากทบทวนตั้งแต่ต้น เริ่มได้ที่ ตัวแปร เงื่อนไข ลูป: 3 อย่างที่ต้องรู้ ก่อนอ่านโค้ดที่ AI เขียนให้
อาทิตย์ละสกิล เดี๋ยวก็เก่ง