berylliumsec/safe-galaxy
GitHub: berylliumsec/safe-galaxy
一款基于Rust的包安装时行为检测工具,通过沙箱化重放、AST能力提取和语义分析在依赖安装阶段实现实时安全干预与审批。
Stars: 0 | Forks: 0
# safe-galaxy


实际运行中的交互式安装审查与运行时批准。请参阅
[`docs/demo/terminal-recording.md`](docs/demo/terminal-recording.md) 以了解
录制工作流和源脚本。
致谢
首先我要感谢全知全能的上帝,祂是一切知识的源泉;没有祂,这一切都不可能实现。
## 概述
该 CLI 暴露了两个等效的入口点:
- `safe-galaxy`
- `sg`
`safe-galaxy` 是一个以 Rust 为基础的包安装防护工具,侧重于:
- 元数据驱动的包检查
- AST 能力提取
- 跨静态分析和运行时审计的第一方语义推理
- 面向开发者的、安装期间的实时行为审查
- 为 `pip`、`uv` 和 `pnpm` 生成安装计划
- 在每个包管理器阶段通过 `bubblewrap` 执行防护安装,并在最终重放时加上 Landlock
- 为沙箱阶段提供可选的 syscall 追踪
- 为敏感的宿主机根目录提供可选的运行时路径批准提示
- 在受防护的安装重放之前进行分阶段的构件分析
许多依赖安全工具主要依赖于历史信号,例如
公告、声誉或预计算的包风险。`safe-galaxy` 增加了实时
安装干预:它在重放前暂存并分析构件,在受防护的执行下运行
真实的包管理器阶段,展示实际发生的具体
行为,并在安装
发生时推荐或执行决策。目标不仅是说“这个包看起来有风险”,
而是帮助开发者了解包在安装时做了什么,
在上下文中展示该行为,并让他们在相关
证据已显示在屏幕上的情况下阻止或允许它。
`safe-galaxy` 以 Linux 为优先,现在默认采用严格的、失败即关闭的行为。
每个安装阶段都在受防护的执行路径下运行,获取阶段只有在计划明确
要求时才可能使用网络,并且重放/安装阶段
在命令级别必须是离线的。下载的存档文件在
最终重放运行之前会被暂存并
扫描。暂存的发现随后可以映射到
`allow`、`warn`、`ask` 或 `block`,持久的交互式批准存储在
托管的用户状态中,使用按管理器、版本和语义风险范围划分的键。
重复安装会重用
来自本地缓存的以构件哈希为键的分析结果,前提是存档
内容和分析配置文件没有发生改变。
## 安装
使用 Cargo 从源码安装:
```
cargo install --git https://github.com/berylliumsec/safe-galaxy --locked
```
验证二进制文件:
```
sg --help
```
如果你更倾向于在检出目录中运行而不是全局安装,请使用:
```
cargo run -- --help
```
Linux 发布版 tarball 还附带提供了 `sg` 和 `safe-galaxy` 二进制文件以及
基准测试入门资产。
## 快速开始
分析当前目录树:
```
sg analyze .
```
检查本地包路径:
```
sg assess path tests/fixtures/corpus/suspicious-js
```
针对包管理器运行安装计划:
```
sg install -m pip -p ./.venv/bin/python requests==2.32.3
```
如果你想要基准测试页面,请访问
`https://safe-galaxy.berylliumsec.com`。
## 功能特性
- 分析包或项目目录树的元数据信号:
- `package.json` 安装钩子和入口点
- `pyproject.toml` 构建后端和脚本
- 原生构件,如 `.so`、`.dll`、`.dylib`、`.node` 和 `.exe`
- 解析轻量级的原生二进制元数据以获取 ELF 优先的语义信息:
- 导入和导出
- 节和构造函数/init-array 标记
- 动态加载器引用
- 有界的可打印字符串
- 使用 Tree-sitter 解析 Python、JavaScript、TypeScript 和 TSX 源码
- 使用 AST 访问器和全文件规范化匹配扫描 JavaScript/TypeScript 源码,这样即使是经过压缩或重新格式化的成员链访问也能浮现出来
- 在能力提取之前,当明显的嵌入式 JavaScript 十六进制/base64 载荷、`atob(...)` 和 `String.fromCharCode(...)` 载荷与动态执行接收器或混淆标记配对时,对其进行解码
- 将 `package.json` 元数据视为第一类证据,用于:
- 生命周期钩子
- 直接 URL 支持的依赖项
- 发布自动化
- 面向持久化的命令
- 浮现面向能力的信号,例如:
- 进程执行
- Shell 执行
- 网络访问
- 环境访问
- 携带敏感信息的认证或环境素材访问
- 宿主机指纹识别
- 直接 URL 依赖检索
- 混淆的加载器行为
- 动态代码执行
- 原生库加载
- 文件系统写入
- 敏感路径访问
- 派生语义发现,例如:
- 安装钩子执行
- 出站网络能力
- 回传意图
- 凭证窃取意图
- 混淆的执行链
- 原生二进制进程或网络能力
- 本地 IPC 活动
- 重放/安装阶段期间归因于包的外部网络活动
- 敏感文件读写
- 已确认的跨源运行时行为
- 为以下项生成安装计划:
- `pip`
- `uv`
- `pnpm`
- 无需安装重放即可评估确切的依赖版本,适用于:
- 使用 `npm pack` 获取的 Node 包
- 使用 `python -m pip download --no-deps` 获取的 Python 包
- 执行受防护的安装流程:
- 沙箱化的 `resolve`
- 沙箱化的 `prefetch`
- 暂存的存档提取及分析
- 可选的终端审计审查
- 沙箱化的离线 `install`
- 运行操作检查和维护:
- `sg doctor`
- `sg gc`
- `sg mcp`
## 命令参考
分析源码目录树:
```
sg analyze .
```
从源码分析:
```
cargo run -- analyze .
```
输出 JSON:
```
sg --format json analyze .
```
评估本地包路径或存档:
```
sg assess path .
sg -f json assess path tests/fixtures/corpus/suspicious-js
```
在不重放安装的情况下评估确切的依赖版本:
```
sg assess dependency --ecosystem python --name requests --version 2.32.3
sg assess dependency --ecosystem node --name kleur --version 4.1.5
```
选择特定的 Python 解释器进行包获取:
```
sg assess dependency -e python -p ./.venv/bin/python -n requests -v 2.32.3
```
构建安装计划:
```
sg plan -m pip requests==2.32.3
sg plan -m uv requests==2.32.3
sg plan -m pnpm -r .
```
在没有配置文件的情况下运行受防护的安装:
```
sg install -m pip -p ./.venv/bin/python requests==2.32.3
```
在没有配置文件的情况下运行交互式受防护的安装:
```
sg -i install -m pip -p ./.venv/bin/python requests==2.32.3
```
最常用的标志提供了常见的短别名:
`-i` = `--interactive`,`-c` = `--config`,`-b` = `--best-effort`,
`-f` = `--format`,`-m` = `--manager`,`-p` = `--python`,`-a` = `--audit`,
`-s` = `--allow-scripts`。
安装命令垫片(shims),以便正常的包管理器安装命令通过
`safe-galaxy` 进行路由:
```
sg -i shim install
export PATH="$HOME/.local/bin:$PATH"
```
`sg shim install` 会将当前的 `--config`、`--interactive` 和
`--best-effort` 设置固化到生成的包装器中,因此在安装垫片时,请使用你希望正常的 `pip`、`uv` 或 `pnpm` 使用所继承的默认值。
当 Python virtualenv 处于活动状态时,`sg shim install` 会定位到该环境的
`bin/` 目录,因此 `pip` 拦截可以在活动环境内工作,并且
它会保留原始启动器,以便在执行 `sg shim uninstall` 时进行恢复。
之后,正常的安装命令就会被拦截:
```
pip install requests==2.32.3
uv pip install requests==2.32.3
pnpm install
```
垫片可包装:
- `pip install ...`
- `pip3 install ...`
- `uv pip install ...`
- `pnpm install ...`
非安装命令(例如 `pip list`、`uv venv` 或 `pnpm run`)会被委派
给垫片背后的真实工具。
移除已安装的垫片:
```
sg shim uninstall
```
在垫片移除后,卸载已安装的 `sg` / `safe-galaxy` 二进制文件:
```
sg uninstall
```
为当前宿主机运行严格的预检:
```
sg doctor
```
清理临时缓存状态:
```
sg gc
sg gc --all
```
通过 syscall 追踪运行受防护的安装:
```
sg --interactive install --audit --manager pip --python ./.venv/bin/python requests==2.32.3
```
对于 `pip`,目标解释器必须支持 `pip install --dry-run`。如果
系统 Python 附带的是较旧版本的 `pip`,请将 `--python` 指向更新的环境,或者
先在那里升级 `pip`。
当高级配置定义了运行时批准路径时,为受防护的安装启用运行时批准:
```
sg --config ./examples/advanced-config.yaml install --manager pip --runtime-approval --python ./.venv/bin/python requests==2.32.3
```
从 YAML 或 JSON 加载高级策略:
```
sg --config ./examples/advanced-config.yaml analyze .
sg --config ./examples/advanced-config.yaml install --manager pip --python ./.venv/bin/python requests==2.32.3
```
当你希望在本地开发期间绕过严格的失败即关闭
检查时,显式允许尽力而为(best-effort)模式:
```
sg --best-effort install --manager pip --python ./.venv/bin/python requests==2.32.3
```
运行 stdio MCP 服务器:
```
sg mcp
sg -c ./examples/advanced-config.yaml mcp
```
向 Codex 或 Claude Code 注册 MCP 服务器:
```
sg mcp register codex
sg mcp register claude-code
sg -c ./examples/advanced-config.yaml mcp register codex
```
## 评估契约
`sg assess` 在 JSON 模式下发射 schema 版本 `safe-galaxy.assessment-result.v2`。
`report` 载荷包含:
- `subject`
- `risk_level`:`low`、`medium` 或 `high`
- `recommended_action`:`allow`、`review` 或 `block`
- `attention_level`
- `posture`
- `summary`
- `reasons`
- `evidence`
- `environment_variables`:在静态可恢复时的确切环境变量名
- `network_endpoints`:字面 URL 或观察到的运行时端点
- `sensitive_paths`:在可恢复时的确切敏感路径字符串
- `secret_indicators`:确切的无值秘密标识符,如环境变量名或认证标记
- `semantic_ids`
- `artifact_count`
- 请求 `include_raw_report` 时的 `raw_report`
`risk_level` 是有意从现有的语义关注级别
和策略决策中派生出来的,而不是一个单独的不透明分数:
- `low-attention` 加 `allow` => `low`
- `review` 关注级别或 `warn`/`ask` => `medium`
- `high-attention` 或 `block` => `high`
确切的依赖评估是非变异的。它获取包存档,
暂存它们,分析它们,并在不运行受防护的
安装重放的情况下应用策略阈值。
## MCP 接口
`sg mcp` 提供两个 stdio MCP 工具:
- `assess_dependency`
- 输入:`ecosystem`、`name`、`version`、可选的 `python_path`、可选的 `include_raw_report`
- `assess_path`
- 输入:`path`、可选的 `include_raw_report`
这两个工具都返回与 `评估契约` 形状相同的结构化 JSON。
服务器级别的策略在进程启动时通过正常的全局
`--config` 标志加载一次。
## 客户端入门
`safe-galaxy` 是 MCP 优先的。标准用户流程是:
1. 使用 `cargo install --git https://github.com/berylliumsec/safe-galaxy --locked` 安装 `sg`,或使用 Linux 发布版 tarball。
2. 验证 `sg --help` 是否有效。
3. 使用 `sg mcp register ` 注册服务器,或手动复制匹配的模板。
4. 重启客户端或编辑器。
5. 要求代理调查一个包。
在安装后,AI 代理可以执行的最快且最简单的路径
是让 `sg` 为你编写客户端配置:
```
sg mcp register codex
sg mcp register claude-code
```
`sg mcp register codex` 会更新 `~/.codex/config.toml`。
`sg mcp register claude-code` 会更新当前项目中的 `.mcp.json`。
这两个命令都会写入一个 `safe-galaxy` MCP 条目,并保留不相关的现有
客户端配置。
如果你倾向于手动注册,代码库和 Linux 发布包
在 `examples/mcp/` 下包含了可随时复制的模板。除非
你确定 `sg` 位于客户端的 `PATH` 中,否则默认使用绝对路径
模板。
Codex:
- Codex CLI 和 Codex IDE 扩展共享 `~/.codex/config.toml`。
- 使用以下之一:
- `examples/mcp/codex/config.absolute.toml`
- `examples/mcp/codex/config.path.toml`
Claude Code:
- 使用以下之一:
- `examples/mcp/claude-code/mcp.absolute.json`
- `examples/mcp/claude-code/mcp.path.json`
- 将选定的 JSON 模板复制到项目根目录中的 `.mcp.json`。
注册命令支持相同的高级启动形式。例如,
这会写入一个在启动时加载策略的 Codex 条目:
```
sg -c ./examples/advanced-config.yaml mcp register codex
```
如果你希望模型更可靠地优先选择此服务器,请将
`examples/mcp/project-instructions.md` 中的代码片段添加到你的项目指导文件中。
Codex 配置示例:
```
[mcp_servers.safe-galaxy]
command = "/ABSOLUTE/PATH/TO/sg"
args = ["mcp"]
```
Claude Code 配置示例:
```
{
"mcpServers": {
"safe-galaxy": {
"command": "/ABSOLUTE/PATH/TO/sg",
"args": ["mcp"]
}
}
}
```
要在服务器启动时加载策略文件,请将参数更改为:
```
--config /ABSOLUTE/PATH/TO/advanced-config.yaml mcp
```
### 代理如何发现它
客户端启动 `sg mcp` 后,它会通过
MCP `tools/list` 请求服务器的工具目录。这就是代理了解到 `-galaxy` 暴露了
`assess_dependency` 和 `assess_path` 的方式。
MCP 是产品界面。技能包装器是可选的,Codex 或 Claude 调用
服务器并不需要它。
### 提示示例
一旦配置了 MCP 服务器,像这样的提示应该可以工作:
- `Investigate the npm package kleur version 4.1.5 and tell me whether I should allow, review, or block it.`
- `Investigate the Python package requests version 2.32.3 and summarize the evidence behind the recommendation.`
- `Analyze this local package path and tell me if it deserves review before install.`
- `Use safe-galaxy to assess this dependency and explain the risk level, recommended action, and key findings.`
## 发布构建
已合并的发布 PR 会将 Linux tarball 和校验和发布到
`main` 分支工作流
[`.github/workflows/release-linux.yml`](.github/workflows/release-linux.yml) 中的
`v` GitHub Release。
该工作流从 `Cargo.toml` 中读取 `package.version`。要从 PR 中发布新版本,
请在合并前在 `Cargo.toml` 中升级版本。
要使用 Cargo 安装而不使用 crates.io:
```
cargo install --git https://github.com/berylliumsec/safe-galaxy --locked
sg --help
```
稍后要移除已安装的二进制文件:
```
sg shim uninstall
sg uninstall
```
你仍然可以在本地复现 Linux 发布打包:
```
bash scripts/release/package-linux.sh v0.1.0
```
这会创建包含以下内容的 `dist/` 输出:
- 名为 `safe-galaxy--.tar.gz` 的 tarball
- 解压后的 `safe-galaxy` 和 `sg` 二进制文件
- `examples/advanced-config.yaml`,用于路径繁重的配置
- `examples/mcp/`,包含 Codex 和 Claude 入门模板
- `checksums.txt`,包含二进制文件和 tarball 的 SHA-256 摘要
验证本地构建:
```
sha256sum -c dist/checksums.txt
tar -xzf dist/safe-galaxy-v0.1.0-x86_64-unknown-linux-gnu.tar.gz -C /tmp
/tmp/safe-galaxy-v0.1.0-x86_64-unknown-linux-gnu/sg --help
```
将打包好的发布版安装到 `~/.local/bin`:
```
bash scripts/release/install-local.sh dist/safe-galaxy-v0.1.0-x86_64-unknown-linux-gnu.tar.gz
~/.local/bin/sg --help
```
安装程序还会将入门资产复制到:
```
${XDG_DATA_HOME:-$HOME/.local/share}/safe-galaxy/examples/mcp
```
如果需要,将 `~/.local/bin` 添加到 `PATH`:
```
export PATH="$HOME/.local/bin:$PATH"
```
## 配置
配置是可选的。正常流程是:
- `sg install ...`
- `sg --interactive install ...`
- `sg --interactive install --audit ...`
仅在你需要高级行为(例如)时才使用配置文件:
- 运行时批准路径
- 沙箱读/写/环境覆盖
- 高级策略调整或特定于项目的共享包覆盖
高级配置示例(`examples/advanced-config.yaml`):
```
best_effort: false
mode: interactive
analysis:
max_file_size_bytes: 262144
ignored_directory_names:
- .git
- target
- node_modules
- dist
- build
sandbox:
network_default: controlled
read_allow:
- ${PROJECT_ROOT}
- ${CACHE_DIR}
write_allow:
- ${PROJECT_ROOT}
- ${CACHE_DIR}
allow_protected_paths:
- ${HOST_HOME}/.aws
deny_env:
- SSH_AUTH_SOCK
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- GITHUB_TOKEN
audit:
mode: optional
runtime_approval:
mode: optional
paths:
- ${HOST_HOME}/.ssh
- ${HOST_HOME}/.aws
prompt_on:
- open-read
- open-exec
- dir-open
decision_scope: session
policy:
semantic_thresholds_by_attention:
low_attention: allow
review: ask
high_attention: ask
semantic_threshold_overrides:
semantic.external-egress: block
thresholds:
install_hooks: ask
native_artifacts: ask
high_severity: ask
medium_severity: warn
low_severity: allow
package_overrides:
pip:trusted-package@1.2.3|semantic:semantic.network-capable-package:
decision: allow
note: approved interactively
```
默认值:
- `mode: fail-closed`
- `best_effort: false`
- `sandbox.network_default: controlled`
- 受保护的宿主机机密路径默认拒绝,仅在 `--interactive` 模式下提供单次运行批准
- 除非明确请求,否则禁用审计和运行时批准
- 托管批准在存在时从 `${XDG_STATE_HOME:-$HOME/.local/state}/safe-galaxy/approvals.yaml` 加载
当 `best_effort` 为 `false` 时,缺少 `bwrap`、缺少包管理器
可执行文件、缺少审计/运行时批准依赖,或不支持
Landlock,都会在执行开始前中止安装。
## 策略行为
- `allow`:继续,不执行额外操作。
- `warn`:继续,并打印从暂存分析中收集到的原因。
- `ask`:在 `interactive` 模式下需要交互式终端;持久的批准会写入托管用户状态。
- `block`:在沙箱重放运行之前停止安装。
策略评估发生在暂存构件提取之后以及最终的
离线安装阶段之前。语义发现现在驱动默认的审查路径,
而遗留的严重性阈值在没有语义发现
存在时仍作为后备。持久化的批准由管理器、规范化的包键、
包版本以及触发提示的稳定语义发现 ID 集作为键,
并且它们按用户和项目根目录存储在托管状态中。
交互式审查呈现明确的风险事实,而不是安全/恶意的判决,
并且每当存在审查或高关注度发现时,默认突出显示 `Block`。
## 沙箱策略
`safe-galaxy` 现在通过显式绑定挂载来构建沙箱文件系统,而不是
将整个宿主机根目录以只读方式绑定。因此,`read_allow` 和 `write_allow`
控制着沙箱阶段真实的文件系统可见性。
- 相对路径从 `${PROJECT_ROOT}` 解析。
- 支持的路径 token 有 `${PROJECT_ROOT}`、`${CACHE_DIR}`、`${TMPDIR}`、`${SANDBOX_HOME}` 和 `${HOST_HOME}`。
- 如果可写路径尚不存在,则会按需创建。
- `allow_protected_paths` 是针对精确内置受保护根目录(如 `${HOST_HOME}/.ssh`)的显式逃生舱;父目录和非目录路径将被拒绝。
- `deny_env` 在沙箱运行时应用其所需覆盖(例如 `HOME` 和 `TMPDIR`)之前过滤宿主机环境。
- 安装流程仍然需要访问项目根目录和缓存目录;移除其中任何一个都会在执行开始前失败。
- `${HOST_HOME}` 下常见的携带凭证的路径默认被阻止。在每个受防护的阶段之前,`safe-galaxy` 会检查有效的挂载计划是否会暴露其中一个根目录。在 `interactive` 模式下,它会针对当前运行的每个路径提示一次;在交互模式之外,除非明确允许了确切的根目录,否则它会失败并关闭。
- 仍然被阻止的受保护根目录也会被空文件或目录覆盖层屏蔽,作为纵深防御,即使更广泛的绑定挂载(如工具前缀)会暴露它们。
- 内置的受保护集涵盖了 SSH、云 CLI、容器、Kubernetes、Git、Terraform、Cargo、Ruby、npm、pip、Poetry 和 `.env` 风格的用户机密。
- 在受支持的 Linux 内核上,最终的安装重放还会应用从相同读/写策略派生的 Landlock 路径规则,在发生变异的子进程内增加内核级别的文件系统防护。
- 每次安装运行现在都会在 `${CACHE_DIR}/runs/` 下获得自己的沙箱工作区,因此像沙箱主目录和 tmp 目录这样的临时状态不会跨运行重用。
- 会改变相同共享缓存或相同目标环境的并发安装,会在执行开始前使用宿主机端咨询锁进行串行化。
- `resolve` 和 `prefetch` 阶段现在在与最终重放相同的受防护隔离模型中运行,带有特定于阶段的可写挂载和显式网络策略验证。
- `uv` 阶段在沙箱内默认使用 `UV_LINK_MODE=copy`,以避免在隔离的缓存/工作区布局中出现跨文件系统的硬链接问题。
- `sandbox.audit.mode: disabled|optional|required` 控制沙箱阶段是否被 `strace` 包装,并在 `${CACHE_DIR}/audit//` 下写入 syscall 追踪。
- 审计追踪当前包含 `file`、`process` 和 `network` syscall。这是有意设为选择性加入(opt-in)的,因为它会增加可衡量的开销。
- 当审计审查运行时,`safe-galaxy` 首先将安装重放到一个临时目标中,然后呈现一个终端审查,其开头为:
- `Attention level`
- `Confirmed across sources`
- `Observed during install`
- `Present in the package`
- `Observed runtime details`
- 交互式审查和受保护机密批准屏幕现在使用 `ratatui` 替代屏幕界面,带有决策窗格、可滚动的详细信息窗格以及安全的 `Esc`/`q` 取消操作(回退到 `Block`)。UI 可以绑定到 `stdout`、`stderr` 或 `/dev/tty`,因此重定向 stdout 不会抑制审查屏幕。
- 默认的终端审查现在隐藏了低级别的追踪计数器和其他空白部分。它专注于能够改变开发者决策的浮现行为,并且当观察到敏感读取、外部网络操作、拒绝或提权执行时,它会包含确切的预览以及下方的详细表格。
- 语义发现行现在保持当前的节布局,但最多显示两行优先级证据。源路径证据被渲染为短尾部加上独立的完整文件系统路径,条目之间有分隔线,因此终端可以干净地链接路径,开发者可以看到具体观察到的动作、进程、端点或源位置,而无需在较低的表格中寻找。
- 回环和 unix 套接字监听器活动作为本地 IPC 上下文仍然可见,但它与非本地网络发现保持分离。
- 原始 syscall 计数、完整的追踪文件和审计 JSON 仍然存在于磁盘上的 `${CACHE_DIR}/audit//` 中,但它们不再打印在默认的交互式审查中。
- 每个审计阶段还会在 `*.summary.json` 处写入一个稳定的 JSON 摘要,使用 schema 版本 `safe-galaxy.audit-summary.v3`。
- 敏感路径发现仅针对观察到或被拒绝的访问发出,而不针对普通的缺失文件探测(例如针对包管理器配置文件的 `ENOENT` 检查)发出。
- 原始的包管理器 stdout/stderr 被捕获在 `${CACHE_DIR}/runs//phase-output/` 下。成功的阶段默认保持安静;失败时 `safe-galaxy` 会打印简短的摘录并指向完整的日志。
- 安装进度现在会打印共享缓存扫描、暂存构件分析、审计审查重放和每个受防护阶段的启动标记,因此长时间运行的 `resolve` 或 `prefetch` 工作在完成之前是可见的。
- 分阶段的安装分析现在会记录每个构件的推断 `artifact_form` 和 `behavior_class`,并且交互式审查会在语义发现之前打印这些配置文件。内置的配置文件当前可区分纯 JS、纯 Python wheels、源码构建、原生扩展、浏览器自动化、二进制供应商、模型/数据包和服务 SDK。
## 运行时批准
`safe-galaxy` 可以选择在静态沙箱之上分层运行时路径批准:
- `runtime_approval.mode: disabled|optional|required` 控制代理是关闭、尽力而为还是失败即关闭。
- `runtime_approval.paths` 列出了仅在运行时批准激活时才应可见的敏感根目录。
- `prompt_on` 支持 `open-read`、`open-exec` 和 `dir-open`。
- v1 决策范围是 `session`,因此批准仅为当前安装运行缓存。
- 运行时批准提示和 `runtime-approval.jsonl` 审计条目包含人类可读的原因,说明为什么请求的路径受到限制。
- 在你回答运行时批准提示后,`safe-galaxy` 会在沙箱阶段继续或展开时打印简短的状态行。
- 受防护的重放和审计子进程将 stdout/stderr 捕获到日志,并且不继承终端 stdin,因此交互式批准保留在 `safe-galaxy` 中,并且包管理器提示不能接管 Shell。
- `safe-galaxy` 还会在安装命令退出之前恢复调用者 tty 状态,因此受防护的子进程不能在提示或阶段失败后将你的 Shell 保留在原始模式。
- 该代理仅限 Linux 并使用 `fanotify`,因此它需要以 `root` 身份运行 `safe-galaxy`,或为隐藏的代理辅助程序使用无密码的 `sudo -n`。
- 如果启用了运行时批准,`safe-galaxy` 现在会在执行开始前预检权限和终端要求。
- 如果运行时批准为 `required` 或传递了 `--require-runtime-approval`,当代理、权限边界或终端不可用时,安装会在任何受防护阶段之前中止。
- 当同时启用沙箱审计时,运行时批准提示和决定也会写入 `${CACHE_DIR}/audit//runtime-approval.jsonl`。
### 端到端流程
当你在启用受防护阶段和运行时批准的情况下运行 `sg install` 时,
完整流程是:
1. `safe-galaxy` 构建安装计划,验证先决条件,并为安装目标和共享缓存获取宿主机端锁。
2. 它暂存安装构件,运行静态分析,并在任何变异重放开始之前应用策略。
3. 对于每个受防护阶段,它会在 `${CACHE_DIR}/runs//` 下创建一个每次运行的工作区,构建显式的 bubblewrap 挂载计划,并将子进程的 stdout/stderr 捕获到 `phase-output/*.stdout.log` 和 `phase-output/*.stderr.log` 中。
4. 受保护的宿主机机密根目录和运行时批准监视的根目录被单独处理:
`allow_protected_paths` 是内置受保护根目录的显式运行前逃生舱,而 `runtime_approval.paths` 启用对阶段期间确切监视根目录的每次访问批准。
5. 如果运行时批准处于活动状态,父 `safe-galaxy` 进程会启动一个短路径主管套接字,派生特权 Linux 代理,并为自己保留终端。受防护的子进程没有交互式 stdin,在它们自己的会话中运行,因此不能拥有或破坏调用者 TTY。
6. 当监视路径被触碰时,代理会发出权限请求,其中包含具体路径、访问类型、进程元数据,以及该路径受限的目录原因。父进程呈现 Ratatui 审查屏幕并默认为Block`。
7. `Allow once` 仅授予该会话范围的批准桶;`Block`、`Esc`、中断或超时会拒绝访问。拒绝时,受防护的子进程会看到访问失败,并且阶段以非零状态退出。
8. 决定之后,`safe-galaxy` 打印一条简短的交接行,完成阶段的展开或继续,在命令退出之前恢复调用者 tty 状态,并为下一个命令保留 Shell 交互。
### 磁盘上的构件
- `${CACHE_DIR}/runs//phase-output/` 包含每个受防护阶段的原始包管理器 stdout/stderr。
- `${CACHE_DIR}/audit//runtime-approval.jsonl` 在启用沙箱审计时记录运行时批准提示和决定。
- `${CACHE_DIR}/audit//*.summary.json` 在启用审计时包含重放阶段的稳定审计摘要。
### 在受保护路径和运行时批准之间做出选择
- 当你希望确切的内置宿主机机密根目录在整次运行中预先暴露时,请使用 `sandbox.allow_protected_paths`。
- 当你希望路径默认保持拒绝状态,并且仅在显式运行时决定后才变得可读或可遍历时,请使用 `runtime_approval.paths`。
- 你可以在同一配置中为不同的根目录同时使用两者,但它们
解决不同的问题:一个是挂载时异常,另一个是
每次访问的关卡。
有关本地端到端路径提示演示,请使用
`examples/runtime-approval/` 中的示例包,并遵循
[`examples/runtime-approval/README.md`](examples/runtime-approval/README.md)。
对于你可以立即分析并可选择在启用审计的情况下
通过受防护的安装进行重放的本地 Node 和 Python 能力演示,请使用
`examples/detection-demo/`,并遵循
[`examples/detection-demo/README.md`](examples/detection-demo/README.md)。
## 分析缓存
暂存的构件分析缓存在 `${CACHE_DIR}/analysis-cache/` 下,使用:
- 存档内容的 BLAKE3 哈希
- 从分析配置和分析器版本派生的分析配置文件哈希
如果两者都匹配,分阶段的安装流程将重用缓存的报告,而不是
再次运行元数据和 AST 提取。存档仍然会为当前
安装流程进行暂存,但未更改的构件会跳过昂贵的扫描工作。
## 开发者指南
发布、基准测试、发布构建和终端演示位于
[developer.md](developer.md) 中。
## JSON 报告
- `sg analyze --format json` 发射 `safe-galaxy.analyze-report.v4`
它现在包含用于过大或不可读源及跳过的原生二进制文件的 `report.skipped_inputs`。
- `sg install --format json` 发射 `safe-galaxy.install-report.v6`
- `sg doctor --format json` 发射 `safe-galaxy.doctor.v1`
- `sg gc --format json` 发射 `safe-galaxy.gc-report.v1`
- 每阶段审计摘要发射 `safe-galaxy.audit-summary.v3`
## 安全模型
- 支持的平台:仅限 Linux。
- 默认姿态:失败即关闭。
- `--best-effort` 是在严格先决条件不可用时用于本地调试的显式逃生舱。
- `--best-effort` 不会绕过受保护的宿主机机密强制执行;如果直接回退会暴露受保护的根目录,除非明确允许了确切的根目录,否则运行仍会被阻止。
- 获取阶段只有在计划要求且沙箱网络策略允许时才可能使用网络。
- 重放/安装阶段在命令级别必须是离线的。
- 运行时批准是选择性加入的,并且由于依赖于 `fanotify`,仍然仅限 Linux。
## 支持矩阵
- `pip`:受防护的 resolve、受防护的 fetch、暂存的构件分析、可选的审计审查、受防护的离线 replay
- `uv`:受防护的 resolve、受防护的 fetch/缓存预热、暂存的构件分析、可选的审计审查、受防护的离线 replay
- `pnpm`:受防护的基于 lockfile 的项目安装、受防护的 fetch、获取存档时的暂存构件分析(如存在)、可选的审计审查、受防护的离线 replay
- 宿主机操作系统:仅限 Linux
## 下一步计划
- 将 AST 提取扩展为规范化的能力图
标签:API接口, Bubblewrap, DNS 解析, Landlock, Node.js包管理, pip安全, pnpm安全, Python包管理, Rust, TLS抓取, uv包管理器, 依赖安全, 包管理器安全, 可视化界面, 威胁情报, 安全防护, 安装时检测, 开发者工具, 沙箱, 系统调用追踪, 网络流量审计, 软件安全, 运行时监控, 通知系统, 错误基检测, 零信任安装, 静态代码分析, 风险拦截