Community程式設計與開發github.com

安全應用程式腳手架

用於啟動、搭建或重新架構一個必須從設計上確保安全的網路應用程式(符合 ANSSI/CIS/FBI/OWASP ASVS 標準),或是在添加驗證、授權、檔案上傳、稽核日誌、管理員功能、Docker/Podman 部署或 MCP 端點時使用。會產生一個無 root 權限的 TypeScript 前端 + Python 後端 + 強化版 PostgreSQL 堆疊,並包含零信任輸入、物件層級授權、資料欄位層級加密、等冪寫入、OIDC/LDAPS/WebAuthn、防篡改稽核日誌、蜜令、簽章映像檔、雙重掃描(Trivy + OpenSCAP)以及上線前的清理程序。

安全應用程式腳手架 是什麼?

安全應用程式腳手架技能可以自動化產生一個「從設計上安全」的 Web 應用程式堆疊,遵循 ANSSI、CIS、FBI 和 OWASP ASVS Level 2 等嚴格的安全標準。它會同時產生一個 TypeScript 前端、一個 Python 後端和一個強化的 PostgreSQL 資料庫,並內建多層防禦機制,包括無 root 權限的容器、零信任輸入驗證、物件層級授權與資料欄位層級加密、防篡改稽核軌跡、供應鏈安全(鎖定依賴、SBOM 與映像檔簽章)、以及主動式防禦(蜜令)。此技能適用於任何需要快速建立合規、安全、可生產部署的應用程式,同時也處理 OIDC/LDAP/WebAuthn 等進階驗證、基於角色的存取控制、檔案上傳安全、以及預先設定的 Docker/Podman 部署,且無需手動設定環境變數即可立即運作。它支援 Docker 和 rootless Podman 作為部署目標,明確避免產生 Kubernetes 或 Helm 配置(除非使用者明確要求),並包含一個一鍵啟動的 `docker compose up` 工作流程,確保從乾淨的程式碼簽出到運行的體驗流暢無阻。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/SkouedLabs/SkouedSkills/tree/HEAD/.claude/skills/secure-app-scaffolder

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

安全應用程式腳手架 是做什麼的?

產生一個符合 ANSSI、CIS、FBI 和 OWASP ASVS Level 2 標準的「從設計上安全」的應用程式:TypeScript 前端、Python 後端、強化版 PostgreSQL。

佈局、README 和 UI 遵循 project-blueprint 技能。此技能中的安全規則優先於任何便利性或 UX 規則。

參考檔案(產生對應成品時請讀取)

使用時機

  • 啟動、搭建或架構一個新的 Web 應用程式或服務。
  • 需求中提及 ANSSI、CIS、FBI、OWASP、強化、無 root 權限、合規。
  • 添加驗證、授權、檔案上傳、稽核日誌、管理員功能、部署檔案或 MCP 端點。

部署目標: 僅限 Docker 和 rootless Podman。除非使用者明確要求,否則不要產生 Kubernetes、Helm 或其他編排器清單。

0. 威脅模型

  • 建立 docs/security/threat-model.md(≤ 1 頁):資產、信任邊界、參與者、主要風險 (STRIDE) 以及對應的控制措施。當出現新的信任邊界(如上傳、Webhook、LLM、MCP)時,更新此文件。

1. 容器與執行時期

  • 無 root 權限: 每個映像檔都以數字 USER(例如 USER 10001:10001)結尾,包括 Web 伺服器(nginxinc/nginx-unprivileged,連接埠 > 1024)。
  • 最小化、釘選映像檔: 多階段建置;執行階段為 distroless 或 slim,無 shell、編譯器或套件管理器;排除開發依賴。基礎映像檔由摘要釘選。使用最新的穩定版 Python。
  • 強化設定: read_only、tmpfs 用於可寫入路徑、cap_drop: [ALL]、no-new-privileges、執行階段預設 seccomp 設定檔(絕不使用 unconfined)、pids_limit、記憶體限制、健康檢查、停用核心傾印(ulimits: core: 0)。僅反向代理發佈連接埠;資料庫網路為 internal: true。絕不掛載 Docker/Podman 的 socket。
  • 無子程序: 不使用 subprocess、os.system、shell=True。透過以下方式強制執行:映像檔中無 shell、SAST 規則、以及在每個 Worker 啟動後載入的處理序內 seccomp 過濾器(拒絕 execve/execveat)(容器層級的拒絕會阻止進入點本身啟動)。
  • 首次執行保證: 在乾淨的程式碼簽出後,docker compose up(也支援 docker-compose up 和 podman compose up)能一試成功:無需 .env、無需手動步驟、無需容器引擎以外的先決條件。映像檔自動建置(build:),僅使用 Docker Compose v2 和 podman-compose 支援的 Compose Specification 功能,不使用儲存庫外的主機路徑,發佈的連接埠 > 1024,不設定 CPU 限制(在許多 rootless cgroup 設定中不可用)。make up 是相同指令的精簡包裝。
  • 無硬編碼密碼: 一個一次性 init 服務會將密碼產生至一個命名磁碟區(0600),並透過 *_FILE 變數使用。在正式環境中,密碼從檔案讀取,而非環境變數。
  • 隔離執行: 所有 JS/CSS/字型/圖示均打包;無 CDN、執行時期下載或遙測。在離線建置時,依賴項來自內部鏡像(Nexus、Artifactory、devpi、Verdaccio)。
  • Vault 就緒: 單一密碼提供者抽象層(預設為 file,正式環境使用 vault/sops)。
  • 內部 TLS: 後端 ↔ 資料庫之間使用 TLS;服務之間可選用 mTLS。

2. 供應鏈與掃描

  • 鎖定依賴: 提交 lockfile;npm ci、uv sync --frozen 或 pip install --require-hashes。若無套件需要安裝腳本(需加入允許清單),則 .npmrc 設定 ignore-scripts=true。
  • 建置前閘道: npm audit --audit-level=high 和 pip-audit 在退出碼 > 0 時使建置失敗。
  • SAST 與密碼掃描: pre-commit 勾點包含 ruff、bandit/semgrep、eslint(+ eslint-plugin-security)、gitleaks。
  • 映像檔掃描(make scan): trivy image(CVE + 密碼 + 錯誤設定)、trivy config(針對 Dockerfile 和 Compose)、oscap-podman(或 oscap-docker)針對基礎作業系統的 CIS 設定檔。
  • SBOM 與簽章(make sbom): CycloneDX SBOM(Trivy 或 Syft),映像檔使用 cosign 簽署(基於金鑰,適用於離線環境),SBOM 作為證明附加;部署時驗證簽章。
  • DAST(可選,建議使用): 在 CI 中針對執行中的堆疊執行 OWASP ZAP 基準掃描。
  • 更新: 按照固定週期使用 Renovate/Dependabot(或等效的離線審查)。

3. 前端 (TypeScript)

  • 位置: /frontend 及其專屬 Dockerfile,建置為靜態資源並由無特權的 Nginx 提供服務。
  • CSP 相容程式碼: 無內嵌 <script>,無 eval/new Function,無執行時期 CSS-in-JS 注入不含 nonce 的 <style>。偏好使用編譯後的 CSS。啟用 Trusted Types(require-trusted-types-for 'script')。
  • 零信任輸入: 每個表單使用 typed Zod schema,並與 API 型別共用。絕不在不受信任的資料上使用 dangerouslySetInnerHTML/v-html;若無法避免使用 RTF 內容,則使用 DOMPurify。
  • 等冪性: API 客戶端為每個 POST/PUT/PATCH/DELETE 請求附加一個 Idempotency-Key(UUIDv4),每次使用者動作產生一次,並在重試時重複使用。
  • CSRF: 自訂標頭(X-Requested-With)+ CSRF Token;後端也會檢查 Origin/Sec-Fetch-Site。僅使用 CORS 允許清單,絕不搭配憑證使用 *。
  • 開放式重新導向: 登入後的 next/returnUrl 僅接受以單一 / 開頭的相對路徑。
  • 套件中無密碼: 正式環境中無 source map;localStorage/sessionStorage 中不存放敏感資料。

4. 後端 (Python) 與資料庫

  • 驗證: 每個請求主體、查詢參數、路徑參數和標頭均透過 Pydantic 驗證,包含最大長度及 extra="forbid"(防止大量賦值:role、owner_id、is_admin 無法從輸入綁定)。
  • 資源限制: 最大請求主體大小、最大 JSON 深度/陣列長度、最大頁面大小(例如 100)、伺服器端逾時。使用者輸入上的正則表達式有界限或使用線性時間引擎 (re2) 以避免 ReDoS。
  • 安全解析: 不使用 pickle、marshal、yaml.load(使用 yaml.safe_load)、eval。XML 使用 defusedxml。範本來源中無使用者輸入(SSTI)。檔案路徑需解析並對照基礎目錄進行檢查(防止路徑遍歷)。
  • 等冪性儲存: (user_id, key) -> request_hash, status, response,TTL 為 24 小時。相同金鑰與相同雜湊值會回傳已儲存回應;不同雜湊值則回傳 422。這可防止重複請求;重放攻擊的防護來自 TLS、CSRF Token 和短會話期限。
  • SQL: 僅使用 ORM 或參數化查詢;動態識別符(ORDER BY、欄位名稱)需透過允許清單。
  • 資料欄位層級加密: PII 在應用程式中使用 AES-256-GCM 加密,採用信封加密(每筆記錄的 DEK 由密碼提供者的主金鑰包裝),使用 key_version 欄位進行輪換,可搜尋欄位使用 HMAC-SHA256 盲索引。主金鑰絕不儲存在資料庫或資料庫備份中。
  • 資料庫強化: 最小化 PostgreSQL,scram-sha-256,TLS,兩個角色(遷移擁有者、執行時期僅 DML),應用程式不使用超級使用者,Alembic 遷移,執行時期角色設定 statement_timeout。
  • SQL 控制台(若有的話): 唯讀角色,僅允許單一 SELECT,statement_timeout,列數限制,鎖定設定。
  • 密碼學與後量子: 靜態加密的 AES-256-GCM 具備量子抗性。PQ 就緒目標是金鑰交換和簽章:代理上使用混合 TLS X25519MLKEM768;ML-KEM/ML-DSA(FIPS 203/204)僅在函式庫支援時使用。隨機值來自 secrets/crypto.getRandomValues。絕不自行實作密碼學原始類型。
  • 對外請求 (SSRF): 任何可由 UI 設定的 URL(Webhook、syslog、LLM、OIDC)均經過驗證:僅允許 https(除非有明確允許清單),若解析後的 IP 為 loopback/link-local/metadata(169.254.0.0/16、fd00:ec2::254)或私有 IP(除非允許清單中有),則拒絕,DNS 解析後重新檢查(防止 DNS 綁架),無跨主機重新導向,嚴格的逾時設定。
  • 對外 Webhook: 使用 HMAC-SHA256 簽署(X-Signature + 時間戳記),以便接收方驗證。
  • 電子郵件: 標頭值中去除 CR/LF;使用帶有憑證驗證的 SMTPS。
  • 匯出: 以 =、+、-、@、Tab 或 CR 開頭的 CSV/XLSX 儲存格前綴加上 '(防止公式注入)。
  • 速率限制: 針對登入、密碼重設、MFA 驗證、API 金鑰、匯出、上傳和昂貴的端點。
  • 回應: 已驗證的 API 回應設定 Cache-Control: no-store。使用包含 request_id 的通用錯誤訊息;堆疊追蹤僅記錄在日誌中。在正式環境中,OpenAPI UI 應停用或僅限管理員使用。

5. 授權

  • 預設拒絕: 每個路由宣告其所需的權限;未宣告的路由會在啟動或測試時失敗。
  • RBAC:角色對應至權限(而非直接在程式碼中檢查角色)。
  • 物件層級檢查 (IDOR/BOLA): 在儲存庫層級對每個依 ID 進行的讀取/寫入進行所有權或租戶檢查。對現有物件的未授權存取回傳 404。
  • 功能層級檢查: 管理員路由位於 /api/v1/admin/* 下,由單一依賴項保護,絕不單純隱藏 UI。
  • 敏感操作(角色變更、金鑰建立、匯出、刪除使用者)需要近期重新驗證;可選用雙人核准流程來將角色提升至管理員。

6. 檔案上傳(若有的話)

  • 在代理和應用程式層級設定大小限制;允許的副檔名清單 和 Magic Byte 檢查。
  • 儲存在 Web 根目錄之外(或物件儲存),使用隨機檔案名稱,以 Content-Disposition: attachment 和 X-Content-Type-Options: nosniff 提供服務。
  • 圖片重新編碼(去除 EXIF 和多重語言檔案);壓縮檔檢查是否有壓縮炸彈和路徑遍歷;可選用離線防毒軟體(ClamAV)。
  • 拒絕 SVG 和 HTML 上傳,除非經過清理並從分離的來源提供服務。

7. 日誌、稽核與管理

  • 結構化日誌: JSON 格式,層級為 DEBUG/INFO/WARN/ERROR/CRITICAL,所有地方都包含 request_id,UTC 時間戳記,使用者值中去掉 CR/LF。從不記錄密碼、Token、金鑰、會話 ID。
  • 遠端 syslog: 透過 TLS 的 RFC 5424(RFC 5425),帶有有界本地緩衝區;主機、連接埠、TLS、CA 可從管理員 UI 設定。無需 rsyslog 容器。
  • 錯誤通知: 可從管理員 UI 設定 SMTPS 和 Webhook,經過 SSRF 驗證,包含「傳送測試」按鈕,並有速率限制。
  • PII 遮罩: 可從管理員 UI 切換的中介軟體。
  • 防篡改稽核軌跡: 僅附加的資料表(執行時期角色僅具備 INSERT/SELECT 權限),每一列與前一列的雜湊值鏈接,並轉發至 syslog。涵蓋:登入、失敗、MFA 變更、角色變更、設定變更、匯出、API 金鑰、蜜令命中;記錄使用者、IP、使用者代理、UTC 時間以及變更前/後的值。
  • 管理員儀表板: 使用統計、錯誤、蜜令警報、被封鎖的 IP。
  • 定期清理: 停用非活躍帳戶、清除過期的 Token/會話/等冪性金鑰、每日加密備份(金鑰與備份分開儲存)、保留政策以及經過測試的還原程序(make restore-test)。
  • 個人資料 (GDPR): 每種資料類型的保留期限、使用者資料匯出和刪除、清理工作。

8. 驗證、身分識別與主動防禦

  • 密碼: Argon2id(argon2-cffi 預設值 / RFC 9106,最低 m=19 MiB,t=2,p=1),當參數變更時在登入時重新雜湊。密碼政策遵循 NIST SP 800-63B:≥ 12 個字元,最大 ≥ 64 個字元,無組成規則,若在內建的已洩漏/常見密碼清單中則拒絕。
  • 登入: 對於未知使用者,回應和時間點相同,漸進式延遲 + 每個帳戶和每個 IP 的節流(避免硬鎖定導致 DoS)。
  • 密碼重設: 一次性隨機 Token,儲存時已雜湊,30 分鐘有效期,無論帳戶是否存在,回應相同,重設後撤銷所有會話。
  • 會話: 伺服器端,Cookie 名稱為 __Host-session(HttpOnly; Secure; SameSite=Lax; Path=/),ID 在登入和權限變更時輪換,使用者可以列出和撤銷其活躍會話。瀏覽器儲存中不使用 JWT;若 JWT 用於服務間通訊:演算法固定、拒絕 none、檢查 aud/iss/exp、短生命週期。
  • 管理員會話: 閒置 1 小時,絕對時間 8 小時,破壞性操作需要重新驗證。
  • MFA: TOTP(已雜湊的恢復碼,拒絕重放相同代碼)和 WebAuthn/Passkeys。管理員帳戶強制啟用 MFA。
  • 情境偵測: 來自未知 IP/裝置的管理員登入會觸發「新的登入」通知,並限制破壞性權限,直到透過 MFA 確認。
  • 引導管理員: 首次啟動時產生隨機密碼,可透過 make admin-password 讀取一次,首次登入時強制重設密碼並註冊 MFA。
  • 緊急帳戶(可選): 當 SSO 中斷時可使用的本機管理員,預設停用,每次使用都會觸發嚴重警報。
  • SSO: OIDC 授權碼流程 + PKCE,驗證 state 和 nonce,檢查 ID Token 的簽章/aud/iss;LDAPS 或 StartTLS 搭配憑證驗證,LDAP 過濾器值經過跳脫(防止 LDAP 注入)。目錄群組對應至角色。
  • SSO 設定,兩個等效來源: 每個 OIDC 和 LDAP(S) 設定(啟用旗標、Issuer/伺服器 URL、Client ID、Scope、Bind DN、Base DN、使用者/群組過濾器、CA 套件、群組到角色對應、自動佈建)可以從管理員 UI 或從環境變數(BACKEND_OIDC_*、BACKEND_LDAP_*)設定。
    • 密碼 (client_secret、Bind Password) 來自 *_FILE 變數或密碼提供者,絕不來自正式環境中的純文字環境變數;在 UI 中它們是唯寫的(••••後4碼)。
    • 優先順序:由環境變數定義的設定優先,並在管理員 UI 中以唯讀方式顯示,附帶「由環境管理」徽章;其他所有設定皆可編輯並以加密形式儲存在資料庫中。
    • 兩個來源使用相同的驗證邏輯(由環境變數載入器和管理員 API 共用的 Pydantic Schema);無效的環境變數設定會導致啟動失敗並顯示清晰的錯誤訊息,無效的 UI 輸入會在儲存前被拒絕。
    • 管理員 UI 具有「測試連線」功能(OIDC 發現 + JWKS 獲取,LDAP Bind + 樣本群組搜尋),且每次變更都會被稽核。
    • 每個來源的設定變更都會被記錄在稽核軌跡中,並觸發即時通知。
    • 自動佈建的使用者會獲得一個預設角色(可設定),並在每次登入時同步其群組成員資格。

9. 部署

  • Docker Compose / Podman Compose: 如前所述,所有服務已定義並強化。
  • 生產環境建置: 可透過 make build-production 命令產生一個僅包含必要服務的最小化 Docker Compose 檔案(僅 app、db、cache),並使用 docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d 啟動。
  • 映像檔簽章驗證: 生產環境部署腳本應在啟動任何容器之前,驗證所有使用映像檔的 Cosign 簽章。
  • 資料庫備份: 每日加密備份,使用 pg_dump 並透過 GPG 加密,儲存在獨立於應用程式伺服器的位置。
  • 上線前檢查清單: 產生 docs/operations/go-live-checklist.md,包含以下項目:
    • 所有環境變數已設定且安全
    • 密碼已從預設值變更
    • TLS 憑證已安裝且有效
    • 防火牆規則已套用
    • 入侵偵測系統 (IDS) 已啟用
    • 備份已設定並測試
    • 監控和警報已設定
    • 事件應變計畫已記錄
    • 安全聯絡人已指定

10. MCP 端點

  • 若使用者要求 MCP 端點,則產生一個遵循 MCP 規範的伺服器端點,位於 /api/v1/mcp/*。
  • MCP 端點應使用與其他 API 相同的驗證和授權機制。
  • 應為 MCP 端點啟用速率限制和審計日誌記錄。

11. 清理程序

  • 上線前清理: 產生一個 make pre-launch-cleanup 命令,執行以下操作:
    • 移除所有開發用的 .env 檔案(如果存在)
    • 移除開發用的啟動腳本(make dev 等)
    • 確保所有環境變數都已從生產環境設定檔中正確設定
    • 驗證所有密碼都已從預設值變更
    • 執行完整的掃描套件 (make scan)
    • 執行 DAST 掃描(如果已配置)
    • 產生最終的 SBOM (make sbom)
    • 驗證所有映像檔都已簽署
    • 標記發行版本
  • 此程序應在部署至生產環境前執行。

12. 文件

  • 產生 docs/security/README.md,總結所有安全措施和設定。
  • 產生 docs/operations/README.md,包含日常操作程序。
  • 產生 docs/development/README.md,包含開發設定指南。
  • 所有文件應使用英文撰寫。

13. 測試

  • 產生涵蓋以下項目的測試:
    • 所有 API 端點的單元測試
    • 關鍵流程的整合測試(登入、註冊、密碼重設)
    • 授權規則的測試(角色權限、物件層級檢查)
    • 檔案上傳的安全性測試
    • 速率限制測試
    • SQL 注入和 XSS 的滲透測試
  • 測試應使用 pytest(Python)和 vitest(TypeScript)執行。

14. 常見問題與疑難排解

  • 若 docker compose up 失敗,請檢查 Docker 版本是否為 v2 或更高版本。
  • 若連接埠已被佔用,請修改 docker-compose.yml 中的連接埠對應。
  • 若認證失敗,請執行 make admin-password 來取得管理員密碼。
  • 若遇到 SSL 錯誤,請確保 CA 憑證已正確設定。

參考資料

相關技能