SAFE 对研究工件中的 Semgrep 和 Trivy 发现执行受控的、仓库感知的安全评估。
它支持两个独立的分类任务:直接的 binary 预测(SECURITY_RELEVANT 或 NON_SECURITY)以及详细的 multiclass 上下文分类法(三个标签 — 参见 三个标签)。每个任务都可以在零样本或代理模式下运行。
它仅需要:
artifact_id 对应一个研究工件文件夹。artifact_id 键控的论文 PDF/文本集合。它不会针对任何带标签的评估数据进行训练或调优。带标签的数据仅在推理之后用于评估预测,分类器永远不会看到这些数据。SAFE 从不执行工件代码;仓库文本被视为不可信的证据,而非指令。
此版本包含完整的 safe_audit 源代码、CLI 和测试,以及一个自包含的 demo/,其中包含三个完全合成的示例工件,您可以在无需任何外部数据的情况下端到端运行。它排除了论文中使用的真实研究工件语料库、真实标签和评估发现。
快速开始: 在 安装 之后,运行 演示 — 它无需任何数据设置即可立即运行。config.example.yaml(稍后在 配置 中介绍)是您自己的发现/工件的模板,在您编辑之前不会运行。
cd path/to/safe-artifact-auditor
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
设置 API 密钥:
export OPENAI_API_KEY="your-key"
对于组织 LiteLLM 代理,请改用 config.litellm.example.yaml — 其中包含内联注释。凭据和自定义标头值从环境变量中读取,绝不会存储在 SAFE 配置或结果文件中。
demo/ 包含三个小的、完全合成的示例工件 — 均不源自或对应于任何真实的已发表研究工件 — 每个对应一个分类法标签,以便审阅者无需任何外部数据即可演练完整流程:
demo-contextual-risk/ — 一个玩具联邦学习检查点聚合器,使用 torch.load 反序列化从调用方提供的 URL 下载的检查点。不可信的、网络来源的输入到达不安全的反序列化汇点,SAFE 预期将其分类为 CONTEXTUAL_RISK。demo-hardening-recommendation/ — 一个玩具基准测试框架,对全部硬编码为 Python 字面量的命令行运行 subprocess.run(..., shell=True),没有调用方控制的输入。SAFE 预期将其分类为 HARDENING_RECOMMENDATION:shell 模式是真实的且值得标记,但没有任何外部内容可以到达或影响它。demo-false-positive/ — 一个测试夹具生成器,固定使用较旧的 Pillow 版本,并带有假设的解压缩炸弹公告。该代码仅创建新的内存图像,从不打开外部数据,因此公告的实际代码路径永远不会被到达。SAFE 预期将其分类为 FALSE_POSITIVE。demo/findings.csv 为每个工件保存一条发现,demo/demo-zero-shot.yaml / demo/demo-agentic.yaml 是可直接运行的配置(artifact_root: . 相对于配置文件解析,因此请从 demo/ 内部运行):
cd demo
safe-audit run --config demo-zero-shot.yaml
safe-audit run --config demo-agentic.yaml
结果分别位于 demo/runs/demo-zero-shot/ 和 demo/runs/demo-agentic/ 中(参见 输出)。
CONTEXTUAL_RISKHARDENING_RECOMMENDATIONFALSE_POSITIVE不使用额外的类别,也不使用确定性的标签更改规则。工件自身代码中已记录的、隔离的研究/安全机制被分类为 HARDENING_RECOMMENDATION,因为即使隔离限制了实际可利用性,底层实践仍然是真实的。
SECURITY_RELEVANT:有效的上下文风险或加固问题,包括有意的、隔离的安全研究行为。NON_SECURITY:虚假的、不匹配的、不适用的、缺失的或可证明未使用的受影响功能发现。评估器还会从多类预测中派生二元视图:FALSE_POSITIVE 变为 NON_SECURITY;所有其他多类标签变为 SECURITY_RELEVANT。直接和派生的二元结果保持明确分离。
project/
├── config.yaml
├── data/
│ └── findings.csv
└── artifacts/
├── artifact_001/
├── artifact_002/
└── artifact_003/
映射是精确的:artifact_id = artifact_001 解析为 artifacts/artifact_001/。
必需的 CSV 列:
artifact_id;tool;finding_id
可选列:
artifact_id;tool;finding_id;category;severity_raw;file;line;message;package;version;cwe;cvss;scanner_applicable
初始的未命名索引列将被忽略。其他列由输入模型保留。
示例:
artifact_id;tool;finding_id;category;severity_raw;file;line;message;package;version;cwe;cvss;scanner_applicable
artifact_001;semgrep;python.lang.security.audit.subprocess-shell-true;code;HIGH;src/probe.py;42;Shell command uses shell=True;;;;CWE-78;;yes
artifact_002;trivy;DEMO-CVE-0001;dependency;HIGH;;;Affected package (illustrative, not a real CVE);example-lib;1.2.0;CWE-502;8.1;yes
scripts/run_scanners.py 和 scripts/build_findings_csv.py 使用 Semgrep 和 Trivy 直接从您自己的代码生成上述 findings.csv 和工件布局。
安装 Semgrep(在任何操作系统上均相同,包括 Linux):
pip install semgrep
在 Linux 上安装 Trivy — 可以使用 apt 仓库(Debian/Ubuntu):
sudo apt-get install wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
或使用官方安装脚本,该脚本适用于任何 Linux 发行版,并将二进制版本安装到 /usr/local/bin(除该目录需要 sudo 外,无需 root 包):
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
在继续之前,请验证两者都在 PATH 上:
semgrep --version
trivy --version
然后在 artifact_root/ 下为每个工件布置一个目录,并运行:
python scripts/run_scanners.py artifact_root --output scan-output
python scripts/build_findings_csv.py scan-output --output data/findings.csv
第一个命令对每个工件目录运行 Semgrep 和 Trivy(漏洞和密钥扫描),并保存原始扫描器 JSON。第二个命令将该 JSON 解析为 SAFE 兼容的 findings.csv(列与 输入结构 匹配;file 相对于每个工件目录报告)。向任一脚本传递 --skip-semgrep/--skip-trivy 以仅运行一个工具。run_scanners.py 上的 --config 固定特定的 Semgrep 规则集,而不是默认的 auto,后者很方便但无法可复现地固定。
本节用于针对您自己的发现 CSV 和工件文件夹运行 SAFE(参见上面的 输入结构)。如果您只想看到 SAFE 运行,请改用 演示 — 下面的 config.example.yaml 是模板,不能按原样运行。
cp config.example.yaml config.yaml
然后编辑 input_csv 和 artifact_root(以及可选的 paper_root)以指向您自己的数据,然后再运行。
关键设置:
model / provider:精确的 OpenAI 模型标识符(或 LiteLLM 别名),以及 openai 或 litellm(带代理 URL 和凭据环境变量名称)。analysis_mode:zero_shot 或 agentic。classification_task:binary 或 multiclass;与 analysis_mode 无关。max_agent_steps:仅在代理配置中需要。max_workers / max_output_tokens / max_schema_retries:并发数、每个响应的输出上限,以及针对架构无效响应的模型调用重试预算。默认模型是 gpt-5.6-sol。如果可用性、成本或延迟要求不同,请明确更改。
safe-audit run --config config.yaml
或者不安装控制台命令:
PYTHONPATH=src python -m safe_audit.cli run --config config.yaml
如需针对包含的合成数据进行可运行的匹配比较,请参见 演示(demo/demo-zero-shot.yaml 和 demo/demo-agentic.yaml)。它们仅在 analysis_mode 和 run_name 上有所不同。零样本模式对基础证据进行一次模型调用。代理模式从相同的证据开始,并可能在返回相同的结构化结果之前调用有界的只读仓库工具。
runs/<run_name>/
├── config.resolved.yaml
├── run_metadata.json
├── summary.json
├── results.jsonl
├── results.csv
├── profiles/
├── evidence/
├── raw/<finding_uid>/
│ ├── 0001-request.json
│ ├── 0001-response.json (或 0001-error.json)
│ └── final-output.txt
└── logs/
├── events.jsonl
├── result_attempts.jsonl
└── run_sessions.jsonl
results.csv 用于分析。results.jsonl 保留完整的结构化记录。证据和原始模型输出支持审计和错误分析。两者都是规范性的:它们仅包含每个发现的最新记录,而 logs/result_attempts.jsonl 是仅追加的,并保留每个历史结果。
在恢复时,SAFE 首先使用当前的严格解析器重新解析每个失败发现的已保存原始响应;无需 API 调用即可恢复唯一有效的分类。只有无法恢复的失败才会被安排进行模型推理。对于部分完成运行的仅失败项继续,请保持相同的 output_root 和 run_name,并设置:
resume: true
resume_policy: failed_only
要针对带标签的金标准 CSV(包含 security_label 或 security_class 列)评估预测:
safe-audit evaluate --results runs/<run_name>/results.jsonl --gold GOLD.csv --output runs/<run_name>/evaluation.json
PYTHONPATH=src python -m unittest discover -s tests -v
测试套件使用假提供程序,因此不需要 API 密钥。
resume / resume_policy:incomplete 重试失败项、缺失工件和未尝试的发现;failed_only 仅重试失败项,同时保留已记录的成功项。cost:可选的实时成本核算和 max_run_cost_usd 终止条件。