从 npm 投毒事件思考,我写了一个基于 FUSE 的 macOS 文件守护工具 Shield

最近一段时间发生了多次投毒事件,恶意代码随意读取 ~/.ssh 、.npmrc 、等机密文件然后静默上传。整个过程中系统没有任何阻拦。机密文件的泄露后导致的密钥轮换工作操作了不少额外的工作和风险,所以最近 Vibe Coding 了一个简单的工具,来尝试解决这个问题。 下面简单介绍一下开发的思路和实...
从 npm 投毒事件思考,我写了一个基于 FUSE 的 macOS 文件守护工具 Shield
从 npm 投毒事件思考,我写了一个基于 FUSE 的 macOS 文件守护工具 Shield

Shield - macOS File Access Protection

最近一段时间发生了多次投毒事件,恶意代码随意读取 ~/.ssh 、.npmrc 、等机密文件然后静默上传。整个过程中系统没有任何阻拦。机密文件的泄露后导致的密钥轮换工作操作了不少额外的工作和风险,所以最近 Vibe Coding 了一个简单的工具,来尝试解决这个问题。

下面简单介绍一下开发的思路和实现原理,更详细内容可以阅读 https://www.npmjs.com/package/@yangch/shieldREADME.md

它做了什么

Shield 是一个基于 FUSE (用户空间文件系统) 的 macOS 命令行工具,能让你指定的敏感文件在被任何进程读取时,弹出一个原生对话框问你“允许还是拒绝”。

技术实现细节

核心流程只有三步:文件重定向 → FUSE 拦截 → 用户授权。

1.存储与重定向

当你执行 shield add ~/.ssh/id_rsa 时:

原始文件被移动到 /usr/local/var/shield/storage/ 下对应的路径

原位置创建一个符号链接,指向 FUSE 挂载点 /usr/local/var/shield/mount/ 下的相同路径

之后,任何对 ~/.ssh/id_rsa 的读写都会经过这个 FUSE 挂载点,由守护进程接管。

2.FUSE 层拦截

Shield 内部运行一个 shield-daemon ,它通过 FUSE 实现了一个简单的文件系统。当进程执行 open() 调用试图打开受保护的文件时,内核将该调用转发到守护进程的 FUSE 处理函数。

这里使用的是 fuse-t (推荐,无需内核扩展,支持 macOS 13+),也可以回退到 macFUSE 。整个拦截发生在用户空间,不影响系统稳定性。

3.用户授权对话框

守护进程收到访问请求后,通过调起一个原生 macOS 对话框,选择 Allow 会放行本次读取,并缓存授权 10 秒。在这 10 秒内,同一文件再次被读不会重复弹窗,避免频繁打扰。选择 Deny 则直接返回错误给调用方,调用方会收到类似 Operation not permitted 的结果,文件内容不会被泄露。

所有授权/拒绝决定都会被写入日志,事后可以审计。 Shield Access Dialog

Access Denied 4.后台驻留

Shield 作为 launchd 服务运行,开机自启。用户可以通过 shield start/stop/status 管理守护进程,不占用 Dock 或菜单栏,静默运行。

安装与使用

# 先安装 fuse-t (推荐,无 kext )
brew install fuse-t

# 安装 Shield
sudo npm install -g @yangch/shield

# 初始化并启动服务
sudo shield install

# 添加要保护的文件
sudo shield add ~/.ssh/id_rsa
sudo shield add ~/.aws/credentials
sudo shield add ~/.npmrc

# 查看守护列表
shield list
# 移除保护(会还原文件到原始位置)
sudo shield remove ~/.ssh/id_rsa

之后只要你在使用系统,任何对受保护文件的读取都会弹窗询问。

一些说明

1 、只支持 macOS ,推荐使用 fuse-t (用户空间,无需批准内核扩展),Windows 暂时还没有支持。

2 、目前只拦截了文件的访问,但是并未对原文件做加密,只能阻拦有针对性的机密文件获取。

来源: V2EX - 技术查看原文