nirva|deploy
2026-05-19·11 min read·NirvaDeploy team
#security#PDPA#best-practices#Thai-SaaS

Security checklist สำหรับ Thai SaaS — 20 items

"ปลอดภัย 99%" = ยังโดน hack. ต้อง 100% systematic.

Why this matters เป็นพิเศษสำหรับไทย

  1. PDPA — ปรับสูงสุด ฿5 ล้าน + จำคุก 1 ปี ถ้าเปิดเผยข้อมูลส่วนบุคคล
  2. Brand damage — Thai market พึ่ง trust สูง — leak 1 ครั้ง = หาย customer 50%
  3. 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 หรือ Node crypto module
  • 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-Policy header ใน 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.json OK เป็น * (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: AuditLog model in web/prisma/schema.prisma

🚨 Incident response

ถ้าโดน breach:

  1. ภายใน 72 ชม. — รายงานสคส. (PDPA §37 mandatory)
  2. ภายใน 7 วัน — แจ้ง affected users
  3. เปิด CVE / advisory — ใส่ /.well-known/security.txt
  4. 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@v3

Or 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

เริ่มเลย →