• 请不要在回答技术问题时复制粘贴 AI 生成的内容
vone
V2EX  ›  程序员

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

  •  
  •   vone · 1h 32m ago · 285 views

    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 、目前只拦截了文件的访问,但是并未对原文件做加密,只能阻拦有针对性的机密文件获取。

    3 replies    2026-05-12 14:16:46 +08:00
    yangg
        1
    yangg  
       1h 19m ago
    这个是个不错的方向
    xylophone21
        2
    xylophone21  
       1h 13m ago
    比如 ~/.aws/credentials 文件,
    - 如果使用 aws cli 进程或者 skill 的脚本来读取, 则是合法的,配置后自动授权
    - 如果其他进程来读取,比如 AI 直接读, 临时专项的脚本等, 则弹出授权

    原理上可以实现吗
    vone
        3
    vone  
    OP
       59 mins ago
    @xylophone21 取决于 FUSE 的实现方式。
    1 、在 Linux 、Windows 上读取访问进程名是没问题的。
    2 、在 MacOS 上如果是 macFUSE 可以读取访问进程名,但是 macFUSE 的安装需要通过内核扩展,目前安装比较麻烦。目前我推荐使用的 fuse-t 是基于 NFS 协议实现的,无法获取访问进程名。
    3 、在 MacOS 上也可以通过 ESF 框架实现,但是这个权限 Apple 官方审核很严格,只针对大型安全公司开放。
    4 、在 MacOS 上推荐使用 fuse-t
    所以结论就是:MacOS 不太行,其他系统可以。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5651 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 07:16 · PVG 15:16 · LAX 00:16 · JFK 03:16
    ♥ Do have faith in what you're doing.