Community寫作與編輯github.com

SébastienElet/agent-skills

編寫用於拒絕的程式碼:鉤子、防護、驗證器、權限檢查、lint 規則、CI 檢查點。在新增或修改任何決定通過或失敗的控制項時使用。務必在檢查可能被繞過或執行失敗時使用此技能,即使該控制項被稱為包裝器或策略。

agent-skills 是什麼?

「程式碼強制」技能提供了一套嚴謹的方法論,用於編寫安全關鍵程式碼中的防護與檢查機制。其核心哲學在於,防護的好壞取決於它拒絕了哪些繞過嘗試,而非單純通過正常路徑的測試。技能詳述了七個步驟,從定義受保護資源的實際值(而非其表達形式)、確認能否真正檢查該值(如區分啟發式方法與實際檢查)、到失敗時必須拒絕(fail closed)、保持探測結果可見、列舉所有繞過方式(如別名、複合指令、子Shell等)、將每種繞過方式轉為自動化測試,以及在風險足夠高時使用獨立代理進行對抗性測試。此技能特別適用於Claude Code、Cursor等AI代理平台,幫助開發者理解為何傳統測試無法捕捉繞過防護的漏洞。常見陷阱包括解析Shell指令字符串做決策、`command -v` 防護在缺少工具時靜默跳過、發現步驟回傳空結果卻通過檢查、以及僅對已知繞過方式進行測試。技能強調整確的檢查必須基於實際值,絕不能僅依賴其表達形式,且所有被識別的繞過方式都必須轉化為自動化測試。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/SebastienElet/agent-skills/tree/HEAD/skills/code-enforcement

Installed? Explore more 寫作與編輯 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜歡的 AI 中提問

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

說明文件

程式碼強制

概述

防護的好壞取決於它拒絕了什麼,當有人試圖繞過它時,而非它是否能順利通過快樂路徑。會存活在審查中的兩種失敗模式是:檢查的是危險值的表達形式而非實際值本身,以及因無法執行而回傳成功的控制項。這兩者在作者自身假設下所撰寫的所有測試中看起來都是綠燈。

使用方式

在撰寫或更改鉤子(hook)、防護(guard)、驗證器(validator)、權限檢查(permission check)、lint 規則(lint rule)或 CI 檢查點(CI gate)時,請遵循以下步驟——在開啟檔案之前,因為第 1 步往往會改變程式碼的歸屬位置。

典型案例:「在儲存庫外部阻擋 rm -rf」」(第 1 步將決策從指令字串上移開);「當遷移沒有回退指令時讓 CI 失敗」(第 3 步和第 4 步阻止當遷移列表回傳空值時通過檢查點);「拒絕沒有簽署提交的推送」(第 5 步列舉別名、--no-verify` 和第二個遠端)。

步驟

  1. 命名接受點(Sink)。 寫下最終到達受保護資源的精確值:展開後的 argv、請求主體、SQL 參數、解析後的路徑。針對該值進行驗證。
  2. 檢查你是否真的能看到它。 如果程式碼只有該值的表達形式——一個 Shell 指令字串、一個 diff、一行日誌、一個提交訊息——那麼這個決策是啟發式的,而非真正的檢查。請在註解和交付備註中說明,並將該層標記為建議性質。不要讓一個啟發式檢查成為你無法撤銷之後果的唯一屏障。
  3. 失敗時封閉(Fail closed)。 缺少執行環境、無法讀取輸入、解析器異常、未解析的變數、空結果:拒絕,並指出缺少什麼。一個因為無法執行而退出碼為 0 的防護就是一個被禁用的防護,而且它會默默地保持被禁用數個月。
  4. 保持探測失敗的可見性。 不要在決定防護能否執行的指令後加上 2>/dev/null,也不要有任何分支將空結果轉化為成功。如果容許探測靜默失敗,則第 3 步無法強制執行。
  5. 在編寫修復程式之前列舉繞過方式。 列出控制項可能被滿足或跳過的方式:複合指令、重複的旗標、第二次呼叫、別名或函數、缺少直譯器、另一台主機、子 Shell、重新命名的檔案。將此列表保留在提交訊息或測試檔案中。
  6. 將該列表中的每一項轉化為測試案例,並整合到專案的自動化檢查中。手動自行測試不算:它會隨著執行它的會話一起消失。
  7. 當繞過方式成本低廉且後果嚴重時,執行對抗性測試。 派遣一個全新上下文(fresh-context)的子代理,其任務是破解該防護,而非審查它;其輸出是嘗試及其結果的列表。對於最壞情況僅為警告的控制項則可跳過此步驟。

常見陷阱

  • 解析 Shell 指令來做決定。 引號處理、$()、&&、別名和 env 前綴都會改變最終執行的內容。這樣的層級只是一個減速丘;真正的檢查應屬於指令效果發生的地方。
  • command -v 防護。 if command -v tool > /dev/null; then check; fi 會在缺少該工具的機器上靜默跳過檢查——而這正是最需要它的機器。反過來做:當工具缺失時拒絕。
  • 一個發現步驟什麼也沒找到。 git grep -E 不支援 \b,因此這樣的模式會匹配到零個檔案而不報錯,檢查點因讀取了空結果而通過。用一個金絲雀(canary)來保護該步驟:一個你知道必須出現在其輸出中的檔案。
  • 只測試你實作的那種拒絕。 有趣的測試是你沒想到的輸入;這就是第 5 步要產生的東西。
  • 僅靠手動測試的防護。 它在作者的機器上通過,然後慢慢腐爛。如果專案沒有地方可以接入測試,那麼缺少測試框架本身就是一部分工作。
  • 撰寫防護的上下文無法破解它。 它與產生漏洞的上下文共享盲點,並會確認自己的設計。只有全新的上下文才具有對抗性。

限制條件

  • 絕不能以受保護值的代理(proxy)來做決定,當實際值本身可達時。
  • 絕不能在防護無法執行其工作的路徑上以退出碼 0 結束;應拒絕並指出原因。
  • 絕不能壓制用於確定防護是否可運行的探測步驟的錯誤。
  • 每個被列舉的繞過方式,在交付前都必須存在於自動化測試中。
  • 清楚說明哪一層是建議性質、哪一層是強制性質;把啟發式方法當成保證,比完全沒有防護更糟。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

相關技能