3lens/whitepaper

白皮書

第 1、4 節已對照 package.json 與作業規格文件;第 2、3、5 節的宣稱各自標示查證狀態與對應證據。

1. 它是什麼

Three-Lens(3lens)是 Antigravity CLI(agy)的外掛,提供有證據支撐的多階段安全保證與漏洞驗證。沒有任何外部依賴:package.json 的 dependencies 與 devDependencies 皆為空,hooks、skills、scripts 內也沒有非內建模組的 import。

2. 設計原則

預設不通過

所有權威性的結論(確認、排除、覆蓋完整性)預設不通過:候選的預設處置是 DEFERRED。零發現是正常結果,乾淨的結論只代表「在宣告的範圍內覆蓋完成」,不是普遍安全認證。實測發現的弱點見第 3 節。

三鏡合取

三個獨立視角:可達性(Reachability)、防禦(Defenses)、影響(Impact)。確認需要三個鏡頭全數支持且證據組完整;任一鏡頭附上通過驗證的反駁就會排除候選。多數決不能決定結論。

3. 威脅模型與防線

執行期有四層防線:Layer 1 終端機沙箱(agy --sandbox)、Layer 2 權限引擎、Layer 3 影子審查脈絡鉤子、Layer 4 路徑封閉與安全讀檔模組。以下每個宣稱獨立列出。

預設不通過

已查證

保護的資產
「確認」與「排除」兩種結論的可信度
防線
候選發現的預設處置是 DEFERRED(待人工審查)。要升到 REPORTABLE,必須三個鏡頭(可達性、防禦、影響)各一票全數支持、每票附通過結構檢查的證據、證據組同時含來源與落點、嚴謹度分數至少 0.60。票數不足、鏡頭不全、意見分歧,一律 DEFERRED。覆蓋、矩陣、發現、脈絡、執行、工具完整性、壓縮脈絡七道關卡任一未過,就不能宣告乾淨。
對應證據
  • 程式碼 deriveFinalDisposition (skills/3lens/scripts/finalize-scan.mjs)
  • 程式碼 validateVoteEvidence (skills/3lens/scripts/finalize-scan.mjs)
  • 測試 SEC-INV-02, SEC-INV-15 (skills/3lens/scripts/check-release-invariants.mjs)
殘餘風險
排除比確認寬鬆。任一鏡頭附上「存在的檔案、未超出檔尾的行號」就能排除候選,即使另外兩個鏡頭都支持。證據驗證只檢查結構,不檢查那一行是否真的支持論點:實測用 README.md 第 1 行當防禦證據,結果是 SUPPRESSED;引用不存在的檔案或超出檔尾的行號則會 DEFERRED。另外,README 稱預設為 UNVERIFIED,程式碼的預設處置其實是 DEFERRED,UNVERIFIED 是狀態或顯示用的標籤(例如「沒有觀察到委派」時的驗證狀態,ACP 適配器也拿它標示未確認的候選),不是處置。
不防範圍
「乾淨」只代表在宣告的範圍內覆蓋完成、沒有通過驗證的發現,不是沒有漏洞的證明。

機密代換

已查證

保護的資產
審查輸入中的憑證與金鑰
防線
準備審查脈絡時,用 6 類樣式(AWS 金鑰、GitHub 權杖、Bearer、PEM 私鑰區塊、鍵值型的密碼與金鑰、JWT)把機密換成保留行號的代號,行數不一致就整個檔案略過。只處理支援的副檔名與 .env*;以點開頭的檔案與資料夾(.env 除外)不進入脈絡,審查進行中鉤子也拒絕直接讀取未進入脈絡的路徑。使用者提示另有一個提示端守衛,用另一組 7 類樣式。
對應證據
  • 程式碼 SECRET_PATTERNS, tokenizeSecretsForContext (skills/3lens/scripts/finalize-scan.mjs)
  • 程式碼 prepare-review-context.mjs
  • 程式碼 SECRET_PATTERNS (hooks/pre-invocation-secret-guard.mjs)
  • 測試 tokenizeSecretsForContext check (skills/3lens/scripts/check-release-invariants.mjs)
殘餘風險
樣式比對只認得列舉的格式。我用 15 種合成樣本實測,脈絡代換只抓到 5 種:AWS 金鑰、GitHub ghp_ 權杖、JWT、PEM RSA 私鑰、16 字以上的純英數 password。漏掉 10 種:Slack 權杖、Google API 金鑰、含符號的密碼、短於 16 字的密碼、內嵌密碼的資料庫連線字串、client_secret、單獨的 token 鍵、Azure AccountKey、加密私鑰與 PGP 私鑰區塊。兩套樣式互不涵蓋:Slack 與 Google 金鑰只有提示端守衛認得,JWT 與 password 只有脈絡代換認得。
不防範圍
其他格式的機密不在保護範圍。使用者自己貼進提示的內容,只受提示端守衛那 7 類樣式的保護。

路徑封閉與符號連結

已查證

保護的資產
儲存庫以外的檔案(讀取與寫入)
防線
Layer 3 鉤子要求詞法與 realpath 檢查同時成立;Layer 4 讀檔時比對已開啟描述符與 realpath 目標的 dev/ino。
對應證據
  • 程式碼 isWriteTargetRealPathContained (hooks/shadow-context-guard.mjs)
  • 程式碼 safeReadFileContained (skills/3lens/scripts/path-containment.mjs)
  • 測試 tests/test-containment-gaps.mjs
殘餘風險
run_command 仍可建立符號連結;硬連結指向外部檔案兩層都不偵測;dev 或 ino 為 0 的檔案系統一律拒絕;只在 Windows 測過;競態視窗在實務上有多難贏,並未量測。
不防範圍
真正的隔離邊界是 Layer 1(agy --sandbox)。Layer 3 鉤子在沒有啟用中的審查脈絡,或遇到未處理的錯誤時會放行(fail-open)。

4. 作業模式

六種作業契約,各是 skills/3lens/jobs/ 下的一份規格文件,由協調代理(一個 LLM 代理)依規格執行;程式碼負責其中確定性的部分,例如目錄帳目、驗證、去重與定稿。

作業做什麼規格引用的腳本
scan掃描整個儲存庫或指定目錄;目錄帳目必須完整,零發現是有效結果。build-inventory.mjsfinalize-scan.mjs
review審查 PR、分支差異或工作樹差異,只看變更的檔案,做靜態的來源到落點分析,不執行利用。—
validate獨立驗證外部提供的候選發現,由三個鏡頭同時派工,不重新掃描整個儲存庫。—
deep多輪探索(預設 3 輪、至少 2 輪),候選以指紋去重後合併。finalize-scan.mjs
remediate在隔離的 scratch/patches/ 產生最小修補,不直接套用到工作副本;提出修補前先確認目標檔案沒有偏離被審查的 commit。—
verify-fix以回歸語意驗證修補:先做格式與路徑安全檢查、確認能乾淨套用(git apply --check)、偵測基準是否過期。validate-patch.mjs

各作業的硬性約束(例如 remediate 不得直接套用修補)寫在規格裡,本站尚未逐項確認是否有程式碼強制。

5. 基準測試

基準測試:量了什麼、沒量什麼

已查證

保護的資產
讀者對「100%」的理解
防線
README 把每項基準標上量測類型(MEASURED、RECORDED_SYNTHETIC、MODEL_OBSERVED)。我在本機重跑了四項確定性基準,數字與 README 一致:50 個案例 50/50(8 組)、20 對案例 20/20、穩定性 10 條譜系 10/10(合成與錄製兩種)。這些量的是判定邏輯與輸出流程有沒有照規則走,輸入是預先寫好的模擬候選,不是模型找漏洞的能力。
對應證據
  • 文件 README.md › Public Benchmark Claims Policy
  • 測試 npm run test:evals, test:semantic, test:stability, test:stability-recorded
  • 文件 release-evidence/cross-provider-replication-report-2026-09-23.md
殘餘風險
模型實際找漏洞的數字在 release-evidence 的報告裡(本站引述,沒有重跑):保留測試組的弱點樣本召回率 96.0%(24/25)與 96.7%(29/30),每種設定只跑 3 輪;乾淨樣本的誤報,一種設定是 0/25,另一種是 8/18(特異度 55.6%)。樣本很小,且其中一題的標準答案被報告自己判定有瑕疵。README 的表格只寫「BASELINE ESTABLISHED」,沒有這些數字。
不防範圍
這些數字不代表在別的程式碼庫、別的模型或別的提示下的表現。