spences10/nopeek

GitHub: spences10/nopeek

为 LLM 编程 agent 设计的环境变量安全加载 CLI,在让 agent 正常使用密钥的同时防止真实值出现在输出或聊天上下文中。

Stars: 6 | Forks: 1

# nopeek [![使用 vite+ 构建](https://img.shields.io/badge/built%20with-Vite+-646CFF?logo=vite&logoColor=white)](https://viteplus.dev) [![使用 vitest 测试](https://img.shields.io/badge/tested%20with-Vitest-6E9F18?logo=vitest&logoColor=white)](https://vitest.dev) 用于 LLM agent 机密安全的 CLI。nopeek 可为编程 agent 加载环境机密信息, 而不会在工具输出或聊天上下文中暴露机密值。 Agent 只能看到密钥的 _名称_,而看不到密钥的 _值_。 ## 快速开始 在 LLM 编程会话中,告诉 agent 使用 nopeek: ``` "run npx nopeek load .env then use $DATABASE_URL to query the users table" "use npx nopeek load .env --only STRIPE_KEY and then curl the billing API" "run npx nopeek load .env --only API_KEY,API_SECRET and test the auth endpoint" ``` agent 会运行该命令,仅获取密钥名称,并在随后的命令中 使用该变量,而永远不会看到其真实值。 ## 工作原理 LLM 编程 agent 可见的 Shell 命令输出可能会被发送到 模型提供商并被其保留。nopeek 可以防止机密信息 出现在该输出中。 **步骤 1.** 告诉你的 agent 使用 nopeek。它只需运行 该命令;它会自行从 CLI 输出中 发现子命令和标志: ``` npx nopeek load .env --only DATABASE_URL ``` **步骤 2.** nopeek 将值注入到会话环境中,并 仅打印密钥名称: ``` Loaded 1 key from .env: DATABASE_URL ``` **步骤 3.** agent 现在可以通过名称使用该变量,而 无需看到其具体值: ``` psql $DATABASE_URL -c "SELECT count(*) FROM users" ``` ### 可选的 agent 提醒 如果你使用带有持久系统提示扩展的 harness,可以添加 一个简短的提醒,以便模型能自动调用 nopeek, 而无需在每个提示中都包含快速开始文本。对于 Pi 用户, `@spences10/pi-nopeek` 扩展可以完成此操作: ``` pi install npm:@spences10/pi-nopeek ``` [`my-pi`](https://github.com/spences10/my-pi) 已默认 包含此提醒。这是可选的:nopeek 仍然是与 harness 无关的, 并且当你在会话中提到它时,它在任何地方依然有效。 根据环境分为三种模式: | 上下文 | 行为 | | --------------------------------------------- | --------------------------------------------- | | 支持 env-file 注入的 Agent 会话 | 直接写入 env 文件,最安全 | | 不支持 env-file 注入的 Agent 会话 | 写入临时文件,输出 `source` 命令 | | 常规 Shell | 打印用于 `eval` 的 `export` 语句 | ## 用法 无需安装。你的 agent 可以直接通过 `npx` 运行它: ``` npx nopeek load .env npx nopeek load .env --only DATABASE_URL npx nopeek set MY_API_KEY --from-env npx nopeek status ``` 所有命令均旨在 LLM 编程会话内部运行。只需 在你的提示中提及 `nopeek`。agent 将从 CLI 输出中 发现正确的子命令。 ## 命令 ### `load` - 从 .env 或 .tfvars 文件加载机密信息 ``` npx nopeek load .env npx nopeek load .env --only DATABASE_URL,API_KEY npx nopeek load .env --persist # also save to config for future sessions npx nopeek load terraform.tfvars --only prod_password npx nopeek load production.tfvars.json --only db_password ``` 支持的格式: | 扩展名 | 格式 | | ---------------- | ----------------------------- | | `.env`, `.env.*` | `KEY=value` | | `.tfvars` | `key = "value"` (HCL 字符串) | | `.tfvars.json` | JSON 顶层字符串 | 对于 `.tfvars` 文件,仅加载顶层的带引号字符串值。 映射、列表、数字和布尔值将被跳过。 `--persist` 标志可将密钥保存到 `~/.config/nopeek/config.json`, 以便 SessionStart 钩子可以在未来的会话中自动注入它们。 ### `set` - 存储机密密钥 ``` npx nopeek set MY_API_KEY --from-env # read from current shell env npx nopeek set MY_API_KEY # interactive prompt (TTY only) ``` 以 `0600` 权限存储到 `~/.config/nopeek/config.json`。 这是静态明文存储;请仅对你可以 接受以明文形式保存在用户配置中的机密信息使用 `set`/`--persist`。 ### `list` - 显示可用密钥 ``` npx nopeek list ``` 显示密钥名称和来源,不包含值。 ### `remove` - 移除已存储的密钥 ``` npx nopeek remove MY_API_KEY ``` ### `init` - 扫描并配置云 CLI ``` npx nopeek init ``` 检测已安装的云 CLI,检查其身份验证配置,并 存储配置文件映射。 | CLI | 更安全的模式 | 检测方式 | | -------- | ---------------------------------------------------- | -------------------------------------------------- | | `aws` | 命名配置文件 (`AWS_PROFILE`) | `~/.aws/credentials` + 环境变量 | | `hcloud` | 命名上下文 (`HCLOUD_CONTEXT`) | `~/.config/hcloud/cli.toml` | | `gcloud` | 命名配置 (`CLOUDSDK_ACTIVE_CONFIG_NAME`) | 活跃的 gcloud 账户 + 内联凭证环境变量 | | `az` | Azure CLI 缓存登录 + 活跃订阅 | `az account show` + 内联凭证环境变量 | ### `status` - 显示当前状态 ``` npx nopeek status ``` 显示会话类型、已存储的密钥、CLI 配置文件以及检测到的 CLI。 ### `audit` - 扫描暴露的机密信息 ``` npx nopeek audit npx nopeek audit ./path/to/dir ``` 扫描 `.env` 文件并报告通过模式 匹配发现的机密信息(AWS 密钥、Bearer token、API 密钥、私钥、 连接字符串等)。检查 `.gitignore` 的覆盖情况。 ## 安全性 - **密钥名称验证** - 环境密钥名称会根据 `^[a-zA-Z_][a-zA-Z0-9_]*$` 进行验证,以防止 Shell 注入 - **安全的文件权限** - config 目录为 `0700`,config 文件为 `0600`,临时 env 文件为 `0600` - **原子写入** - config 通过临时文件 + 重命名的方式进行写入, 以防止损坏 - **输出前进行密钥验证** - 在打印 Shell 导出之前,会拒绝无效的环境变量名 - **标准输出中不含值** - 在检测到的 agent 会话中,值会被 写入 env 文件或临时文件;只有 `source` 路径或密钥名 会到达标准输出 - **明文配置警告** - 持久化的密钥是受文件权限(而非加密) 保护的本地明文机密 ## 推荐的 Agent 拒绝规则 nopeek 是主要的防御手段,但在任何支持拒绝规则的 agent 运行时中,拒绝规则都是一个有用的安全网。它可以阻止 agent 读取 机密文件或将凭证内联嵌入到命令中: ``` { "permissions": { "deny": [ // Block reading secret files "Read(.env)", "Read(*.env)", "Read(*.tfvars)", "Read(*credentials*)", "Read(*secret*)", "Read(**/.config/gcloud/**)", "Read(**/.azure/**)", "Read(*service-account*.json)", // Block cat/head on secret files "Bash(cat .env)", "Bash(cat *.env*)", "Bash(cat *tfvars*)", "Bash(cat *credentials*)", "Bash(cat *secret*)", // Block inline credentials in commands "Bash(PGPASSWORD*)", "Bash(*HCLOUD_TOKEN*)", "Bash(hcloud context create*)", "Bash(*GOOGLE_APPLICATION_CREDENTIALS*)", "Bash(*CLOUDSDK_AUTH_ACCESS_TOKEN*)", "Bash(*GOOGLE_OAUTH_ACCESS_TOKEN*)", "Bash(*AZURE_CLIENT_SECRET*)", "Bash(*ARM_CLIENT_SECRET*)", "Bash(*AZURE_PASSWORD*)", "Bash(*AZURE_ACCESS_TOKEN*)", "Bash(*ARM_ACCESS_KEY*)", // Block fetching secret values from cloud providers "Bash(*secretsmanager get-secret-value*)", "Bash(*hetzner*secret*)", "Bash(*hetzner*access_key*)", "Bash(gcloud auth print-access-token*)", "Bash(gcloud auth application-default print-access-token*)", "Bash(az account get-access-token*)", ], }, } ``` 如果没有这些规则,agent 仍然可以直接读取 `.tfvars` 或 `.env` 文件,并将这些值硬编码到 Shell 命令中。nopeek 可以防止机密信息出现在 _输出_ 中,而拒绝规则则可以从根本上阻止 agent _读取_ 这些文件。 ## 局限性 - **基于模式的机密检测是尽力而为的。** 审计 模式能捕获已知的格式,但无法捕获所有可能的机密。 - **Agent 检测是基于标记的。** nopeek 会检测常见的 agent 环境标记和 env-file 注入,但没有哪个 CLI 能保证 识别出所有的 harness。 - **临时文件会在磁盘上短暂存在。** 这些文件以 `0600` 权限写入 `/tmp/nopeek/`,但在文件被清理之前, 其值一直存在于磁盘上。 - **持久化的密钥是明文的。** `set` 和 `load --persist` 会 以 `0600` 权限将值存储在 `~/.config/nopeek/config.json` 中。 - **输出编校并不全面。** 建议将机密信息作为 环境变量加载,这样就根本不需要打印它们的值了。 ## 许可证 MIT
标签:AI编程助手, Cutter, DLL 劫持, GNU通用公共许可证, JSONLines, LLM代理, meg, MITM代理, Node.js, Vite, Vitest, XML 请求, 代理安全, 信息安全, 大语言模型, 大语言模型安全, 安全助手, 安全基线, 安全开发, 密钥保护, 开发安全, 教学环境, 机密管理, 环境变量, 环境隔离, 结构化查询, 网络安全, 自动化安全, 自动化攻击, 防数据泄露, 隐私保护, 零信任