12 次提交、0 次合併:我在開源 AI 安全社群學到的事
目錄
我們做了一個 LLM prompt 防禦掃描器:prompt-defense-audit。掃描系統提示詞,用純 regex 偵測 12 種攻擊向量是否有防禦。不用 LLM、不用 API、5 毫秒跑完。
背後有實際資料:從 4 個公開資料集掃了 1,646 個正式環境系統提示,發現 97.8% 沒有間接注入防禦,平均分數 36/100。
我們覺得這個研究有價值,決定貢獻回開源社群。
然後花了兩週學到一個痛苦的教訓。
大撒網
我們向 12 個開源專案提交了 PR 或 Issue:
| 專案 | 類型 | 結果 |
|---|---|---|
| 一個大型 LLM 紅隊測試框架(7,500⭐) | PR | 被關閉 |
| Cisco AI Defense skill-scanner | Issue #81 | 被關閉 |
| OWASP LLM Top 10 | PR #816 | 無回應 |
| Anthropic cookbook | PR #502 | 無回應 |
| Microsoft agent-governance-toolkit | Issue #821 | 後來有回應 |
| Microsoft presidio | Issue #1933 | 無回應 |
| awesome-llm-security | PR #134 | 無回應 |
| awesome-ai-tools | PR #1031 | 無回應 |
| Awesome-Prompt-Engineering | PR #91 | 無回應 |
| agent-audit | Issue #5 | 無回應 |
| 一個 LLM 護欄框架 | Issue #1764 | 無回應 |
12 個提交。0 個合併。2 個直接被關。9 個沒人理。
為什麼全部失敗
回頭看,原因很明確。
錯誤一:用同一把鑰匙開所有的門
我們把同一套 YAML 格式的「防禦姿態 pattern」提交給不同的專案。每個專案都有自己的架構、自己的程式語言、自己的 plugin 格式。我們完全沒有去理解。
那個紅隊測試框架是 Python 寫的,核心概念是 Probe(產生攻擊)和 Detector(評估回應),用 class 繼承、有 detect() method、要跑 pytest。
我們提交了 6 個 YAML 檔案。
維護者的回覆很直接:這個 PR 完全沒有試著遵循該專案的使用方式與程式碼規範,因此婉拒。
他說得對。我們提交了一份規格書,但他們要的是可以跑的 Python 模組。
錯誤二:做好了再問
那個專案的創建者其實有在 issue 裡問我們一個問題:
"Can you give references to the principles behind the defense assessment approach & quantification method?"
我們沒有回答這個問題,就直接開了 PR。
這等於跳過了「取得共識」的步驟。在開源社群,這是大忌。你應該先在 issue 裡討論方向、確認架構適配,拿到某種程度的認可,然後再寫 code。
「做好了再問」在開源社群不是效率,是傲慢。
錯誤三:跟錯人
在那個專案的 issue 討論中,一位獨立研究者(不是該專案的維護者)很熱情地回應,說「go ahead and open that PR against community_modules/contrib/」。
我們照做了。但那個目錄結構是他自己 repo 的,不是該專案的。他沒有 merge 權限。
教訓:確認你在跟誰對話。熱情 ≠ 權限。
錯誤四:工具本身不夠格
當維護者點進我們的 prompt-defense-audit repo,他們看到:
- 3 顆星
- 3 個 commits
- 0 個 CI/CD
- 0 個 test framework(只有一個手寫 assert 的檔案)
- 沒有 CONTRIBUTING.md
- 沒有 SECURITY.md:一個安全工具,沒有安全政策
這看起來像是一個週末的 side project,不像是一個值得整合進企業級工具的函式庫。
轉折
Cisco AI Defense 的 skill-scanner 拒絕了我們的 issue,但維護者 vineethsai7 說了一句關鍵的話:
"I don't think this is part of the scope of skill-scanner. If you think the MCP specific ones can fit in the MCP scanner, please open a PR there!"
他把我們導向了 mcp-scanner。
這次我們換了方式。
先讀 code,再寫 code
我們花時間讀透了 mcp-scanner 的架構:它的 threat detection 模組怎麼寫、test 怎麼跑、Python code style 是什麼。然後用他們的語言寫了一個 Prompt Defense Analyzer,不是用我們自己的 YAML 格式。
同時打磨工具
我們把 prompt-defense-audit 從玩具升級到專業:
- 手寫 assert → Vitest,84 個測試,100% coverage
- 沒有 CI → GitHub Actions,Node 20/22 matrix,badge 亮綠燈
- 沒有文件 → CONTRIBUTING.md、SECURITY.md、CHANGELOG.md、issue templates
- 3 個 commits → 有 release notes 的 v1.3.0
正確回覆那個紅隊測試框架
回到那個專案的 issue,我們回答了創建者的方法論問題:
- 附上學術引用(Greshake et al. 2023 間接注入、Schulhoff et al. 2023 注入分類學、OWASP LLM Top 10)
- 承認 PR 架構錯誤
- 提出兩個用 Python probe/detector 重做的方向
- 明確說「我想先取得共識再寫 code」
然後等。
第一個 Merge
Cisco mcp-scanner PR #146,從開 PR 到合併:51 分鐘。
說實話,這不是一個高難度的技術成就。mcp-scanner 是新專案,積極吸收貢獻,門檻相對低。我們的 PR 是純新增(955 行新增、0 行刪除),不碰現有 code,reviewer 沒什麼要擔心的。
但它代表一件事:我們學會了用對方的語言說話。
目前的狀態
| 專案 | 狀態 |
|---|---|
| Cisco mcp-scanner | 已合併 ✅ |
| 大型 LLM 紅隊測試框架 | 等待維護者回覆。方向對了,結果未知 |
| Microsoft agent-governance-toolkit | 有正面互動,維護者提出合作方向 |
| 其餘 9 個 | 靜置 |
2026 年 9 月 26 日補註: 上表是撰文當時的狀態。Microsoft agent-governance-toolkit 的 PR #854 已於 2026 年 4 月 8 日合併。這支 PR 放了什麼(12 個攻擊向量的偵測邏輯、58 個測試)、為什麼投給這個專案,寫在從零到幫微軟寫 Code 的四個月紀錄。它從開 issue 提案、被維護者主動指派到合併的經過,連同 Cisco 那次 51 分鐘合併,則記在Cisco 在 51 分鐘內 merge 我的 PR。截至 2026 年 9 月 26 日,我們累計有 31 個 PR 合併進 15 個組織的上游專案(不含 awesome 清單收錄)。
一個 merge 不算成功。但零個 merge 到一個 merge 之間的距離,比一個到十個還遠。
給正在被拒的人
如果你也在嘗試貢獻開源 AI 安全專案,這是我們付了學費換來的經驗:
1. 先在 issue 討論,等有共識再寫 code。
大多數被拒的 PR 不是因為 code 不好,是因為方向沒對齊。一個 issue 裡的三句話討論,可以省你一週的工作。
2. 用對方的語言寫。
如果專案用 Python,你就用 Python。如果他們有自己的 base class,你就繼承那個 base class。不要發明自己的格式然後期望別人來適應你。
3. 你的工具要配得上你的野心。
如果你要向有大企業支持的專案提交貢獻,你的 repo 不能長得像一個週末專案。CI、測試、文件、安全政策:這些不是裝飾,是維護者判斷你是否可靠的信號。
4. 被拒不是終點,是資訊。
「不在我們的 scope」→ 表示你要找對的 repo。 「沒有整合我們的架構」→ 表示你要讀他們的 code。 「可以提供方法論引用嗎?」→ 表示他們有興趣,但需要你證明嚴謹度。
每一次拒絕都在告訴你下一步該往哪走。
5. 確認你在跟誰說話。
熱情的回覆 ≠ merge 權限。看清楚對方是 maintainer、contributor、還是路人。
這篇文章會更新
這個故事還沒結束。如果對方的維護者接受我們的方向,我們會用 Python 寫一個正式的 probe/detector 模組,那會是一個真正的技術挑戰。如果被拒,我們也會寫出來。
開源貢獻不是英雄故事,是反覆碰壁然後學會轉彎的過程。
本文作者是 Ultra Lab 團隊,我們做 AI 安全工具。prompt-defense-audit 是 MIT 開源,歡迎貢獻。
常見問題
開源專案的 PR 為什麼會被拒絕?
大多數被拒的 PR 不是因為 code 不好,而是方向沒對齊。我們 12 次提交全部失敗的原因有四個:用自己的 YAML 格式提交,沒有遵循對方的架構、程式語言與 plugin 格式;沒有回答創建者的問題就直接開 PR;把非維護者的熱情回覆當成權限;自己的 repo 缺少 CI、測試框架和 SECURITY.md,看起來像週末的 side project。
貢獻開源專案,要先開 issue 討論還是直接發 PR?
先在 issue 討論,等有共識再寫 code:先討論方向、確認架構適配,拿到某種程度的認可,然後再寫。在開源社群,「做好了再問」不是效率,是傲慢。一個 issue 裡的三句話討論,可以省你一週的工作。
PR 或 issue 被開源維護者拒絕後該怎麼辦?
被拒不是終點,是資訊。「不在我們的 scope」表示你要找對的 repo;「沒有整合我們的架構」表示你要讀他們的 code;「可以提供方法論引用嗎?」表示他們有興趣,但需要你證明嚴謹度。我們的第一個 merge 就來自一次拒絕:Cisco skill-scanner 的維護者拒絕我們的 issue 時,把我們導向 mcp-scanner,後來 PR #146 從開 PR 到合併花了 51 分鐘。
開源維護者怎麼判斷外部貢獻者可不可靠?
CI、測試、文件、安全政策不是裝飾,是維護者判斷你是否可靠的信號。維護者點進我們的 prompt-defense-audit 時,只看到 3 顆星、3 個 commits、沒有 CI、沒有 SECURITY.md。後來我們改用 Vitest(84 個測試、100% coverage)、加上 GitHub Actions,並補齊 CONTRIBUTING.md、SECURITY.md 與 CHANGELOG.md。