Security guide · 2026-10-08

减少本地凭据:用 1Password 和不用 1Password 的做法

这一页按凭据类型列出两套做法。一套用 1Password,另一套只用系统自带工具和开源工具。第三节单独讲办公室里当服务器用、平时没人在旁边的机器。

适用:macOS 和 Linux1Password 功能核对日期:2026-10-08

先说结论

目标是磁盘上不留明文凭据。有人在旁边的电脑,用 1Password 桌面应用加 Touch ID 发放凭据:SSH 代理、op run、shell 插件。

没人在旁边的机器按不了 Touch ID。这类机器各用一个只读的服务账号,只能读一个专用保险库。这个服务账号的令牌是磁盘上唯一留下的凭据,放进系统钥匙串或 systemd-creds。

生产环境和个人账号的凭据不放到无人值守的机器上。这套做法防的是同步、备份、git 和丢电脑造成的泄露。以你的用户身份运行的恶意程序仍然能拿到当时正在用的凭据。

一、本地凭据从哪里泄露

1.1 五条泄露路径

明文凭据的常见泄露路径
路径例子去掉明文后
云同步Dropbox、iCloud 里的 .env、密码导出文件、私钥挡住
Git 提交写在 .zshrc 或配置文件里的密钥,被 push 到 GitHub。删掉文件后,历史里还在挡住
备份Time Machine、整机镜像、发给别人的日志和导出包挡住
设备丢失笔记本被偷,磁盘没加密或开机密码太弱挡住(磁盘加密是前提)
本机恶意程序粘贴执行了一条来路不明的命令,程序以你的身份读文件和钥匙串只能缩小范围

最后一条在常见的例子中是这样发生的:有人在 MacBook 的终端里执行了一条伪装成 base64 的命令,后门拿到了 macOS 登录密码。这时登录钥匙串、浏览器保存的密码和 Cookie、SSH 私钥、云平台凭据都在攻击者的能力范围内。如果 1Password 当时处于解锁状态,它的本地数据也在范围内。攻击者随后就能从外部用这些凭据操作 GitHub 和 AWS。

1.2 这套做法挡不住什么

所以这套做法要配三件事:不在终端里粘贴来路不明的命令;每个凭据只给最小权限;发现异常时能快速轮换。

二、按凭据类型的做法

2.1 总表

每类凭据的两套做法
凭据用 1Password不用 1Password
SSH 私钥1Password SSH 代理,私钥不写到磁盘,每次使用 Touch IDmacOS:Secretive(私钥在 Secure Enclave);两种系统都可用 YubiKey 的 ed25519-sk 密钥
API 密钥、.env.env 只写 op:// 引用,用 op run 启动程序sops 加 age 加密 .env;或者运行时从钥匙串取值
命令行工具令牌shell 插件(gh、aws 等)工具自带的钥匙串存储(gh 默认就是);AWS 用 aws-vault
Git HTTPS 凭据shell 插件或 gh auth setup-gitosxkeychain、libsecret 凭据助手
提交签名用 1Password 里的 SSH 密钥签名(op-ssh-sign)用 Secretive 或 YubiKey 里的 SSH 密钥签名
云平台密钥shell 插件;能用 SSO 短期凭据时优先用 SSOSSO 短期凭据;aws-vault
网站密码、两步验证1Password 保存密码、TOTP、通行密钥;Watchtower 查弱密码和泄露Apple 密码 App;两步验证用硬件密钥或单独的验证器
无人值守机器每台机器一个只读服务账号,一个专用保险库macOS 钥匙串;Linux systemd-creds;sops 加 age

2.2 SSH 私钥

用 1Password。在 1Password 里新建或导入 SSH 密钥,然后在“设置 → 开发者”里打开“使用 SSH 代理”。在 ~/.ssh/config 里把代理指向 1Password:

Host *
  IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"   # macOS
# Linux: IdentityAgent ~/.1password/agent.sock

1Password 对每把密钥单独要求授权,用 Touch ID 或系统密码批准。确认能登录以后,删掉 ~/.ssh/id_* 私钥文件。

不用 1Password。macOS 用开源应用 Secretive,私钥在 Secure Enclave 里生成,导不出来,每次使用可以要求 Touch ID。Linux 和 macOS 都能用 YubiKey 生成 ed25519-sk 密钥,每次使用要碰一下硬件。最低要求:私钥加 passphrase,再交给 ssh-agent,不要放进 Dropbox。

2.3 API 密钥和 .env 文件

用 1Password。.env 里只写引用,格式是 op://保险库/条目/字段:

OPENAI_API_KEY=op://Dev/openai/credential
DATABASE_URL=op://Dev/slax-local-db/url

启动时用 op run --env-file=.env -- npm run dev。真实值只出现在这个进程的环境变量里。op run 默认把输出里的密钥值替换成一段提示文字。这种 .env 可以提交到 git。配置文件模板用 op inject -i config.tpl.yml -o config.yml,生成的文件要加进 .gitignore。

1Password Environments 是更新的做法:在桌面应用里管理一组变量,把它挂载成本地 .env。官方说明写的是“不把明文密钥写到磁盘”。它要求管理员打开 Environments 策略,桌面应用要处于登录状态。

不用 1Password。用 sops 加 age 把 .env 加密后提交,运行时 sops exec-env .env.enc 'npm run dev'。age 私钥是唯一的明文,放在 ~/.config/sops/age/keys.txt,不进 Dropbox。只有一两个变量时,直接从钥匙串取:export OPENAI_API_KEY="$(security find-generic-password -s openai -w)"。这一行可以写进 .zshrc,文件里没有明文。

2.4 命令行工具的令牌

用 1Password。op plugin init gh,按提示选择 1Password 里的令牌条目。以后运行 gh 时,1Password 在运行那一刻提供令牌,需要 Touch ID。1Password 为几十个工具提供了插件,包括 gh、aws、stripe、openai、huggingface。接入后删掉工具原来的明文文件,比如 ~/.config/gh/hosts.yml 里的 oauth_token。

不用 1Password。很多工具默认用系统钥匙串,gh 新版本默认存进钥匙串,加了 --insecure-storage 才写明文。先 gh auth logout,再 gh auth login,检查 hosts.yml 里不再有令牌。Docker 设置 credsStore,npm 和 PyPI 用短期令牌或可信发布。

2.5 Git 凭据和提交签名

用 SSH 地址时,Git 用的就是 2.2 节的 SSH 密钥。提交签名也用同一把密钥:

git config --global gpg.format ssh
git config --global user.signingkey "ssh-ed25519 AAAA..."      # 公钥
git config --global gpg.ssh.program "/Applications/1Password.app/Contents/MacOS/op-ssh-sign"
git config --global commit.gpgsign true

不用 1Password 时,不设置 gpg.ssh.program,签名密钥指向 Secretive 或 YubiKey 的公钥。HTTPS 地址的凭据交给 osxkeychain(macOS)或 libsecret(Linux 桌面)凭据助手。不要用 store 助手,它把令牌明文写进 ~/.git-credentials。

2.6 云平台访问密钥

长期访问密钥(AWS 的 AKIA 开头那种)是最危险的一类:泄露后在作废前一直能用。能用 SSO 的,用 aws sso login、gcloud auth login 拿几小时有效的短期凭据。必须用长期密钥时,用 1Password 的 aws 插件,或者用 aws-vault 把密钥存进钥匙串,每次换成短期凭据再交给命令。~/.aws/credentials 里不留明文。

2.7 网站密码、两步验证和恢复码

三、无人值守的机器

3.1 问题:没有人按 Touch ID

1Password 桌面应用给命令行授权时,需要有人在这台机器上按 Touch ID 或输入密码。授权在终端空闲 10 分钟后失效,最长 12 小时;应用锁定后全部授权立即失效。人在外面时,办公室的机器弹出授权框也没人批准,代理和定时任务就会卡住或失败。

不能为了方便关掉锁定,也不能让个人账号一直保持解锁。这类机器要用另一种身份:机器自己的身份,权限固定,而且很小。

3.2 用 1Password:服务账号

服务账号是给机器用的 1Password 身份,用一个令牌登录,不需要桌面应用和 Touch ID。设置 OP_SERVICE_ACCOUNT_TOKEN 环境变量后,op read、op run、op inject 都照常工作。

服务账号的请求限制(官方文档,2026-10-08 核对)
套餐每个令牌每小时整个账户每 24 小时
Business读 10,000 次,写 1,000 次50,000 次
Teams读 1,000 次,写 100 次5,000 次
Individual、Families读 1,000 次,写 100 次1,000 次

个人和家庭套餐每天只有 1,000 次,所有服务账号共用。每分钟跑一次的定时任务如果每次都调用 op,一天就超了。长期运行的程序应该在启动时取一次凭据,不要每次请求都去读。

风险服务账号令牌本身就是一个凭据。谁拿到它,谁就能读那个保险库。常见的例子中,CI 用一个服务账号读 1Password,每次 GitHub Actions 运行都会读一次。能触发工作流的人,就能借 CI 的令牌读密钥。所以保险库要小,生产凭据和测试凭据要分开。

3.3 不用 1Password:系统钥匙串和加密凭据

macOS。用户保持登录时,登录钥匙串是解锁的,后台任务可以直接读:

security add-generic-password -a "$USER" -s openai-m2 -w      # 回车后输入值,不进 shell 历史
security find-generic-password -a "$USER" -s openai-m2 -w      # 脚本里这样取值

Linux。系统服务用 systemd-creds 加密凭据。有 TPM2 芯片时,密文和这台机器绑定,拷到别的机器上解不开:

sudo systemd-creds encrypt --name=openai - /etc/credstore.encrypted/openai
# 单元文件里:
LoadCredentialEncrypted=openai:/etc/credstore.encrypted/openai
# 程序从 $CREDENTIALS_DIRECTORY/openai 读取

多台机器共用一批凭据时,用 sops 加 age:密文进 git,每台机器各有一把 age 私钥,丢一台只作废那一把。

3.4 人不在时需要高权限

无人值守的机器只放自动任务需要的凭据。人不在办公室、又要做高权限操作(生产部署、改 DNS、动个人账号)时,按下面的顺序选:

  1. 从随身电脑 SSH 到办公室机器,用 ssh -A 转发 1Password SSH 代理。授权框弹在随身电脑上,用 Touch ID 批准,办公室机器上不留私钥。只对自己的机器用 -A,不要在配置里写 Host * ForwardAgent yes。批准以后,这个会话里同一把密钥的后续连接都不再询问。
  2. 操作在随身电脑上本地做,不经过办公室机器。
  3. 等回到办公室再做。

不要为了远程方便,把生产密钥放进服务器保险库。

四、AI 代理的规则

Claude Code、Codex 这类代理以你的用户身份运行,能读你能读的文件,也能运行 op。下面五条把它们能拿到的东西压到最小:

五、方法与来源

1Password 的功能、时限和请求限制在 2026-10-08 按官方开发者文档核对。FileVault 远程解锁按 Apple 的 macOS 26 企业版说明核对。gh 从哪个版本开始默认使用钥匙串,本次没有核对。

  1. 1Password Developer,Service accounts: Get started,1password.dev/service-accounts/get-started
  2. 1Password Developer,Service account rate limits,1password.dev/service-accounts/rate-limits
  3. 1Password Developer,CLI app integration security,1password.dev/cli/app-integration-security
  4. 1Password Developer,SSH agent forwarding,1password.dev/ssh/agent/forwarding
  5. 1Password Developer,Environments,1password.dev/environments
  6. Apple Support,What's new for enterprise in macOS Tahoe 26,support.apple.com/en-us/124963
  7. Secretive(Secure Enclave SSH 密钥),github.com/maxgoedjen/secretive
  8. sops,github.com/getsops/sops
  9. aws-vault,github.com/99designs/aws-vault
  10. systemd-creds 手册,freedesktop.org/…/systemd-creds.html