// docs / baas security / clerk hardening
Clerk 安全清單:20 項
Clerk 為你的應用程式處理驗證、工作階段與組織 — 這代表設定錯誤的 Clerk 整合就是驗證繞過、工作階段固定向量或組織外洩路徑。本清單是涵蓋金鑰、工作階段設定、webhook、組織、JWT 範本與持續監控的 20 項稽核。AI 編碼工具會以合理預設快速接好 Clerk;本清單捕捉它們留下的項目。
關於驗證層設定錯誤為何是 AI 工具弱點的背景,請參閱 AI 編碼工具為何留下安全漏洞。關於 Auth0 上的對應清單,請參閱 Auth0 安全清單。
環境金鑰與來源允許清單
Clerk 為每個專案發行兩種不同的金鑰。混淆或洩漏它們是第一個失敗模式。
- 在瀏覽器中使用可公開金鑰 (生產為
pk_live_*、開發為pk_test_*);僅在伺服器端使用機密金鑰 (sk_live_*/sk_test_*)。可公開金鑰在NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY中是安全的;機密金鑰絕不能帶有公開的 env 前綴,也絕不能出現在用戶端元件中。 - 驗證生產應用程式使用
pk_live_*,而非pk_test_*。測試執行個體允許未驗證的電子郵件地址與停用的 MFA — 將測試模式發布到生產就是一種驗證繞過。 - 在 Clerk 儀表板中設定允許的來源。Settings → Domains → Allowed origins 必須精確列出你的生產網域。空白或萬用字元的來源清單會讓攻擊者能建立與你後端通訊的假冒 Clerk 前端。
- 在任何離職或疑似洩漏時輪換機密金鑰。儀表板 → API Keys → Reset。舊金鑰失效;在輪換生效前以新值重新部署伺服器端程式碼。
工作階段設定
工作階段過期與閒置逾時是被竊工作階段為 10 分鐘事件還是 30 天事件的差別。
- 對處理敏感資料的 SaaS 應用程式,將工作階段閒置逾時設為 30 分鐘或更短。儀表板 → Sessions → Inactivity timeout。銀行等級的應用程式應使用 5-10 分鐘;標準 SaaS 為 30-60 分鐘;消費性應用程式為 1-7 天。預設為 7 天。
- 在密碼變更、電子郵件變更與 MFA 註冊時啟用工作階段撤銷。儀表板 → Sessions → Revoke on。這些是使用者主動發起的安全事件;其他裝置上的現有工作階段應被終止。
- 在每條受保護路由上於伺服器端驗證工作階段,而不僅在登入時。在 Next.js 中:伺服器元件 / API 路由中的
const { userId } = await auth();會從 cookie 讀取 JWT 並驗證它。絕不要只信任 cookie 檢查。 - 在工作階段 cookie 上設定
SameSite=Lax(預設) 或Strict。在 DevTools → Application → Cookies 中驗證。SameSite=None是 CSRF 向量 — 除非你已明確設定跨網域驗證設定,否則絕不要使用。
Webhook 驗證
Clerk webhook 會在使用者生命週期事件 (created、updated、deleted、session.ended) 上觸發。它們是你資料庫的同步機制 — 而偽造的 webhook 就是一種資料庫寫入原語。
- 對每個 webhook 驗證 Svix 簽章。Clerk webhook 由 Svix 簽署。使用
new Webhook(secret).verify(body, headers)。驗證失敗時以401拒絕。 - 將 webhook 機密存於環境變數,絕不在程式碼中。機密會在每次儀表板重新產生時輪換 — 你的部署必須從 env 讀取它,而非從常數。
- 每個處理程式都要具備冪等性。Webhook 投遞可能重複。在
webhook_events資料表中使用svix-id標頭作為主鍵以進行去重複。將狀態變更與冪等插入包進同一筆交易。 - 在
user.deleted上,24 小時內硬刪除或匿名化 PII。GDPR / CCPA 都要求這樣做。稽核刪除路徑:哪些資料表持有此使用者的資料?在能用的地方使用 FK ON DELETE CASCADE。
組織與權限
如果你使用 Clerk Organizations,組織邊界就是你的租戶隔離。每個伺服器端查詢都必須以它過濾。
- 在每條 API 路由上,從
auth()讀取userId與orgId,並以兩者過濾資料庫查詢。WHERE org_id = $orgId AND user_id = $userId。絕不要信任來自請求主體的org_id。 - <strong>Use Clerk role checks for privileged operations, not boolean checks against the user object.</strong> <code>has({ role: 'org:admin' })</code> reads the role from the verified JWT. A user can spoof a boolean on a stale client object; they cannot spoof a JWT claim.
- 以兩個真實組織帳號測試跨組織隔離。建立組織 A、填入資料、在另一個瀏覽器中以組織 B 登入,嘗試透過 API 讀取組織 A 的資料。回應必須是
403或404。
JWT 範本與外部整合
JWT 範本將 Clerk 身分推送到 Supabase、Firebase 與其他下游服務。設定錯誤的範本會過度共享宣告或暴露你並不打算暴露的資料。
- 對每個 JWT 範本,列出每個宣告並確認其必要性。儀表板 → JWT Templates。一個會把
email和phone傳給 Supabase 的範本,會將 PII 暴露給任何能在瀏覽器中讀到 JWT 的人。 - 對用於用戶端下游呼叫的 JWT 範本設定短的過期時間。下游 API 請求 60 秒是標準。長壽的 JWT 會被竊取並重放。
- 在接收端驗證對象 (
aud) 宣告。Supabase、Firebase 等應檢查aud是否符合預期的服務識別碼。若沒有這項檢查,為服務 A 發行的 JWT 可以驗證至服務 B。
營運監控
驗證是你擁有的最高訊號日誌來源。要監視它。
- 對每 IP / 每帳號的登入失敗激增告警。正常失敗率的 50 倍就是憑證填充攻擊。Clerk 會將這些事件發送到 webhook;將它們路由到你的 SIEM。
- 每季檢視工作階段與執行個體設定的漂移。隨著 Clerk 更新,預設值會變;「舊設定」會隨時間悄悄變成錯誤。將儀表板 JSON 匯出與你最後已知正確的副本進行差異比較。
後續步驟
對你的生產 URL 執行 FixVibe 掃描 — baas.clerk-auth0 檢查會標記 Clerk 可公開金鑰、生產中的測試金鑰,以及被包進套件的機密金鑰。關於 Auth0 上的對應清單,請參閱 Auth0 安全清單。關於跨 BaaS 提供者的總覽,請閱讀 BaaS 設定錯誤掃描器。
