Security checklist สำหรับ Thai SaaS — 20 items
"ปลอดภัย 99%" = ยังโดน hack. ต้อง 100% systematic.
Why this matters เป็นพิเศษสำหรับไทย
- PDPA — ปรับสูงสุด ฿5 ล้าน + จำคุก 1 ปี ถ้าเปิดเผยข้อมูลส่วนบุคคล
- Brand damage — Thai market พึ่ง trust สูง — leak 1 ครั้ง = หาย customer 50%
- Regulatory scrutiny — Bank of Thailand, SEC, สคส. inspect ถ้ามี complaint
✅ 20-item checklist
ทำเป็นช่องแล้วเช็คทีละข้อ:
🔑 Authentication
- [ ] #1. OAuth-only login (ห้าม password)
- ปลอดภัยกว่า password — Line/Google handle phishing/MFA ให้
- NirvaDeploy ใช้ pattern นี้: ดู
web/lib/auth.ts
- [ ] #2. JWT session ≤ 30 วัน + rotate on action
- ไม่ปล่อย session ยาวไม่จำกัด — เสี่ยงถ้า device หาย
- [ ] #3. MFA สำหรับ admin accounts
- TOTP (Google Authenticator) — Phase 2.x roadmap
- WebAuthn (passkey) — Phase 5
- [ ] #4. Session invalidation on password change
- (Phase 2.x ใช้ OAuth-only — ไม่มี password — แต่ logout-all-devices ต้องทำได้)
🔐 Secrets + credentials
- [ ] #5. Secrets ใน env var เท่านั้น
- ห้าม hardcode, ห้าม commit
.gitignoreมี.env,.env.local
- [ ] #6. Encrypt at rest (DB column-level)
- Railway/Dokploy access tokens → encrypted column (AES-256)
- Use
crypto.subtleหรือ Nodecryptomodule - KDF ใช้
NEXTAUTH_SECRETเป็น input
// web/lib/crypto.ts (Phase 2.x stub)
import { createCipheriv, randomBytes, scrypt } from "node:crypto";
import { promisify } from "node:util";
const scryptAsync = promisify(scrypt);
export async function encrypt(plaintext: string): Promise<string> {
const salt = randomBytes(16);
const key = (await scryptAsync(
process.env.NEXTAUTH_SECRET!,
salt,
32,
)) as Buffer;
const iv = randomBytes(12);
const cipher = createCipheriv("aes-256-gcm", key, iv);
const enc = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
const tag = cipher.getAuthTag();
return Buffer.concat([salt, iv, tag, enc]).toString("base64");
}- [ ] #7. Rotate secrets every 90 days
- Set calendar reminder
- Phase 2.x: NirvaDeploy will track + auto-remind
- [ ] #8. Never log secrets
- Filter middleware ที่ scan logs for
password=,token=,Authorization:
🌐 Network + transport
- [ ] #9. HTTPS only (TLS 1.3)
- Vercel + Cloudflare = HTTPS by default
- HSTS header:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
- [ ] #10. CSP (Content Security Policy)
- บล็อค XSS — ใส่
Content-Security-Policyheader ใน next.config.mjs
async headers() {
return [{
source: "/(.*)",
headers: [
{
key: "Content-Security-Policy",
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://js.stripe.com",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self' https://api.stripe.com",
"frame-ancestors 'none'",
].join("; "),
},
],
}];
}- [ ] #11. CORS strict
Access-Control-Allow-Origin: https://yourapp.com(ห้าม*ใน production)- Exception:
/api/openapi.jsonOK เป็น*(public docs)
- [ ] #12. Rate limit ทุก API endpoint
- Use Upstash Redis + sliding window
- 100 req/min/IP สำหรับ unauthenticated
- 1000 req/min/user สำหรับ authenticated
🛡 Application layer
- [ ] #13. Input validation (Pydantic / Zod)
extra="forbid"ทุก Pydantic model- Zod
.strict()ทุก request schema - NirvaDeploy MCP ทุก tool ใช้ pattern นี้แล้ว
- [ ] #14. SQL injection — parameterized queries only
- ORM (Prisma / SQLAlchemy) จัดการให้แล้ว
- ห้าม
f"SELECT * FROM users WHERE id={user_id}"
- [ ] #15. XSS — ห้าม `dangerouslySetInnerHTML` กับ user content
- ถ้าจำเป็น → use DOMPurify
- NirvaDeploy blog ใช้ custom
<Markdown />component (safe-by-default)
- [ ] #16. CSRF protection
- SameSite=Lax cookies (NextAuth default)
- หรือใช้ CSRF token สำหรับ state-changing endpoints
- [ ] #17. Mass assignment protection
- ห้าม
user.update(req.body)ตรงๆ — filter fields:
ts const { name, email } = req.body; // explicit allowlist await prisma.user.update({ where: { id }, data: { name, email } });
📋 PDPA compliance (Thai-specific)
- [ ] #18. Data deletion (Right to Erasure §33)
- ทุก user ต้อง delete account ได้
- NirvaDeploy มี:
/dashboard/settings/account/delete+/api/account/delete - 7-day grace window
- [ ] #19. Data export (Right of Access §30)
- User ขอ export ข้อมูลทั้งหมด → ส่ง JSON
- NirvaDeploy:
/api/account/export
- [ ] #20. Audit log destructive actions
- Delete service, scale to 0, rotate token, change email → log to DB
- Retain 90 days hot + 5 years cold
- NirvaDeploy schema:
AuditLogmodel inweb/prisma/schema.prisma
🚨 Incident response
ถ้าโดน breach:
- ภายใน 72 ชม. — รายงานสคส. (PDPA §37 mandatory)
- ภายใน 7 วัน — แจ้ง affected users
- เปิด CVE / advisory — ใส่
/.well-known/security.txt - Hire forensics — บริษัทไทย: Sertis, ACIS Professional, IBM X-Force
NirvaDeploy security: [email protected] — encrypted PGP soon
🔍 Dependency scanning
ทำอัตโนมัติ:
# .github/workflows/security.yml
name: Security
on: [push, pull_request]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm audit --audit-level=high
- uses: actions/setup-python@v5
- run: pip install safety && safety check
# SAST
- uses: github/codeql-action/init@v3
- uses: github/codeql-action/analyze@v3Or use Snyk / Dependabot for automated PRs
🧪 Penetration testing
ก่อน production launch หรือ Phase 5:
- Self-test: OWASP ZAP — open source, free
- Paid: Sertis, Cybertron, ACIS — Thai pentesters ~฿80K-200K/test
- Bug bounty: HackerOne / Bugcrowd — community-driven
📋 NirvaDeploy security defaults
ที่เราทำให้ already:
✅ OAuth-only (Line + Google) ✅ JWT 30-day session ✅ Engine credentials encrypted (schema ready) ✅ Audit log table (schema ready) ✅ PDPA delete + export endpoints ✅ security.txt published ✅ DPO contact ([email protected]) ✅ Open redirect prevention in affiliate tracking ✅ SameSite=Lax cookies ✅ HTTPS (Vercel managed) ✅ Pydantic extra="forbid" ทุก MCP tool
ที่ยังต้องทำใน Phase 2.x:
⏳ MFA (TOTP) ⏳ Rate limiting middleware (Upstash Redis) ⏳ CSP header (production-ready) ⏳ Encryption helper (lib/crypto.ts wired) ⏳ Cron job for audit log archive ⏳ Dependency scan in CI ⏳ Bug bounty program
ดู /security สำหรับ disclosure protocol
Security issue พบ? Email `[email protected]` (อย่าเปิด public issue)
ชอบบทความนี้?
ลอง NirvaDeploy ฟรี
Free tier ตลอดชีพ · ไม่ต้องใส่บัตร · Sign in ด้วย Line/Google
เริ่มเลย →