ปุ่ม “Don’t Ask Again” ของ Claude Code จะบันทึกคำสั่งที่คุณอนุมัติแบบเป๊ะ ๆ ลงในไฟล์ .claude/settings.local.json เป็นกฎ allow ถ้าคำสั่งนั้นมีรหัสผ่านหรือ API key อยู่ ความลับนั้นจะถูกเก็บอยู่ในโฟลเดอร์โปรเจกต์ของคุณแบบข้อความล้วน และถ้าไฟล์นี้ถูก commit ขึ้นไป มันก็จะกลายเป็นข้อมูลสาธารณะ บริษัทด้านความปลอดภัย Apiiro พบไฟล์ลักษณะนี้ถึง 1,122 ไฟล์บน GitHub สาธารณะที่มีความลับจริงรวมกัน 1,379 รายการ นี่คือวิธีตรวจสอบ repo ของคุณเองด้วยคำสั่งเดียว เคลียร์ความเสียหาย และป้องกันไม่ให้เกิดขึ้นอีก
เกิดอะไรขึ้น: ผลการค้นพบของ Apiiro ในตัวเลข
Apiiro ค้นหาไฟล์ .claude/settings.local.json ซึ่งเป็นไฟล์รายโปรเจกต์ที่ Claude Code เก็บการอนุมัติสิทธิ์ส่วนตัวของคุณ จาก GitHub สาธารณะ พบไฟล์ 104,185 ไฟล์ใน repo 103,617 แห่ง ในจำนวนนั้นมี 1,122 ไฟล์ที่มีความลับจริงอย่างน้อยหนึ่งรายการ รวมทั้งหมด 1,379 ความลับที่ไม่ซ้ำกัน ตามรายงานของ iTnews เกี่ยวกับงานวิจัยนี้
| ประเภทความลับ | จำนวน |
|---|---|
| รหัสผ่านฐานข้อมูล | 379 |
| Supabase service-role keys | 122 |
| การล็อกอิน SSH สู่เซิร์ฟเวอร์สาธารณะ | 43 |
| โทเคน GitHub, GitLab และ npm | 42 |
| AWS keys | 23 |
เมื่อ Apiiro ขยายการค้นหาไปยึงเวอร์ชันเก่ากว่าของไฟล์ใน git, ไฟล์ที่แชร์ร่วมกัน .claude/settings.json และบันทึกการทำงานของ agent จำนวนความลับเพิ่มขึ้นเป็น 2,539 รายการใน repo 1,994 แห่ง Apiiro ไม่ได้ทดสอบว่า credential เหล่านั้นยังใช้งานได้อยู่หรือไม่ แต่มีองค์กรหนึ่งที่ได้รับแจ้งยืนยันว่า key หนึ่งยังใช้งานได้จริง
ตัวเลขของตัวสแกนคือส่วนที่น่ากังวลที่สุด จากไฟล์ 1,122 ไฟล์ที่มีความลับจริง TruffleHog ตรวจพบ 643 ไฟล์ และ gitleaks ตรวจพบ 564 ไฟล์ มี 215 ไฟล์ที่หลุดรอดจากทั้งสองตัว ดังนั้นการบอกว่า “เรารันเครื่องมือสแกนความลับอยู่” ไม่ใช่หลักฐานว่าคุณสะอาด
เรื่องนี้ติดอันดับหนึ่งบน Hacker News ด้วยคะแนน 582 คะแนน Boris Cherny ผู้ดูแล Claude Code ที่ Anthropic ตอบในเธรดนั้นว่า Claude Code ในอดีตไม่ได้ล้างความลับออกจากไฟล์ และทีมงานกำลังพิจารณาเรื่องนี้อยู่ อ่านงานวิจัยต้นฉบับของ Apiiro
ทำไม “Don’t Ask Again” ทำให้ความลับหลุดเข้าไปอยู่ในไฟล์
เมื่อ Claude Code ต้องการรันคำสั่ง Bash มันจะถามก่อนเสมอ หากคุณเลือก “Yes, and don’t ask again” Claude Code จะเขียนการอนุมัติถาวรลงใน .claude/settings.local.json เป็นกฎ allow ตามที่เอกสาร settings ของ Anthropic อธิบายไว้ กฎนี้จะบันทึกข้อความของคำสั่ง ถ้าคำสั่งเป็นแบบนี้:
psql "postgresql://admin:Sup3rS3cret@db.example.com:5432/prod" -c "select count(*) from users"
ไฟล์ settings ของคุณก็จะมีเนื้อหาประมาณนี้:
{
"permissions": {
"allow": [
"Bash(psql \"postgresql://admin:Sup3rS3cret@db.example.com:5432/prod\" -c \"select count(*) from users\")"
]
}
}
รหัสผ่านอยู่ในกฎเพราะมันอยู่ในคำสั่ง Claude Code บันทึกสิ่งที่คุณอนุมัติแบบคำต่อคำ

ทำไมมันจึงไปอยู่บน GitHub
Claude Code พยายามไม่ให้ไฟล์นี้เข้าสู่ git ครั้งแรกที่มันเขียน .claude/settings.local.json ใน repo ที่ยังไม่ได้ ignore ไฟล์นี้ มันจะเพิ่ม **/.claude/settings.local.json ลงในไฟล์ global git excludes ของคุณ แต่การป้องกันนี้มีช่องโหว่:
- คุณสร้างไฟล์นั้นด้วยตัวเอง เอกสารระบุชัดเจนว่า: ถ้าคุณสร้างไฟล์นี้เอง คุณต้องเพิ่มมันลงใน
.gitignoreด้วยตัวเอง ความเห็นของ Cherny บน HN คือไฟล์ที่รั่วไหลเหล่านี้ถูกสร้างขึ้นด้วยมือแล้วถูก commit เข้าไป - กฎ ignore มีผลเฉพาะบนเครื่องเดียว มันอยู่ใน global excludes ของคุณ ไม่ใช่
.gitignoreของ repo เพื่อนร่วมทีม, CI job หรือเครื่องใหม่ที่คัดลอกโฟลเดอร์มา จะไม่ได้รับการป้องกันนี้ - ไฟล์ถูกเพิ่มแบบ force-add หรือถูก track มาก่อนกฎจะเกิดขึ้น
git add -fจะข้ามกฎ ignore และเมื่อไฟล์ถูก track แล้ว กฎ ignore จะไม่มีผลกับไฟล์นั้นอีก - ไฟล์ที่แชร์ร่วมกัน ในส่วนขยาย VS Code การ์ดอนุมัติให้คุณเลือกไฟล์ปลายทางได้ รวมถึง
.claude/settings.jsonที่ถูก commit กฎที่บันทึกไว้ที่นั่นจะส่งผลกับทุกคน
ตรวจสอบ repo ของคุณด้วยคำสั่งเดียว
เริ่มจาก repo ที่คุณอยู่ คำสั่งนี้บอกคุณว่าไฟล์ถูก track อยู่หรือไม่ และเคยถูก commit หรือเปล่า:
git ls-files | grep -E '(^|/)\.claude/settings(\.local)?\.json$'
git log --all --name-only --format= | grep -E '\.claude/settings(\.local)?\.json$' | sort -u
ถ้าบรรทัดแรกแสดงผลอะไรออกมา แปลว่าไฟล์อยู่ใน tree ปัจจุบันของคุณ ถ้าบรรทัดที่สองแสดงผลอะไรออกมา แปลว่ามันอยู่ในประวัติของคุณ แม้ว่าคุณจะลบมันไปแล้วก็ตาม
หากต้องการกวาดตรวจทุก repo ใต้โฟลเดอร์หนึ่งพร้อมกัน:
find ~/code -path '*/.claude/settings.local.json' -exec sh -c \
'cd "$(dirname "$1")/.." && git ls-files --error-unmatch .claude/settings.local.json >/dev/null 2>&1 && echo "TRACKED: $PWD"' _ {} \;
สำหรับองค์กรบน GitHub คุณสามารถใช้ GitHub CLI ค้นหาโค้ดตามชื่อไฟล์ได้:
gh search code permissions --owner your-org --filename settings.local.json
แล้วตรวจเนื้อหาในไฟล์ที่พบ เพราะเครื่องมือสแกนพลาดไป 19% ของไฟล์ที่รั่วไหล คุณควรอ่านกฎต่าง ๆ ด้วยตัวเองแทนการเชื่อผลสแกนสีเขียว:
grep -nE 'Bash\(' .claude/settings.local.json | grep -iE 'pass|token|key|secret|://[^/]*:[^@]*@'
Connection string ที่มี user:password@, header Authorization: Bearer, -p ตามด้วยรหัสผ่านเป็นข้อความจริง หรือสิ่งใดที่ขึ้นต้นด้วย sk-, ghp_, AKIA หรือ eyJ คือ credential ทั้งสิ้น รัน gitleaks กับ repo เป็นขั้นตอนที่สอง ไม่ใช่ขั้นตอนเดียว
วิธีแก้ไขเมื่อไฟล์ settings รั่วไหล
ลำดับขั้นสำคัญมาก ต้องหมุนเปลี่ยน (rotate) credential ก่อน เพราะการลบไฟล์ไม่ช่วยอะไรกับสำเนาที่อยู่ใน fork, clone และ cache ไปแล้ว
- หมุนเปลี่ยน credential ทุกตัวที่ไฟล์นี้เคยเก็บ ตรวจประวัติทั้งหมดของไฟล์ด้วย
git log -p --all -- .claude/settings.local.jsonจดทุกความลับที่พบ แล้ว revoke แต่ละตัวที่ผู้ให้บริการของมัน Apiiro ก็แนะนำให้ทำขั้นตอนนี้ก่อน - ถอนการ track ไฟล์และ ignore มันในตัว repo เอง:
git rm --cached .claude/settings.local.json
echo '.claude/settings.local.json' >> .gitignore
git add .gitignore && git commit -m "Stop tracking Claude Code local settings"
git check-ignore -v .claude/settings.local.json
คำสั่งสุดท้ายควรแสดงบรรทัดใน .gitignore ที่ตรงกัน กฎใน repo จะปกป้องทุก clone
- ล้างประวัติถ้า repo เป็นสาธารณะหรือถูกแชร์กว้าง git-filter-repo ลบไฟล์ออกจากทุก commit:
git filter-repo --invert-paths --path .claude/settings.local.json
git push --force --all
ขั้นตอนนี้จะเขียนประวัติใหม่สำหรับทุกคน จึงควรเตือนทีมก่อน และมันไม่ไปถึง fork ด้วย จึงเป็นเพียงการเคลียร์ ไม่ใช่ตัวแทนของขั้นตอนที่ 1
- เคลียร์ไฟล์ในเครื่องด้วย เปิด
.claude/settings.local.jsonลบกฎใด ๆ ที่มีความลับเป็นข้อความจริง แล้วแทนที่ด้วย pattern (ดูหัวข้อถัดไป) - เปิดใช้ push protection GitHub secret scanning push protection จะบล็อก push ที่มีรูปแบบความลับที่ระบบจดจำได้ มันไม่ได้จับทุกอย่าง ตามที่ไฟล์ 215 ไฟล์ที่หลุดรอดแสดงให้เห็น แต่มันหยุดรูปแบบโทเคนทั่วไปได้
ป้องกันไม่ให้เกิดขึ้นอีก
ทางแก้พูดง่าย ๆ ว่า: อย่าใส่ความลับเป็นข้อความจริงในคำสั่งที่ agent ของคุณรัน และอนุมัติเป็น pattern แทนคำสั่งเป๊ะ ๆ

อ้างอิงความลับ อย่าพิมพ์มันลงไป เชลล์จะขยายตัวแปรในขณะรัน แต่กฎ allow จะเก็บข้อความตามที่เขียนไว้ ดังนั้น psql "$DATABASE_URL" จะบันทึก $DATABASE_URL ในกฎ ไม่ใช่รหัสผ่าน:
{
"permissions": {
"allow": ["Bash(psql \"$DATABASE_URL\" *)", "Bash(npm run test *)"],
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
กฎ deny มาจากเอกสาร settings ของ Anthropic โดยตรง มันป้องกันไม่ให้ Claude Code อ่านไฟล์ .env ของคุณ จึงไม่สามารถคัดลอก key จากที่นั่นไปใส่ในคำสั่งได้เช่นกัน
จำกัดขอบเขตของกฎให้แคบ ผู้คอมเมนต์บน HN ที่อ้างงานวิจัยบอกว่า 5% ของไฟล์อนุญาตคำสั่งเชลล์ใด ๆ และ 43% มีกฎ interpreter เช่น Bash(python:*) กฎแบบนี้ปล่อยให้ agent รันอะไรก็ได้ผ่าน Python จึงเท่ากับเป็นกฎ allow-everything ที่ยุ่งยากขึ้น
พิจารณาใช้ auto mode และ sandbox Cherny แนะนำ auto mode แทนการเขียนกฎสิทธิ์ด้วยมือ และบอกว่า Anthropic สร้าง sandbox แบบโอเพนซอร์สไว้ มีผู้คอมเมนต์หลายคนชี้ว่า auto mode เป็น classifier ไม่ใช่ขอบเขตด้านความปลอดภัย จึงควรใช้คู่กับนิสัยที่กล่าวมาข้างต้น
เก็บ agent ให้ห่างจากความลับของ production key ที่ปลอดภัยที่สุดคือ key ที่ agent ไม่เคยเห็น เราเคยพูดถึงแนวทางนี้ใน วิธีให้ AI agent ใช้ API key โดยไม่ต้องเห็นมัน และสิ่งที่ผู้โจมตีทำกับ AI key ที่รั่วไหลใน AI API keys ที่ถูกขโมยและ LLMjacking
ให้ coding agent ของคุณเรียก API โดยไม่ต้องพิมพ์ key ด้วย Apidog CLI
วิธีที่พบบ่อยที่ key หลุดเข้าไปในคำสั่งที่ถูกอนุมัติ คือการเรียก API อย่างรวดเร็ว เช่น curl -H "Authorization: Bearer sk-..." เพื่อเช็ก endpoint คุณสามารถมอบงานนี้ให้ Apidog CLI แทนได้ key จะอยู่ในตัวแปร environment ของ Apidog scenario ทดสอบของคุณจะอ้างอิงมันเป็น {{API_KEY}} และคำสั่งที่ agent รันจะมีเพียง project, scenario และ environment ID เท่านั้น ไม่มีความลับใด ๆ ให้ถูกบันทึก
ตั้งค่าครั้งเดียว ใน terminal ของคุณเองแทนที่จะผ่าน agent เพื่อให้ access token ของคุณไม่ผ่านการอนุมัติใด ๆ:
npm install -g apidog-cli@latest
apidog auth login
npx -y skills add https://apidog.com # pick Claude Code when prompted
แล้วสั่ง Claude Code ด้วย prompt เดียว:
List the environments in Apidog project 123456, then run test scenario 7890
against the staging environment and summarise any failed assertions.
The API key is stored in that environment as {{API_KEY}}. Never pass a key,
token or password on the command line, and never use --env-var for secrets.
Agent จะรันคำสั่งลักษณะนี้ ซึ่งปลอดภัยพอให้อนุมัติด้วย “Don’t Ask Again” ได้:
apidog environment list --project 123456
apidog run -t 7890 --project 123456 -e <envId> -r cli,json
มีข้อควรระวังตรงไปตรงมาสองข้อ ข้อแรก apidog run ใช้ค่าที่แชร์ของตัวแปร ซึ่งถูกซิงก์ไปยัง Apidog และสมาชิกของโปรเจกต์สามารถเห็นได้ จึงควรเก็บ test key ที่จำกัดสิทธิ์ไว้ที่นั่น ไม่ใช่ root key ของ production ถ้าคุณต้องการเก็บค่าไว้บนดิสก์ apidog run รับ --variables <path> ได้เช่นกัน ให้ชี้ไปยังไฟล์นอก repo ข้อที่สอง แฟล็ก --env-var "key=value" มีไว้สำหรับส่งตัวแปรผ่าน command line ซึ่งเป็นรูปแบบที่ทำให้เกิดการรั่วไหลพอดี จึงควรบอก agent ของคุณไม่ให้ใช้กับความลับ
ทีมที่ใช้แพลน Enterprise ยังดึงความลับจาก HashiCorp Vault, Azure Key Vault หรือ AWS Secrets Manager ได้ด้วย Apidog Vault Secrets และ Enterprise SaaS Secret Scanner จะระบุ key ที่ถูกบันทึกใน requests, scripts และตัวแปรของ Apidog มันไม่ได้สแกน repo บน GitHub จึงควรใช้วิธีตรวจสอบข้างต้นควบคู่กันไป ดูคำแนะนำการตั้งค่าแบบเต็มได้ที่ วิธีใช้ Apidog CLI ใน Claude Code และ การจัดการ environment และตัวแปรความลับใน Apidog แพลน Free ของ Apidog รองรับผู้ใช้ได้ถึง 4 คน
คำถามที่พบบ่อย
settings.local.json ของ Claude Code ถูก gitignore ไว้โดยค่าเริ่มต้นหรือไม่?
บางส่วน เมื่อ Claude Code สร้างไฟล์นี้ใน git repository มันจะเพิ่ม **/.claude/settings.local.json ลงใน global git excludes ของคุณ ซึ่งป้องกันเฉพาะเครื่องของคุณ และไม่มีผลหากคุณสร้างไฟล์ด้วยตัวเองหรือ force-add มัน ควรเพิ่มบรรทัดนี้ลงใน .gitignore ของ repo เองด้วย
การลบไฟล์ทำให้ key ที่รั่วไหลหายไปหรือไม่?
ไม่ key ยังอยู่ในประวัติ git, ใน fork และในทุก clone ที่สร้างไว้ขณะที่มันเป็นสาธารณะ หมุนเปลี่ยน key ก่อน แล้วจึงถอนการ track ไฟล์และล้างประวัติด้วย git-filter-repo
gitleaks หรือ TruffleHog จับการรั่วไหลแบบนี้ได้หรือไม่?
ไม่ชัวร์ ในตัวอย่างของ Apiiro มีไฟล์ 215 จาก 1,122 ไฟล์ที่มีความลับจริงซึ่งทั้งสองเครื่องมือพลาด รันเครื่องมือสแกน แล้วอ่านกฎ Bash(...) ในไฟล์ด้วยตัวเองด้วย
นี่เป็นปัญหาของโมเดลหรือปัญหาของ Claude Code?
Apiiro ทดสอบซ้ำได้กับ Opus 5.5 และ Fable 5.1 และสรุปว่าเป็นลักษณะของ Claude Code ไม่ใช่โมเดล การอนุมัติจะเก็บข้อความคำสั่ง ไม่ว่าโมเดลใดจะเป็นผู้เขียนคำสั่งนั้น
ฉันจะอนุมัติคำสั่งอย่างปลอดภัยใน Claude Code ได้อย่างไร?
อนุมัติเป็น pattern เช่น Bash(npm run test *) และอ้างอิงความลับเป็นตัวแปร environment เช่น $DATABASE_URL เพิ่มกฎ deny สำหรับ Read(./.env) และ Read(./.env.*) ด้วย
