「不用記帳」all-set-tw:自架 Cloudflare 的台灣自動記帳工具,高敏感憑證試用前安全核實 | Allen 知識庫 | Allen 知識庫安全評估threads
「不用記帳」all-set-tw:自架 Cloudflare 的台灣自動記帳工具,高敏感憑證試用前安全核實
2026年9月22日11 分鐘閱讀👁 7
結論先講
「不用記帳」TedLin1993/all-set-tw 是一個開源、可自部署的台灣個人財務整合工具。官方 README 與程式碼可核實:它支援電子發票、集保 e 存摺,以及 9 家台灣銀行,後端跑在 Cloudflare Workers,使用 D1、Queues、Workers AI、Browser Rendering 與 Cron Triggers;專案授權為 MIT。
但這類工具的風險等級非常高,因為它會保存銀行/集保/電子發票登入憑證或 session token。程式碼確實有把 connector 設定以 AES-GCM 加密後存入 D1,符合作者留言「加密後存在 Cloudflare D1」的大方向;但這不等於「低風險」。安全性主要取決於 Cloudflare 帳號、Worker Secret CONFIG_ENCRYPTION_KEY、D1 存取權、log、依賴供應鏈,以及銀行端是否容許這種自動化登入。
Allen 若要測試,我建議可以測,但只適合用 sandbox 方式:獨立 Cloudflare 帳號/獨立 fork/獨立 D1/最低敏感度帳號,先不要放主要薪轉、主要信用卡、證券核心帳密。
可由官方 repo 核實的事
1. 支援清單:9 家銀行 + 集保 + 電子發票
README 的「支援資料來源」列出:
- 電子發票載具
- 集保 e 存摺
- 玉山銀行
- 國泰世華銀行
- 永豐行動銀行
- 台新銀行
- 中國信託銀行
- 新光銀行
- 華南銀行
- 王道銀行
- 第一銀行
程式碼 supportedConnectorIds / connectorCatalog 也對應 11 個 connector:einvoice, tdcc, esun, cathaybk, , , , , , , 。其中銀行剛好是 9 家,Threads 主張「支援 9 家台灣銀行、集保、電子發票」可由 repo 核實。
sinopac
taishin
ctbc
skbank
obank
hncb
firstbank
2. 功能範圍:帳戶、信用卡、投資、發票集中查看
README 宣稱本專案是「自動同步銀行、信用卡、投資與電子發票的自架個人財務整合工具」。connector catalog 的 capabilities 也包含:
- 電子發票與品項明細
- 銀行帳戶
- 餘額快照
- 銀行交易
- 信用卡帳單
- 投資持倉
- 投資交易
- net worth history
因此「集中帳戶餘額、信用卡消費、投資與發票」可由 README 與 code 大致核實。
3. 架構:Cloudflare Workers / D1 / Queues / Workers AI / Browser Rendering
README 與後端架構文件都寫明:後端執行於 Cloudflare Workers,以 Hono 提供 API,並整合 D1、Access、Browser Run / Browser Rendering、Workers AI、Cron Triggers 與 Queues。
main = "apps/worker/src/index.ts"
- D1 binding:
DB
- Browser binding:
BROWSER
- AI binding:
AI
- Queue:
taiwan-fin-hub-sync
- Cron:
*/10 * * * *
- observability logs enabled
apps/worker/src/index.ts 也顯示 Worker export 同時處理:
也就是:HTTP API、Cron 觸發、Queue consumer 都在同一個 Worker 架構內。
4. 定時同步
wrangler.toml 設定 Cron 每 10 分鐘觸發一次;後端文件說 Cron 只負責把排程同步訊息送進 Queue,是否真正執行由 D1 裡的 sync job 狀態判斷。Queue consumer 每次最多處理一個 connector,並用 20 秒延遲串接下一個,避免連續啟動 Browser session 撞到 Browser Run 限制。
這支持 Threads 主張「定時自動同步」,但不是每 10 分鐘無條件同步所有來源;實際同步頻率還會受使用者設定、D1 sync job 狀態、Browser Run 額度與外部銀行狀態影響。
5. 開源授權
GitHub API 與 LICENSE 都顯示授權為 MIT。LICENSE 內含:
- Copyright (c) 2026 Kuan-Yin Chen
- Copyright (c) 2026 Zih-Jian Lin
README 也標示本專案以 kevchentw/taiwan-fin-hub 為基礎發展而來。
作者自述/社群主張,但需分層看待
1. Threads 貼文主張
透過 Threads 頁面 meta description 可抓到原貼文核心文字:
目前支援 9 家台灣銀行,加上集保和電子發票,可以把帳戶餘額、信用卡消費、投資和發票集中在一起看,也能定時自動同步。
專案一樣是開源的,可以部署在自己的 Cloudflare 帳號,一般使用免費方案就夠用了。
這些主張大多可由 README / repo 架構核實,但「免費方案就夠用」有條件:README 自己也說免費額度不是無限,超過限制時功能可能暫停至額度重置。
2. 作者留言:「帳密加密後存在 Cloudflare D1」
這點我沒有透過公開 HTML 成功重新抓到留言串,但任務上下文提供的留言內容是:使用者問「帳號密碼輸入一次後存在 Cloudflare?」作者答「對,加密後存在 Cloudflare D1」。
程式碼核實結果:方向成立。connector_settings.encrypted_config 存在 D1;apps/worker/src/platform/crypto.ts 使用 AES-GCM 加密 JSON;apps/worker/src/features/connectors/service.ts 在儲存 connector 設定時呼叫 encryptJson(encryptedConfig, encryptionKey),而 encryptionKey 來自 Worker Secret CONFIG_ENCRYPTION_KEY。
- D1 存的是密文,不是明文。
- 金鑰存在 Cloudflare Worker Secret。
- 如果攻擊者同時取得 D1 與 Worker Secret,仍可解密。
- 目前 README 明確寫「不支援金鑰輪替」。
- 這是「加密靜態儲存」,不是「憑證永遠不會被 Worker 或 Cloudflare 執行環境處理」。
高階安全審查
1. 銀行帳密 / token 加密方式
CONFIG_ENCRYPTION_KEY 經 SHA-256 digest 後匯入為 AES-GCM key。
- 每次加密使用
crypto.getRandomValues(new Uint8Array(12)) 產生 12-byte IV。
- 密文格式包含
{ v: 1, alg: "AES-GCM", iv, ciphertext }。
decryptJson 會檢查版本與演算法,再用同一把 key 解密。
- AES-GCM + 隨機 IV 是合理的靜態加密方式。
- 但 key derivation 只是
SHA-256(secret),沒有 HKDF / PBKDF / salt / context separation。
- 所有 connector 共用同一個
CONFIG_ENCRYPTION_KEY。
- 沒有看到 key rotation 機制;README 也明講目前不支援金鑰輪替。
- 沒有使用 Cloudflare KMS 類型的外部 key management;實際是 Worker Secret + WebCrypto。
風險等級:中高。對個人 self-host 來說可接受作為第一版,但對銀行憑證屬於「高敏感資料」,建議至少補 key rotation / per-connector key wrapping / 明確備份與銷毀流程後,再放主要帳戶。
2. 金鑰來源與保存
部署後由 Cloudflare 保存為 CONFIG_ENCRYPTION_KEY。README 也提醒:如果日後重建 Worker、搬移環境或沿用既有 D1,必須使用相同金鑰,否則需要重新設定所有 connector。
- 這代表「遺失金鑰」會造成既有 D1 憑證不可解密。
- 「洩漏金鑰 + 洩漏 D1」則可解密全部 connector 設定。
- 建議 Allen 測試時把金鑰放密碼管理器,不要放 GitHub Secrets 以外的 repo 檔案,不要截圖留存。
3. D1 權限與備份
- D1 binding 名稱為
DB。
connector_settings 表有 encrypted_config。
- D1 migration 管理 schema。
- 部署文件有「既有 D1」與 migration 指令。
- README / docs 沒有看到完整 D1 備份、restore、定期 export、密文備份驗證 SOP。
- Cloudflare 帳號管理員、Workers Builds token、wrangler token、CI 權限若過大,都可能接觸 D1 或部署設定。
- D1 內不只憑證密文,也有金融交易、餘額、發票、持倉等敏感資料;這些業務資料看起來是明文儲存,不是逐欄加密。
- 沒看到應用層備份加密或資料保留/刪除政策。
建議:測試前先定義「如何刪 D1、如何撤銷 token、如何確認備份不存在或已刪除」。
4. 憑證是否會送第三方
- 銀行/集保/電子發票登入資料會由 Worker connector 送往各官方或實際服務端點。
- 需要瀏覽器的銀行 connector 會使用 Cloudflare Browser Rendering / Puppeteer;也就是登入流程在 Cloudflare 瀏覽器環境中執行。
- 驗證碼辨識會把 CAPTCHA 圖片送到 Cloudflare Workers AI,模型為
@cf/google/gemma-4-26b-a4b-it。
- 中國信託 local dev 有 loopback Node relay,但註解寫正式 Worker 不使用該 relay。
- 把銀行帳密送到作者伺服器。
- 把金融資料送到非 Cloudflare 的第三方分析服務。
- 外部 SaaS telemetry SDK。
但要注意:Cloudflare 本身是執行平台與資料處理方。若 Allen 的威脅模型是「不能讓任何第三方基礎設施處理銀行登入資料」,那這個專案不符合。
5. Log / 錯誤是否可能洩漏
- 架構文件明確要求未知錯誤不要回傳 stack trace、SQL 或敏感 connector response。
sanitizeDatabaseError 會把 Drizzle query error 轉成 generic Database query failed.。
- scheduler 的 structured log 主要記錄 connector、scope、status、duration、records,不記錄交易明細。
safeErrorLogDetails 對 stack / cause stack 做 URL、token、cookie、password 等模式的 redaction。
safeErrorMessage 只做 whitespace normalization + 300 字截斷,沒有同樣套用 token/password redaction;而多個 route 會把 safeErrorMessage(error) 回傳給前端或寫入 sync job failure。
- scheduler 失敗 log 會包含
message = safeErrorMessage(error);如果某個 connector error message 本身含敏感 response,就有外洩風險。
- OCR service 在 Workers AI 錯誤時
console.warn/error(..., error),若 Cloudflare AI error 物件含 request 內容,理論上可能把 CAPTCHA 圖片或 metadata 帶入 log;是否實際如此未確認。
wrangler.toml 啟用 observability logs 與 invocation logs。這對 debug 有利,但對金融憑證工具要特別小心。
建議:把 safeErrorMessage 也套用與 sanitizeErrorDiagnostic 同級的 redaction;connector error 應以固定錯誤碼為主,不把原始銀行錯誤文字直接持久化。
6. Session / Auth / CSRF
- API 全域套
accessMiddleware。
- Worker 驗證 Cloudflare Access JWT 的 RS256 簽章、issuer、audience、exp、nbf。
- JWT 可從
Cf-Access-Jwt-Assertion header 或 CF_Authorization cookie 讀取。
- Demo mode 可略過 Access,但 demoReadOnlyMiddleware 只允許 GET / HEAD / OPTIONS。
- Local dev mode 只允許 localhost / 127.0.0.1 / ::1 略過 Access。
- 沒看到 app 自己的 CSRF token 或 Origin / Referer 檢查。
- 若部署後使用 Cloudflare Access cookie 作為瀏覽器登入狀態,所有 state-changing API 都依賴 Cloudflare Access 的 cookie 行為與 same-site 保護;app 本身沒有額外 CSRF 防線。
- 沒看到 CSP、X-Frame-Options、HSTS 等應用層安全 header 設定;可能部分由 Cloudflare / Access / browser default 承擔,但 repo 未明確。
- 若使用者忘記把 Worker URL 改成 Restricted,API middleware 仍會要求 Access JWT;但靜態前端會公開顯示。README 有要求部署後啟用 Restricted,這步不可省略。
建議:正式放真實憑證前,補 Origin allowlist 或 CSRF token;並在 Worker 回應加 CSP / frame-ancestors / nosniff 等 headers。
7. 依賴供應鏈
我沒有安裝或執行程式;只在已存在的 package-lock.json 上跑 npm audit --package-lock-only。結果:
- total vulnerabilities: 17
- high: 8
- moderate: 9
- critical: 0
@cloudflare/puppeteer via @puppeteer/browsers / extract-zip
wrangler via miniflare / sharp
nanoid
ip-address
hono
vitest
devalue
drizzle-kit / esbuild
- 有些是 dev tooling 或本機測試工具,不一定進入 production bundle。
- 但
hono 是 Worker runtime dependency,@cloudflare/puppeteer 也和 Browser connector 相關,不能完全忽略。
- 對高敏感財務憑證工具,建議先更新依賴並跑 CI / connector selfcheck,再測真實帳號。
8. Cloudflare 免費額度聲明是否有條件
README 自己已經寫清楚:Workers、D1、Queues、Workers AI、Browser Run 均有免費額度,但不是無限;超過限制時功能可能暫停到額度重置。
- Browser Run Free:10 minutes/day,Browser Sessions concurrent browsers 3。
- D1 Free:5 million rows read/day、100,000 rows written/day、5 GB total storage。
- Workers AI Free:10,000 Neurons/day。
- Queues Free:10,000 operations/day,message retention 24 hours。
因此「一般個人低頻使用可從免費方案開始」合理;但「通常夠」取決於:
- 開幾個 browser connector。
- 同步頻率。
- 發票品項明細數量。
- 是否常遇到 retry / CAPTCHA / bank site failure。
- D1 查詢是否有掃描大量 rows。
- Workers AI CAPTCHA 辨識使用量。
尚未確認或需要更深審查的點
- 沒有逐一驗證每個銀行 connector 目前仍可登入與同步;銀行頁面 / API 改版會使 connector 失效。
- 沒有部署,也沒有接觸任何真實帳密,因此無法驗證 Cloudflare dashboard 設定實際是否與文件一致。
- 沒有完成逐檔資料外送審計;目前只看到主要架構沒有送作者伺服器,但仍應做完整 outbound endpoint inventory。
- 沒有驗證 D1 備份、Time Travel、刪除、export 的實際操作流程。
- 沒有驗證 Cloudflare Access cookie 的 SameSite / CSRF 實際防護效果。
- Threads 留言「加密後存在 D1」由任務上下文提供,公開 HTML 未抓到該留言;但程式碼已核實此說法的大方向成立。
Allen 是否值得測試?
值得測,但只建議當作「高敏感 self-host 財務 connector PoC」測,不建議一開始就接主要銀行帳戶。
- 架構完整,並非只有 README demo。
- 支援清單與 connector catalog 對得上。
- 有 Cloudflare Access、D1 migration、Queue scheduler、加密儲存、測試檔與 selfcheck。
- MIT 授權,適合 fork 後自行審查與改造。
- 對 Allen 的 LifeOps / personal finance dashboard 有參考價值。
- 憑證與 session token 仍會由 Cloudflare Worker / Browser / AI 平台處理。
- 無 key rotation。
- D1 裡的金融資料多半是明文。
- app 自身未見 CSRF token / Origin 檢查。
safeErrorMessage redaction 不夠強。
- npm audit 有高風險與中風險依賴。
- 銀行自動化登入可能違反銀行服務條款或觸發風控。
- README 免責聲明也明確說未與集保、財政部、金管會、銀行或金融機構合作或授權。
安全 sandbox 試用步驟
-
先 fork,不要直接用主帳號 deploy upstream
- 建立 Allen 自己的 private fork 或測試 repo。
- pin 一個已審查 commit,例如本次檢出的 commit:
5d1a0f6787e9665590dfd2797be4f0659fb19c98。
- 暫時不要啟用自動 upstream sync,避免未審查的新程式自動上線。
-
用獨立 Cloudflare 帳號或至少獨立 project
- 不要和正式 BigIntTech / Allen KB / 其他 production Workers 混在同一組高權限 token。
- Cloudflare Access 只允許 Allen 自己的信箱或 Cloudflare account member。
- Session duration 先設短一點,不要一開始就拉到一個月。
-
產生並保存獨立 CONFIG_ENCRYPTION_KEY
- 用
openssl rand -hex 32 產生。
- 存到密碼管理器。
- 不要 commit 到 repo、不要貼到聊天、不要截圖。
- 若要刪除測試環境,要同時刪 Worker Secret、D1、Queues、GitHub Actions secrets。
-
先不接銀行帳密
- 先用 demo / manual assets / 只看 UI 與部署狀態。
- 檢查 Access 是否真的擋住未登入訪問。
- 用瀏覽器無痕視窗測
/api/... 是否會被拒絕。
-
若一定要測真實 connector,先選低風險帳戶
- 不要用主要薪轉戶、主要信用卡、主力證券戶。
- 選餘額低、權限低、可快速改密碼或停用的帳戶。
- 測完立即改密碼或撤銷裝置 / session。
- 不要同時開多家銀行;一次只測一個 connector。
-
測試前先關注 log
- Cloudflare Logs / Observability 開啟時,只看必要欄位。
- 故意輸入錯誤密碼時,檢查 log 與前端錯誤是否有洩漏帳號、token、cookie。
- 若看到銀行 response 原文或 session 值,立即停止測試。
-
補上最低限度 hardening 後再擴大
- 更新有漏洞的依賴。
- 對 state-changing API 補 Origin / CSRF 防護。
- 對
safeErrorMessage 套用 redaction。
- 關閉不必要的 invocation logs 或降低 log detail。
- 建立 D1 export / delete / restore SOP。
- 記錄 outbound endpoints,確認沒有非預期第三方。
-
測完要有銷毀流程
- 刪除 Cloudflare Worker、D1、Queue、Access app。
- 刪除 GitHub deploy repo 或 secrets。
- 改掉所有測過的銀行/集保/電子發票密碼。
- 在銀行端撤銷已登入裝置或 trusted device。
一句話判斷
all-set-tw 是值得追蹤與 sandbox 測試的台灣個人財務自架專案;官方 repo 確實支援 9 家銀行、集保與電子發票,也確實把 connector 設定加密後存 D1。但因它處理的是銀行帳密與 session token,目前更適合「隔離環境審查與低風險試用」,不建議 Allen 直接把主要金融帳戶接上去長期自動同步。