AI 編碼工具,如 Claude Code、Copilot、Cursor 等,能夠讀取您專案目錄中的檔案,這意味著明文的 .env 檔案可能成為意外洩漏機密資訊的來源。這並非理論上的問題,而是我親身經歷過幾次的已知問題(即使在 Claude Code 的 settings.json 檔案中明確指示 Claude 不要窺探)。enject 透過確保機密資訊的明文形式完全不會出現在磁碟上來解決此問題。您的 .env 檔案僅包含符號參考;真實的值儲存在加密的本機儲存庫中,並在啟動時直接注入到您的子程序中。

此專案的靈感來自 Filip Hric 的解決方案/部落格文章,該文章利用 1Password 使用類似的概念。我想要一個獨立的解決方案,不依賴第三方服務,因此催生了這個專案。是的,這個專案幾乎完全是使用 Claude Code 開發的,並經過大量的手動驗證和測試。

此專案主要設計用於減輕 AI/LLM 工具意外讀取專案中 .env 機密資訊的已知問題。額外的優勢包括防止 .env 檔案意外提交到儲存庫時洩漏機密資訊,能夠分享包含參考而非明文機密的 .env 檔案,以及分享加密儲存庫本身的選項。

此專案並非防止 AI 代理獲取您機密資訊的萬靈丹。例如,代理仍然可以(意外地或透過提示注入)編寫將機密資訊洩漏到終端輸出或執行階段檔案的程式碼。我們強烈建議不要依賴此工具,或一般而言的 .env 檔案來儲存生產環境的機密資訊。

技術上來說,它可以安全地提交(或許還是不要這麼做),更重要的是:對於任何意外(或或許不是那麼意外)窺探它的 AI 工具來說是安全的。

當您執行 enject run -- npm start 時,它會:

儲存檔案是一個二進位 Blob。沒有主密碼,它與隨機雜訊無法區分。每次寫入時都會重新生成一個新的 Nonce,因此不可能重複使用 AES-GCM Nonce。對密文的任何修改——即使是單一位元的翻轉——都會導致驗證失敗並拒絕解密。

此版本仍處於 Alpha 階段,因此在呼叫 cargo install 時需要附加最新版本進行安裝。

編譯後的二進位檔案位於 target/release/enject。將其安裝到 PATH 中的某個位置一次,以便您可以從任何專案執行它:

如果您使用了選項 A 且 ~/.local/bin 尚未加入 PATH,請將以下內容添加到您的 shell 設定檔(~/.zshrc、~/.bashrc 或 ~/.bash_profile)中:

二進位檔案是全域安裝的——您無需重新安裝它。但每個專案都有自己的加密儲存庫:

這會在目前目錄中建立 .enject/,其中包含專案的設定檔和加密儲存庫。將其加入 .gitignore——它永遠不應該被提交。

每個專案執行一次此命令,位於專案根目錄:

這會生成一個隨機的 32 位元組 salt,寫入 .enject/config.toml,在 .enject/store 建立一個空的加密儲存庫,並提示您設定主密碼。將 .enject/ 加入您的 .gitignore——儲存庫永遠不應該被提交。

值始終透過互動方式輸入。沒有辦法將值作為命令列參數傳遞——這可以防止機密資訊出現在 shell 歷史記錄或 ps 輸出中。

純粹的 KEY=VALUE 行會原封不動地通過。只有 en:// 參考會被解析。

-- 後面的所有內容都會原封不動地傳遞給作業系統。子程序會繼承您的完整 shell 環境(因此 PATH、HOME 等都存在),並疊加 .env 值。

沒有 get 和 export。將機密值列印到 stdout 會產生一個 AI 可讀的洩漏向量——enject 的全部目的是讓值遠離磁碟和任何可讀的輸出流。

每個安全不變量都有對應的自動化測試和手動檢查路徑。

31 個測試,全部涵蓋以下聲明。

自動化:store::password::tests::test_encrypt_decrypt_roundtrip

儲存一個機密,持久化儲存庫,從磁碟重新載入,解密,並檢查值是否正確往返。只有當磁碟上的位元組是有效的密文時才會通過——明文會解密失敗。

xxd 會顯示二進位資料。strings 不會返回任何內容——沒有可以提取的 ASCII 序列。前 12 個位元組是隨機 Nonce;之後的所有內容都是 AES-GCM 密文,並附加一個 16 位元組的驗證標籤。

自動化:store::password::tests::test_nonce_changes_on_each_save

連續儲存兩次儲存庫,每次讀取檔案的前 12 個位元組,並斷言它們不同。

自動化:store::password::tests::test_wrong_password_returns_err

使用一個密碼建立儲存庫,然後嘗試使用另一個密碼解鎖它,並斷言返回 Err。

AES-GCM 會對密文產生一個 16 位元組的驗證標籤。任何修改——即使是單一位元的翻轉——都會在解密進行之前導致驗證失敗。明文永遠不會暴露。

自動化:store::password::tests::test_tampered_ciphertext_returns_err

翻轉儲存庫檔案的密文區域(在 12 位元組 Nonce 之後)的一個位元組,然後嘗試解密並斷言 Err。

如果 .env 中的參考在儲存庫中沒有匹配的鍵,enject run 會立即以非零代碼退出。子程序永遠不會啟動。

自動化:env_template::tests::test_unknown_ev_ref_returns_err

呼叫 resolve() 並傳入一個沒有匹配項的參考,並斷言 Err。

實作可選/額外的系統級儲存庫,以便更容易維護跨多個專案使用的機密資訊。

減少在更新時每次手動輸入儲存庫密碼的需求。