Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
enject — enject: 将 .env 机密从 AI 的窥探中隐藏:机密存储在本地加密存储(每个项目)中,并在运行时直接注入应用程序,从不以明文形式接触磁盘。 | Kitploit
工具/GitHubGitHub/greatscott/enject
加密/解密工具云安全DevSecOps秘密检测供应链安全身份验证
GitHubgreatscott/enject

enject

enject: 将 .env 机密从 AI 的窥探中隐藏:机密存储在本地加密存储(每个项目)中,并在运行时直接注入应用程序,从不以明文形式接触磁盘。

查看仓库
50014166个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

enject

将 .env 机密隐藏,远离 AI 的窥探。

(注意:该项目原先名为 enveil,现已更名为 enject)

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 文件)来存储生产环境机密。

工作原理

你的 .env 文件看起来像这样:

root@kitploit:~
DATABASE_URL=en://database_url
STRIPE_KEY=en://stripe_key
PORT=3000

从技术上讲,它可以安全地提交(不过最好还是别这么做),更重要的是:任何 AI 工具意外(或许并非那么意外)窥探它时都是安全的。

当你运行 enject run -- npm start 时,它会:

  1. 提示输入主密码(不回显,不进 shell 历史)
  2. 使用 Argon2id(64 MB 内存,3 次迭代)从密码派生 256 位 AES 密钥
  3. 使用 AES-256-GCM 解密本地存储——存储文件由一个 12 字节随机 nonce 及随后的已验证密文组成
  4. 根据解密的映射表解析每一个 en:// 引用
  5. 将密钥和密码字节从内存中归零
  6. 启动子进程,将解析后的值注入其环境

存储文件是一个二进制 blob。没有主密码,它与随机噪声无异。每次写入时都会生成全新的 nonce,因此 AES-GCM nonce 重用不可能发生。对密文的任何修改——哪怕只翻转一位——都会导致认证失败,拒绝解密。


安装

通过 cargo

此版本仍为 alpha 版本,因此在调用 cargo install 时需要附加最新版本号。

root@kitploit:~
cargo install enject --version 0.2.0-alpha 

从源码编译

需要 Rust 1.70+。

root@kitploit:~
git clone https://github.com/greatscott/enject
cd enject
cargo build --release

编译后的二进制文件位于 target/release/enject。将其安装到 PATH 中的某个位置,以便从任何项目运行:

macOS / Linux (bash 或 zsh)

root@kitploit:~
# 选项 A: ~/.local/bin(无需 sudo,Linux 常用)
mkdir -p ~/.local/bin
cp target/release/enject ~/.local/bin/

# 选项 B: /usr/local/bin(需要 sudo,系统全局可用)
sudo cp target/release/enject /usr/local/bin/

# 选项 C: ~/.cargo/bin(如果你使用 rustup,此目录已位于 PATH)
cp target/release/enject ~/.cargo/bin/

如果你使用了选项 A 且 ~/.local/bin 尚未在 PATH 中,请将以下内容添加到 shell 配置(~/.zshrc、~/.bashrc 或 ~/.bash_profile):

root@kitploit:~
export PATH="$HOME/.local/bin:$PATH"

然后重新加载:

root@kitploit:~
source ~/.zshrc   # 或 ~/.bashrc

验证是否成功:

root@kitploit:~
enject --version

每个项目设置(每个项目运行一次)

二进制文件是全局安装的——你不需要重新安装它。但每个项目都有自己的加密存储:

root@kitploit:~
cd your-project
enject init

这会在当前目录创建 .enject/,包含项目的配置和加密存储。将其添加到 .gitignore——它绝不应被提交。


使用方法

初始化存储

每个项目运行一次,在项目根目录:

root@kitploit:~
enject init

这会生成一个随机的 32 字节盐,写入 .enject/config.toml,创建一个空的加密存储文件 .enject/store,并提示你设置主密码。将 .enject/ 添加到你的 .gitignore——存储文件绝不应被提交。

添加机密

root@kitploit:~
enject set some_database_url
# 提示: Value for 'database_url': (隐藏输入)

enject set some_api_key

值始终以交互方式输入。无法将值作为命令行参数传递——这可以防止机密出现在 shell 历史或 ps 输出中。

在 .env 中引用机密

root@kitploit:~
DATABASE_URL=en://some_database_url
MY_API_KEY=en://stripe_key
PORT=3000

纯 KEY=VALUE 行保持不变。只有 en:// 引用会被解析。

运行你的应用

root@kitploit:~
enject run -- npm start
enject run -- python manage.py runserver
enject run -- cargo run

-- 之后的所有内容都会原样传递给操作系统。子进程继承你的完整 shell 环境(因此 PATH、HOME 等存在),并在其基础上叠加 .env 中的值。

其他命令

root@kitploit:~
enject list              # 打印存储的密钥名称(不显示值)
enject delete <key>      # 删除一个机密
enject import <file>     # 加密纯文本 .env 中的所有值,将其重写为 en:// 模板
enject rotate            # 使用新的主密码重新加密存储

故意缺失的命令

没有 get 和 export 命令。将机密值打印到标准输出会创造一个 AI 可读的泄露渠道——enject 的全部意义就在于将值保留在磁盘和任何可读输出流之外。


安全性验证

每个安全不变量都有对应的自动化测试和手动检查路径。

运行所有自动化测试

root@kitploit:~
cargo test

31 个测试,全部覆盖以下声明。


1. 机密永远不会以明文写入磁盘

自动化: store::password::tests::test_encrypt_decrypt_roundtrip

保存一个机密,持久化存储,从磁盘重新加载,解密,并检查值是否往返正确。只有当磁盘上的字节是有效的密文时测试才会通过——明文会导致解密失败。

root@kitploit:~
cargo test store::password::tests::test_encrypt_decrypt_roundtrip

手动检查:

root@kitploit:~
enject init          # 密码: test123
enject set mykey     # 值: my-super-secret

xxd .enject/store | head -5
strings .enject/store

xxd 将显示二进制数据。strings 将返回空——没有可提取的 ASCII 序列。前 12 个字节是随机 nonce;之后是 AES-GCM 密文,末尾附加了 16 字节的认证标签。


2. 每次写入都使用全新的随机 nonce

自动化: store::password::tests::test_nonce_changes_on_each_save

连续保存存储两次,每次读取文件的前 12 个字节,并断言它们不同。

root@kitploit:~
cargo test store::password::tests::test_nonce_changes_on_each_save

手动检查:

root@kitploit:~
xxd .enject/store | head -1    # 注意前 12 个字节
enject set anotherkey          # 任何写入都会轮换 nonce
xxd .enject/store | head -1    # 前 12 个字节现在不同

3. 错误密码返回错误

自动化: store::password::tests::test_wrong_password_returns_err

用一个密码创建存储,然后尝试用另一个密码解锁,并断言返回 Err。

root@kitploit:~
cargo test store::password::tests::test_wrong_password_returns_err

手动:

root@kitploit:~
enject list    # 输入错误密码
# 输出: "Wrong master password or corrupted store."
# 退出码: 1

4. 篡改密文会被拒绝(AES-GCM 认证)

AES-GCM 会在密文上生成一个 16 字节的认证标签。任何修改——哪怕只翻转一位——都会导致验证在解密前失败。明文永远不会暴露。

自动化: store::password::tests::test_tampered_ciphertext_returns_err

在存储文件的密文区域(前 12 字节 nonce 之后)翻转一个字节,然后尝试解密并断言 Err。

root@kitploit:~
cargo test store::password::tests::test_tampered_ciphertext_returns_err

手动:

root@kitploit:~
# 翻转第 20 个字节(密文内部,nonce 之后)
python3 -c "
data = open('.enject/store', 'rb').read()
bad  = data[:20] + bytes([data[20] ^ 0xFF]) + data[21:]
open('.enject/store', 'wb').write(bad)
"
enject list
# 输出: "Wrong master password or corrupted store."

5. 任何未解析的 en:// 引用都会导致硬错误

如果 .env 中的引用在存储中没有匹配的密钥,enject run 会立即退出并返回非零退出码。子进程永远不会被启动。

自动化: env_template::tests::test_unknown_ev_ref_returns_err

调用 resolve() 并传入一个没有匹配条目的引用,断言返回 Err。

root@kitploit:~
cargo test env_template::tests::test_unknown_ev_ref_returns_err

手动:

root@kitploit:~
echo "DB=en://nonexistent_key" > .env
enject run -- env
# 输出: Secret 'nonexistent_key' not found in store. Add it with: enject set nonexistent_key
# 退出码: 1  (`env` 子进程从未运行)

未来方向

1. 全局存储

实现可选的/附加的系统级存储,以便更轻松地维护跨多个项目使用的机密。

2. 集成系统钥匙串等

减少每次更新时手动输入存储密码的需求。

下载工具