Day 18,我們建立了 architecture.json。
Agent 現在知道 Demo 是一個 Firebase Web App,也知道 Browser 會直接存取 Firestore。
下一個問題是:Agent 應該檢查什麼?
最直覺的方法,是把一大段 Checklist 放進 Prompt:
請檢查:
- 是否有 Broken Access Control
- 是否洩漏個資
- 是否缺少 Timeout
- 是否缺少 Health Check
- 是否暴露 API Key
這種 Prompt 看起來涵蓋很多問題,實際執行時卻會產生三種噪音:
今天要把前 7 至 15 天累積的資安、隱私與 SRE 知識,轉成 Agent 可以選擇、執行與追蹤版本的規則。
每條規則不只描述「最佳實務」,還要定義:
Checklist 通常是一個問題:
系統是否有適當的存取控制?
這句話適合提醒人類,卻不足以驅動 Agent。
Agent 還需要知道:
「適當」是什麼?
哪些元件適用?
要讀哪些證據?
看到什麼才算失敗?
靜態證據能否直接確認漏洞?
因此,Vibe Guard 的規則至少包含以下欄位:
{
"id": "SEC-AUTHZ-001",
"version": "1.0.0",
"domain": "security",
"title": "User-owned records enforce ownership on every operation",
"source": "OWASP ASVS access control",
"appliesWhen": "browser_direct_firestore",
"requiredEvidence": [
"firestore.rules",
"project ownership field",
"read and write query path"
],
"evaluator": "firestore_owner_check",
"failureVerdict": "candidate"
}
title 說明期待的安全狀態。
appliesWhen 決定這條規則是否適合目前架構。
requiredEvidence 告訴 Agent,做出判斷前要收集哪些資料。
evaluator 對應實際檢查邏輯。
failureVerdict 則限制規則失敗時可以使用的最高結論。
這裡刻意設定為 candidate,而不是 confirmed。
只看到過寬的 Firestore Rules,可以建立越權假設;要成為 Confirmed Finding,仍要通過 Day 17 的攻擊路徑、邊界跨越、重現與影響門檻。
如果規則只有自然語言名稱:
檢查存取控制
幾個月後修改內容,很難回答:
因此每條規則使用不隨標題改變的 ID:
SEC-AUTHZ-001
PRIV-MIN-001
REL-TIMEOUT-001
SEC-SECRET-001
SRE-HEALTH-001
Domain 前綴讓結果可以依資安、隱私與可靠性分流。
版本則採用:
1.0.0
如果只修正文案,可以增加 Patch。
如果新增證據欄位或改變判斷結果,可以增加 Minor。
如果規則語意已不相容,就增加 Major。
報告未來應同時保存:
{
"ruleId": "SEC-AUTHZ-001",
"ruleVersion": "1.0.0"
}
這樣評估資料集才能重播相同條件。
Day 18 的 Recon 已經輸出:
{
"from": "Browser",
"to": "Cloud Firestore emulator",
"data": "Project records and authenticated identity"
}
Rule Engine 可以使用這項架構事實判斷:
case "browser_direct_firestore":
return boundaries.some(
(boundary) =>
boundary.from === "Browser" &&
boundary.to.includes("Cloud Firestore")
);
只有 Browser 直接存取 Firestore 時,SEC-AUTHZ-001 才進入評估。
另一條規則要求長駐 Server 提供 Liveness 與 Readiness:
{
"id": "SRE-HEALTH-001",
"appliesWhen": "long_running_server",
"evaluator": "health_endpoints"
}
目前 Demo 的架構類型是:
Local-only Firebase web application
它沒有 Repository 內的長駐 Application Server。
所以結果應該是:
SRE-HEALTH-001 NOT_APPLICABLE
而不是:
Critical: Application has no /health endpoint.
Not Applicable 不是忽略風險,而是證明 Agent 有先理解架構。
今天加入五條示範規則:
| Rule | Domain | 需要回答的問題 |
|---|---|---|
SEC-AUTHZ-001 |
Security | 使用者擁有的資料是否在每個操作檢查 Owner? |
PRIV-MIN-001 |
Privacy | 儲存與顯示的個資是否為功能必要? |
REL-TIMEOUT-001 |
Reliability | 外部呼叫是否有明確 Deadline? |
SEC-SECRET-001 |
Security | Client 中的 Key 是否具備特權? |
SRE-HEALTH-001 |
Reliability | 長駐 Server 是否有健康檢查? |
這五條規則不能共用同一種證據。
授權規則需要:
Security Rules
資料所有權欄位
實際讀寫路徑
兩個帳號的動態測試
個資最小化需要:
收集與保存的欄位
誰能讀取
畫面是否顯示
產品需求與保存目的
Timeout 規則需要:
外部呼叫位置
SDK 預設行為
Application Deadline
Retry 與上游 Timeout
如果沒有產品需求,Agent 可以指出 ownerEmail 被保存及顯示,卻不能自行斷言這個欄位一定沒有合法用途。
因此它先輸出 Candidate,並要求補充功能需求與可讀取範圍。
Demo 的 Firebase Client Configuration 包含:
apiKey: "demo-api-key"
只做字串掃描的工具可能立即回報:
High: API Key committed to source code.
但這個值用於本機 Firebase Emulator,而且程式會拒絕在非 Localhost 執行。
它不是 GEMINI_API_KEY,也沒有證據顯示能呼叫具特權的正式環境服務。
規則的判斷邏輯會同時檢查用途與執行環境:
const localOnly = mainSource.includes(
"This intentionally vulnerable demo can only run locally."
);
const emulatorKey = mainSource.includes('apiKey: "demo-api-key"');
return localOnly && emulatorKey
? {
verdict: "pass",
evidence:
"The value identifies a localhost-only Firebase Emulator project and is not a Gemini credential."
}
: {
verdict: "requires_evidence",
nextStep: "Inspect enabled APIs and key restrictions."
};
這裡的重點不是用字串比對證明所有 Key 都安全。
重點是規則不能只因變數名稱包含 apiKey,就跳過金鑰用途、權限與限制條件。
Reviewer 會呼叫 Gemini:
ai.interactions.create(...)
目前 Application Code 沒有設定明確 Deadline。
Rule Engine 可以確認:
The Gemini call site has no explicit deadline in application code.
但它還不知道:
所以這條規則輸出:
REL-TIMEOUT-001 REQUIRES_EVIDENCE
並要求:
Check SDK defaults and define the end-to-end review deadline.
這個分類可以避免把「缺少可見設定」直接寫成「服務會永遠卡住」。
Google SRE 的 Production Service Practices 建議每個 RPC Client 使用帶 Jitter 的 Exponential Backoff,也強調服務應在過載時合理降級。
不過,SRE 原則仍要轉成符合系統邊界的測試,不能只把原文貼進 Prompt。
專案加入:
demo-app/
├── rule-engine-demo/
│ ├── rules.json
│ └── scenario.js
└── recon-demo/
└── architecture.json
先執行:
cd /media/mickey/777/ithome/demo-app
npm run rules:demo
這個指令會先重新產生 Day 18 的 architecture.json,再載入規則:
{
"scripts": {
"rules:demo": "npm run recon:demo >/dev/null && node rule-engine-demo/scenario.js"
}
}
執行結果如下:
RULE CATALOG
SEC-AUTHZ-001 v1.0.0 domain=security applies_when=browser_direct_firestore
PRIV-MIN-001 v1.0.0 domain=privacy applies_when=stores_user_records
REL-TIMEOUT-001 v1.0.0 domain=reliability applies_when=calls_external_model_api
SEC-SECRET-001 v1.0.0 domain=security applies_when=client_has_api_key_field
SRE-HEALTH-001 v1.0.0 domain=reliability applies_when=long_running_server
EVALUATION
SEC-AUTHZ-001 CANDIDATE
firestore.rules allows every authenticated identity to read and write projects.
next: Run the two-account authorization scenario to confirm cross-account impact.
PRIV-MIN-001 CANDIDATE
The project document stores ownerEmail and the project list renders it.
next: Confirm the feature requirement and identify which users can read project documents.
REL-TIMEOUT-001 REQUIRES_EVIDENCE
The Gemini call site has no explicit deadline in application code.
next: Check SDK defaults and define the end-to-end review deadline before confirming a reliability gap.
SEC-SECRET-001 PASS
The value identifies a localhost-only Firebase Emulator project and is not a Gemini credential.
SRE-HEALTH-001 NOT_APPLICABLE
Applicability condition 'long_running_server' is false.
SUMMARY
pass: 1
candidate: 2
requires_evidence: 1
not_applicable: 1
今天的 Demo 使用 Deterministic JavaScript,沒有讓 Gemini 自由決定最後 Verdict。
這是刻意的設計。
比較安全的分工是:
Recon
建立架構、資料流與信任邊界
Rule Selector
根據 appliesWhen 選擇規則
Deterministic Tools
搜尋程式碼、讀取設定、執行測試
Gemini
解釋跨檔案語意、提出攻擊假設、整理缺少的證據
Validator
檢查引用、重現結果與 Verdict 上限
Gemini Function Calling 可以讓模型選擇外部工具,並產生符合 Function Schema 的參數。
未來可以提供:
read_file
search_code
run_authorization_test
inspect_dependency
request_project_evidence
但模型提出 Function Call,不代表工具可以直接獲得所有權限。
Host Application 仍要負責:
規則定義「為什麼查」,工具提供「如何查」,Validator 決定「證據支持到哪一層結論」。
第一版 rules.json 仍然很小。
正式規則庫至少還需要:
requires_evidence 比例。OWASP ASVS 提供可測試的 Web Application Security Requirements,也建議引用時帶上版本與 Requirement Identifier。
這類標準適合作為規則來源,卻不應不經轉換就成為 Finding。
一項 Requirement 還要結合應用架構、實作證據與可重現測試,才能變成 Agent 的判斷。
把知識交給 Agent,不是把更多文件塞進 Context Window。
一條可執行規則至少要回答:
今天的 Rule Engine 根據 Recon 結果選擇五條規則,最後產生:
1 Pass
2 Candidates
1 Requires Evidence
1 Not Applicable
這份結果比「發現四個問題」更有用。
它同時說明哪些控制已通過、哪些需要驗證、哪些缺少環境證據,以及哪些規則根本不適用。
明天,我們會建立 Security Hunter,讓 Gemini 根據適用規則與架構資料提出攻擊假設,再交給 Validator 篩掉無法重現的結論。