Lisovate/fend

GitHub: Lisovate/fend

Fend 是一个基于微型虚拟机的沙箱运行时,通过将 npm install 及开发脚本隔离执行来抵御供应链攻击,保护开发者的密钥和凭证不被恶意依赖窃取。

Stars: 0 | Forks: 0

![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/0f79e27843180312.svg) [![npm](https://img.shields.io/npm/v/@fendsh/cli/alpha?label=npm)](https://www.npmjs.com/package/@fendsh/cli) [![downloads](https://img.shields.io/npm/dm/@fendsh/cli?label=downloads%2Fmonth)](https://www.npmjs.com/package/@fendsh/cli) ![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Platform: macOS%20arm64](https://img.shields.io/badge/platform-macOS%20arm64-111827) ![Status: alpha](https://img.shields.io/badge/status-alpha-f59e0b) # fend **抵御危险的依赖。** 一个为 `npm install` 及相关操作打造的沙箱运行时。 `npm install` 仍然会以你的用户身份运行任意的第三方代码,而近期的供应链攻击表明这在实际操作中几乎毫无阻力。围绕 Axios、Bitwarden CLI 和 SAP 的 Mini Shai-Hulud 所使用的软件包发生的安全事件展示了同样的模式:一旦在主机上执行了安装时代码,密钥和开发者环境就会暴露无遗。现有的工具大多只能在事后捕获已知的恶意软件包。Fend 采取了相反的方法,默认将软件包的执行视为恶意的。 ``` fend npm install # runs npm install inside a micro-VM fend npm run dev # dev server is sandboxed too; ports forward back fend audit # OSV.dev advisory check across the lockfile fend audit --fix # propose + apply safe upgrades ``` ## 为什么需要它 当你运行 `npm install` 时,任何软件包都可以定义 `preinstall`/`postinstall` 脚本,这些脚本会使用你的完整用户权限执行任意代码。一个恶意的依赖包可以静默读取 `~/.ssh/id_rsa`、`~/.aws/credentials`,扫描 `.env` 文件,安装后台进程,访问 macOS Keychain —— 你的用户帐户能触及的任何东西它都能碰。 `npm audit` 只能捕获*已知的* CVE 漏洞。Node 的实验性权限模型是 opt-in(选择加入)的,且鲜有使用。macOS 会保护系统文件,但你的主目录 —— 那些高价值数据存放的地方 —— 却是毫无防备的。 **fend 假设一切都是恶意的,并将执行过程与你的机器隔离开来。** 你的代码保留在原生环境中,你可以像平常一样编辑它。当某些操作需要*执行*时 —— 无论是 `npm install`、`npm run dev` 还是 `npm test` —— 它都会在一个轻量级的 micro-VM 中运行,且只通过 VirtioFS 访问*项目目录*。你机器上的其他任何内容都无法被访问。 这是将浏览器安全模型应用到了本地开发中。 ## 快速开始 通过 npm 安装的路径需要 macOS 13+ (Apple Silicon) 和 Node.js 18+。 ``` # install — 已签名且经过 Apple notarized 的二进制文件 npm install -g @fendsh/cli # 首次运行会自动准备 guest runtime(约 1.5 GB,一次性操作,之后缓存至 # ~/.fend/runtime/) fend npm install # 其他所有操作只需 `fend ` fend npm run dev # dev server runs in the VM, port 3000 forwards to host fend npm test fend node scripts/seed.js fend --network off npm test ``` 验证安装: ``` fend --version # 0.1.0-alpha.1 fend doctor # checks kernel, runtime, daemon, config ``` ### Shell hook (无前缀) 如果你不想每次都输入 `fend`,可以安装 shell hook: ``` # zsh echo 'eval "$(fend hook zsh)"' >> ~/.zshrc # bash echo 'eval "$(fend hook bash)"' >> ~/.bashrc # 然后在任何项目中 cd my-project fend on # npm/bun/pnpm/yarn/node/python now route through fend npm install # sandboxed npm run dev # sandboxed fend off # back to normal ``` ### 审计 `fend audit` 会向 [OSV.dev](https://osv.dev/) 查询针对你的 `package-lock.json` 中所有内容的公告,并打印统一的报告: ``` fend audit # report only fend audit --fix # apply safe in-range upgrades + overrides fend audit --fix --force # also apply major-version bumps fend audit --json # structured output for CI ``` 该审计也会在 `fend npm install` 之前自动运行。检查结果会显示为: ``` warn 3 advisories found worst HIGH packages 2 of 412 packages duration 1.1s Package Current Fix Worst Advisories minimist 1.2.0 1.2.6 override HIGH GHSA-xvch-5gv4-984h lodash 3.10.1 4.17.21 needs --force CRITICAL GHSA-jf85-cpcp-j695 HIGH minimist: Prototype pollution in minimist [GHSA-xvch-5gv4-984h] CRITICAL lodash: Prototype pollution in defaultsDeep [GHSA-jf85-cpcp-j695] info fix plan 1 auto-fixable, 1 major bump (--force) ``` ### 计划中:AI 辅助的软件包审查 Fend 的安装流程旨在支持未来的 AI 审查关卡,该关卡位于 `npm install --ignore-scripts` 和 `npm rebuild` 之间:首先安装不带 生命周期脚本的软件包,收集有关风险/新/带有脚本的软件包的证据, 向 AI 审查器请求结构化的裁决,然后决定是否应该运行脚本。 首个集成目标是 [`agent-ws`](https://www.npmjs.com/package/agent-ws), 一个为 Claude Code 和 Codex CLI 提供的本地 WebSocket 桥接。这使得默认情况下 provider token 保留在 Fend 外部,并允许用户复用他们现有的 CLI agent 身份验证。其预期角色是提供咨询/门禁支持 —— AI 可以解释 并标记可疑的依赖行为,但它无法证明一个软件包是安全的。 可能的审查输入: - lockfile 中新增或更改的软件包 - 生命周期脚本 (`preinstall`, `install`, `postinstall`, `prepare`) - 选定的软件包文件,如 `package.json` 和安装脚本 - OSV 审计发现 - 来自沙箱的网络和文件系统证据 未来可能的配置形式: ``` [ai] enabled = false provider = "agent-ws" # agent-ws | openai | anthropic url = "ws://localhost:9999" token_env = "FEND_AGENT_WS_TOKEN" mode = "report" # report | warn | block scope = "risky" # risky | new | direct | all max_packages = 25 ``` ### 在沙箱中运行 Claude Code ``` fend claude # runs `claude` with your Anthropic OAuth token injected, # nothing else from your machine reachable fend claude # run anything else with the same env ``` ## 配置 在项目根目录下放置一个 `.fend.toml` 文件。所有字段均为可选。 ``` [runtime] node = "22" # pin the Node version inside the VM bun = "1.1" [vm] cpus = 2 memory = "2GB" [network] mode = "on" # on | off [watch] mode = "auto" # auto | native | polling | mirror poll_interval_ms = 500 # used when polling is active [audit] level = "strict" # strict | warn | off rebuild = true # run `npm rebuild` after a clean audit auto_approve_in_ci = false # skip prompts when $CI is set block = ["malware", "critical"] # severities that halt the install prompt = ["high"] # severities that require y/N confirmation fix_on_install = true # offer to apply safe fixes before install include_prerelease = false # consider pre-release versions when fixing ``` 使用 `fend init` 生成一个。 对于那些不应该访问网络的命令,例如测试或有风险的安装脚本重建,请使用 `mode = "off"` 或 `fend --network off `。网络模式会被记录在 `fend log` 中,以供日后审查。 `[watch]` 用于控制长时间运行的开发服务器的文件更改检测。目前,`auto` 在 macOS 上保留使用原生的 VirtioFS 通知,而对于可能的 Linux 开发命令,则会切换到轮询(polling)方式,以兼容当前的 VirtioFS 主机到客户机的监视器限制。你可以使用 `fend --watch polling npm run dev` 来覆盖单个命令,或者使用 `fend --watch native npm run dev` 强制使用原生行为。`mirror` 是为计划的 Linux 模式保留的,在该模式下,主机源文件将被复制到一次性的客户机本地工作区中,以实现更好的 HMR 表现。 实用的日志过滤器: ``` fend log --network off fend log --network-events fend log --fs-risk high fend log --audit-decision blocked fend log --failed ``` 使用 `fend log --json` 检查特定运行的结构化文件系统和网络证据。 ### 终端输出 面向人类的输出有意保持紧凑:状态标签、小表格,以及针对常见失败模式的提示。客户机命令的 stdout/stderr 会原封不动地传递,因此 `npm`、`node` 和测试运行器等工具仍能正常工作。 实用的环境控制: ``` NO_COLOR=1 fend npm test # disable ANSI colors FEND_VERBOSE=1 fend npm run dev # include daemon/debug status lines FEND_QUIET=1 fend npm test # suppress non-warning host status FEND_FORCE_COLOR=1 fend log # force color even when auto-detection says no ``` ## 工作原理 `fend ` 将任何 shell 命令包装在沙箱 VM 中。在 macOS 上,这是 [Apple 的 Virtualization.framework](https://developer.apple.com/documentation/virtualization) 运行一个经过精简的 Linux,并使用 [VirtioFS](https://virtio-fs.gitlab.io/) 挂载项目目录。每个项目的首次调用会启动一个 VM(约 1 秒);后续调用会复用一个热 VM(空闲 5 分钟后自动暂停)。 一个小巧的 Rust 二进制文件 (`fendd`) 在 VM 内以 PID 1 的身份运行,通过 virtio-vsock 与主机通信,管理端口转发,并监督用户的命令。 该 VM 可以读写项目目录,并且在默认情况下可以访问网络。 可以通过 `--network off` 禁用特定命令的网络访问。它无法看到 `~/.ssh`、`~/.aws`、`~/Library`、`~/.gnupg`、项目外部的 `.env` 文件, 或主机上的任何其他路径。 有关深入的架构细节 —— VM 生命周期、场景、文件监视/HMR 策略、VirtioFS 性能、系统图表 —— 请参阅 [`ARCHITECTURE.md`](./ARCHITECTURE.md)。 ## 从源代码构建 你需要 Xcode 15+ (Swift 5.9+)、Rust 和 Docker。 ``` # Swift CLI + daemon(为本地开发进行 ad-hoc signed) FEND_AD_HOC=1 ./scripts/build-binary.sh swift/.build/release/fend --help # Rust guest agent(cross-compiled 到 aarch64-musl,baked into rootfs) cd fendd && cargo build --release --target aarch64-unknown-linux-musl # 运行测试 swift test --package-path swift cargo test --manifest-path fendd/Cargo.toml ``` 在 macOS 上,首次调用 `fend ` 会运行 `swift/scripts/prepare-runtime.sh` 并准备 `~/.fend/runtime/`。在 Linux x86_64 上,该流程现在由 Rust 二进制文件负责: `fend setup` 会准备 `~/.fend/runtime/linux-x86_64`,当需要时,正常的 `fend ` 运行引导程序会自动完成此操作。 ### 打包为 npm `scripts/build-binary.sh` 会将 macOS Apple Silicon 二进制文件暂存到 `packages/cli-darwin-arm64/bin/` 中,默认情况下会使用 Developer ID + hardened runtime + RFC 3161 时间戳 + Apple 公证进行签名。在本地开发时设置 `FEND_AD_HOC=1`(不需要 Developer ID),或者在迭代时设置 `FEND_SKIP_NOTARIZE=1` 以跳过 Apple 的提交流程。 `scripts/build-linux-binary.sh` 会将 Linux x64 主机的 `fend` 二进制文件以及 打包好的 `fendd` 客户机代理暂存到 `packages/cli-linux-x64/` 中。位于 `bin/fend.js` 的 JS 包装器通过 npm 的 `optionalDependencies` 解析正确的平台包,并在本地开发期间回退到 monorepo artifacts。 对于本地发布验证: - `./scripts/pack-npm.sh --platform darwin-arm64` 构建/暂存二进制文件并 生成根目录和平台的 `.tgz` 包。 - `./scripts/publish-npm.sh --platform darwin-arm64 --dry-run` 检查 发布顺序和包内容,而不会触及 registry。 由标签触发的 `.github/workflows/release.yml` 在 CI 中运行相同的流程, 并附带了 npm Sigstore provenance(`docs/RELEASING.md` 记录了 所需的 GitHub secrets 和完整的发布流程)。 ## 路线图 - Fend 首先专注于打造一个稳定可靠的 macOS Apple Silicon alpha 版本:npm 分发、Developer ID 签名、公证以及真实项目的浸泡测试。 - macOS Intel 是 Apple Silicon alpha 版本稳定之后的下一个候选平台。 - Linux 主机的工作正在 `linux/` 下的 Rust 中积极进行,但目前的发布路径 仍以 macOS 优先。 - Windows 和 AI 辅助审查仍是未来的工作。 请参阅 [docs/ROADMAP.md](./docs/ROADMAP.md) 获取路线图摘要,以及 [docs/linux-backend.md](./docs/linux-backend.md) 获取详细的 Linux 计划。 欢迎提交 Issues、bug 报告和 PR。 ## 安全 Fend 是一款安全工具,因此本代码仓库将供应链和披露规范视为 产品的一部分。签名提交、分支保护和私密 漏洞披露是预期发布流程的一部分。请参阅 [SECURITY.md](./SECURITY.md) 了解报告策略和响应预期。 ## 贡献 如果你想做出贡献,请先阅读 [CONTRIBUTING.md](./CONTRIBUTING.md) 了解 构建/测试期望,并阅读 [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) 了解 社区基本准则。包含测试和相关文档更新的小而专注的 PR 是最容易得到审查的。 ## 许可证 MIT — 请参阅 [LICENSE](./LICENSE)。 ## 致谢 站在巨人的肩膀上: - [Apple Virtualization.framework](https://developer.apple.com/documentation/virtualization) — macOS 虚拟机管理程序,使亚秒级 VM 启动变得可行 - [Apple Containerization](https://github.com/apple/containerization) — 验证了每个工作负载对应一个 VM 的方法 - [VirtioFS](https://virtio-fs.gitlab.io/) — 接近原生的共享文件系统性能 - [OSV.dev](https://osv.dev/) — 为 `fend audit` 提供支持的开源漏洞数据库 - [OrbStack](https://orbstack.dev/) — 证明了 Mac 上的 VM 也能感觉如同原生 - [swift-argument-parser](https://github.com/apple/swift-argument-parser)
标签:macOS开发, Node.js安全, npm脚本执行, OSV.dev, Rust, WebAssembly, 依赖安全, 前端安全工具, 前端工程化, 包管理安全, 可视化界面, 安全隔离, 开发环境安全, 微虚拟机, 暗色界面, 机密信息保护, 沙箱运行时, 网络安全审计, 网络流量审计, 请求拦截, 轻量级虚拟机, 通知系统, 防供应链攻击, 零信任执行