เช็กลิสต์ความปลอดภัย API (ตัวตน/สิทธิ์/ช่องโหว่เว็บ)
ไล่ให้ครบก่อน commit ทุกครั้งที่สร้างหรือแก้ route ใน frontend/src/app/api/** และ Go handler ใน backend/internal/adapter/inbound/http/** (กฎข้อ 9, 10, 20 ใน AGENTS.md) ส่วนเงิน/transaction ดู ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch)
A. ตัวตนและสิทธิ์ (AuthN/AuthZ)
- ตัวตนต้องมาจากสิ่งที่ตรวจแล้วเท่านั้น — ห้ามรับ
email/userCode/databaseจาก body มาสร้าง session; Google ID Token ต้องตรวจaud= Client ID ของเว็บ และemail_verified === true - Route ที่เรียก backend ด้วยกุญแจ Admin (header
X-Admin-Api-Key) ต้องตรวจสิทธิ์ Admin ของผู้เรียกฝั่ง server ก่อน (requireAdmin()หรือisWorkspaceAdmin()ในsrc/app/api/workspace/[...path]/route.ts) — แค่มี session ไม่พอ - ค่า actor (
actor_email,actor_user_code) เขียนทับหลัง spread body เช่น{ ...body, actor_email: session.email }ห้ามให้ผู้ใช้ปลอม - Route ที่ไม่ต้อง login ห้ามให้ผู้เรียกเลือก tenant/ฐานข้อมูลเอง (
?db=,?provider=) ให้ตรึงที่ฐานสาธิตsmldemo /blob/insertและ/query/execใช้ write policy เดียวกัน (domainquery.ValidateClientInsert/ValidateClientPolicyในwrite_policy.go): ตารางเงิน/สต็อก/GL ห้ามเขียนตรงจากเบราว์เซอร์
B. ช่องโหว่ฝั่งเว็บ
- returnTo / redirect ใช้
safeReturnPath()(frontend/src/lib/safe-return.ts, มี unit test) เสมอ —startsWith("/") && !startsWith("//")ไม่พอ เพราะ/\evil.comเบราว์เซอร์ตีเป็น//evil.com(ใช้ในlogin/page.tsxและselect-database/page.tsx) - HTML string ที่เข้า
innerHTML, LeafletbindPopup,dangerouslySetInnerHTMLต้อง escape ข้อมูลจาก DB ทุกช่อง (escapePopupHtmlในSmlMapPickerModal.tsx) - ไฟล์อัปโหลดที่ส่งต่อให้เบราว์เซอร์ ใช้
safeMediaContentType()(frontend/src/lib/api-server.ts) อนุญาตเฉพาะรูป raster + PDF พร้อมX-Content-Type-Options: nosniff— ห้ามส่งtext/html/image/svg+xml(ใช้กับapi/crm/image,process/docpicture/image,process/itempicture/image) - อ่านไฟล์จาก MinIO ไม่สำเร็จ ห้ามเขียนรูป placeholder ทับ key เดิม (แสดง placeholder แต่ไม่บันทึกทับ)
ตัวอย่าง
import { safeReturnPath } from "@/lib/safe-return";
router.replace(safeReturnPath(new URLSearchParams(location.search).get("returnTo")));
กฎความลับทั่วไป (ห้ามใส่รหัส/Token ใน repo, ใช้ env) อยู่ที่ กฎขอบเขตงานและกฎเหล็กประจำ repo (Repo Scope & Iron Rules)
ข้อควรระวังการตรวจ backend
- เครื่องที่มีแค่ Go 1.24 (go.mod ต้องการเวอร์ชันใหม่กว่า) ให้ type-check ในสำเนา scratch ที่ใส่
replaceให้ dependency ห้ามแก้go.modจริง แล้วรันgo vet ./... && go test ./internal/... - Unit test frontend ใช้
node --experimental-strip-types --testกับไฟล์*.test.ts - ปัญหาที่ยังเปิดอยู่ที่ต้องตัดสินใจเชิงออกแบบ ห้ามแก้เองโดยไม่ถามลุงจืด (KMS ระบุสถานะปัจจุบันว่าไม่มีรายการค้าง)
ที่มา
.agents/skills/secure-api-data-integrity-checklist/SKILL.mdWorkflow A–Bdocs/kms/KMS_SECURITY_DATA_INTEGRITY_LESSONS.mdตาราง S1–S5, B1, B2, B7
ดูเพิ่ม
สารบัญมาตรฐานและกฎเหล็กของ SML Ai Account (Standards Overview) · บทเรียนบั๊กสิทธิ์และการข้ามฐานข้อมูล (Auth Bypass, Cross-Tenant, Demo Read-Only, Screen Rights) · ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch) · Google Login, Multi-Tenant PDPA และหน้าเลือกโมดูลหลัง Login (Google OAuth, Tenant Isolation, Home Hub) · ภาพรวม Backend Go ของ SML Ai Account (Backend overview)