manticore-projects/aurscan

GitHub: manticore-projects/aurscan

aurscan 是一款利用大模型和静态规则在构建前自动扫描 AUR 包以拦截恶意代码的安全工具。

Stars: 70 | Forks: 7

# 🛡️ aurscan **在构建之前,让 Claude 模型为你阅读 PKGBUILD,从而拦截恶意的 AUR 包。** [![CI](https://github.com/manticore-projects/aurscan/actions/workflows/ci.yml/badge.svg)](https://github.com/manticore-projects/aurscan/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/v/release/manticore-projects/aurscan?sort=semver)](https://github.com/manticore-projects/aurscan/releases) [![Go](https://img.shields.io/badge/Go-1.22-00ADD8?logo=go&logoColor=white)](https://go.dev) [![Go Report Card](https://goreportcard.com/badge/github.com/manticore-projects/aurscan)](https://goreportcard.com/report/github.com/manticore-projects/aurscan) [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) [![Platform](https://img.shields.io/badge/platform-Arch%20Linux-1793D1?logo=archlinux&logoColor=white)](https://archlinux.org)
亲自阅读 PKGBUILD 只能发现你已知的攻击方式。**aurscan** 会在 **`makepkg` 执行任何一行代码之前**,读取包的 `PKGBUILD`、`.install` 脚本、`.SRCINFO` 和辅助脚本,并在脚本看起来存在恶意时阻止构建。 它分两个阶段运行:**快速的确定性静态规则**(离线、零成本)首先捕获已知的攻击活动特征,随后由 **Claude、Codex 或本地模型**(根据这些规则命中情况和包的 AUR 信誉作为参考)对复杂情况做出判断。即使在完全没有配置模型的情况下,仅靠静态规则也能产生安全失败(fail-closed)的判定结果,因此即使完全离线,您也能得到保护。 ``` $ syay firefox-patch-bin scanning firefox-patch-bin (3 files) ... [ MAL! ] firefox-patch-bin confidence 95% A source labelled "patches" points at a personal GitHub repo unrelated to Firefox and is executed during build — the July 2025 CHAOS RAT vector. [critical] PKGBUILD: Disguised source pulls attacker-controlled code. > patches::git+https://github.com/.../zenbrowser-patch.git ↳ tokens: 12,431 in / 214 out · $0.0413 scanner usage: 1 call(s) · tokens: 12,431 in / 214 out · $0.0413 !! Installation blocked: 1 package(s) flagged MALICIOUS. [A]bort (default) / [r]eport to mailing list & abort / [c]ontinue anyway: ``` ## 目录 - [为什么需要](#-why) - [如何挂钩 yay](#-how-it-hooks-into-yay) - [安装](#-install) - [认证](#-authentication) - [用法](#-usage) - [Token 与成本报告](#-token--cost-reporting) - [配置](#%EF%B8%8F-configuration) - [安全保障](#-how-it-stays-safe) - [项目结构](#%EF%B8%8F-project-layout) - [局限性](#%EF%B8%8F-limitations) - [贡献](#-contributing) ## 🎯 为什么需要 2025 年 7 月,`firefox-patch-bin`、`librewolf-fix-bin` 和 `zen-browser-patched-bin` 这几个 AUR 包被上传,其中包含一个伪装成 `patches` 的 `source=()` 条目,实际上它拉取了个人的 GitHub 仓库并在构建时运行了 **CHAOS RAT**。它们看起来就像是普通的浏览器修复程序;快速扫一眼 PKGBUILD 并不能明显看出问题。它们在网上存在了约 46 个小时。 aurscan 的构建初衷就是准确标记这类事物——即陌生的诡计,而不仅仅是你碰巧知道的那一种。 2026 年 6 月,**Atomic Arch** 攻击活动大规模地印证了这一点:攻击者接管了 **1,500 多个**孤立的 AUR 包,并且在某些情况下利用 git 提交*伪造*来冒充受信任的维护者,添加了一个运行 `npm install atomic-lockfile`(第二波中为 `bun install js-digest`)的安装后步骤,从而拉取了一个 Rust 凭据窃取程序,并且在以 root 身份构建时还会拉取一个 **eBPF rootkit**。包名和历史记录保持不变;只有构建指令及其编写者被悄悄改变了。aurscan 的 prompt 和静态规则编码了这些确切的攻击特征。 ## 🔌 如何挂钩 yay aurscan 利用 yay 自身的编辑器步骤,在唯一安全的拦截点——**下载之后、构建之前**——进行拦截。`syay` 包装器透明地将 yay 的编辑器指向 `aurscan-edit`,并强制开启编辑提示,因此扫描器会在 **yay 即将构建的每一个 AUR PKGBUILD** 上运行: | 你输入的内容 | 被扫描的内容 | |---|---| | `syay -S pkg` | 指定的包 | | `syay pkg` | 你从 yay **交互式**搜索菜单中选择的包 | | `syay -Syu` | 每一个 AUR 升级 | | _(以上任意一项)_ | ……以及它们的 AUR **依赖项**,这些也是 yay 在构建前会呈现出来的 | 当判定为**干净 (clean)** 时,它会链接到你真实的 `$VISUAL`/`$EDITOR`,因此你的手动审查依然会进行。当判定为**非 OK (non-OK)** 时,它会以非零状态退出,yay 将中止构建。 ## 📦 安装 ``` git clone https://github.com/manticore-projects/aurscan cd aurscan ./install.sh # build (needs Go) + install into /usr/local/bin ``` 然后使其透明化 —— **fish**: ``` alias yay=syay funcsave yay ```
bash / zsh ``` echo "alias yay=syay" >> ~/.bashrc # or ~/.zshrc ```
这会安装三个名称,它们都是**相同的静态二进制文件**:`aurscan`(CLI)、`syay`(yay 包装器)和 `aurscan-edit`(yay 调用的编辑器门控)。 ### paru paru 拥有原生的 `PreBuildCommand` 钩子——比 yay 的编辑器技巧更干净——因此你有两个选择: ``` # 选项 1(推荐):无 wrapper。一次性设置,然后直接使用普通的 `paru` 即可受控拦截。 aurscan --install-paru-hook # adds PreBuildCommand to ~/.config/paru/paru.conf # 撤销请使用:aurscan --uninstall-paru-hook # 选项 2:透明 wrapper,与 syay (fish) 保持对称 alias paru=sparu funcsave paru ``` 无论哪种方式,扫描器都会在下载之后、构建之前,于 PKGBUILD 目录中针对每个包运行一次——覆盖了 `-S`、裸的交互式搜索、`-Syu` 以及 AUR 依赖,甚至涵盖了缓存的构建。非 OK 的判定会让 paru 中止构建。`sparu` 会注入一个临时的配置(通过 `PARU_CONF`),该配置会 `Include` 你真实的 `paru.conf`,因此你自己的设置会被保留且永远不会被修改。 | 任务 | 命令 | |---|---| | 更新 | `git pull && ./install.sh` | | 卸载 | `./install.sh --uninstall` | | 无 root 安装 | `SUDO= PREFIX=~/.local ./install.sh` | | 仅构建 | `make build` | | 运行测试 | `make test` | | UPX 压缩二进制文件 | `make compress` | | 交叉构建发布构件 | `make release` | ## 🔑 认证 按以下顺序自动检测——**选项 1 完全不需要 API key**: 1. `PATH` 中的 **Claude Code CLI** (`claude`) 且已登录 → 使用你现有的 Claude 订阅。报告每次扫描的**确切成本**。 2. **`ANTHROPIC_API_KEY`** → 直接 API(默认为 `claude-sonnet-4-6`)。报告确切的 token;成本根据内置价格表计算。 3. `PATH` 中的 **Codex CLI** (`codex`) 且已登录 → 使用你现有的 Codex 订阅。token 和成本是估算的/无法从 CLI 输出中获取。 4. 通过 `AURSCAN_OPENAI_URL` 的**本地 / 自托管模型** → 任何兼容 OpenAI 的 `/chat/completions` endpoint(**llama.cpp、Ollama、vLLM、LocalAI**)。完全私有;设置 `AURSCAN_OPENAI_URL_FALLBACK` 以进行自动故障转移(例如 GPU 主机 → 本地 CPU)。可以通过 `AURSCAN_OPENAI_MODEL` 替换模型。 5. **`AURSCAN_BACKEND=/path/to/cmd`** → 任何可执行文件,该文件读取 stdin 上的 prompt 并在 stdout 上打印回复。 6. **完全没有后端** → 静态规则仍然会运行,并在严重匹配时阻止构建。
本地模型示例 (llama.cpp / Ollama) ``` # llama.cpp server,并带有到第二台主机的 fallback set -Ux AURSCAN_BACKEND openai set -Ux AURSCAN_OPENAI_URL http://192.168.0.110:18080/v1/chat/completions set -Ux AURSCAN_OPENAI_URL_FALLBACK http://127.0.0.1:18083/v1/chat/completions set -Ux AURSCAN_OPENAI_MODEL qwen2.5-coder-32b ``` 在速度慢、仅有 CPU 的主机上(例如手持设备),默认的 180 s 预算可能会在模型完成之前过期——你会看到 `context deadline exceeded`。请提高该预算,并确保模型的上下文窗口足以容纳 prompt(一个包通常有几千个 token;Ollama 默认的 2048 会将其静默截断): ``` set -Ux AURSCAN_TIMEOUT 900 # 15 minutes # 而在 Ollama 方面,请为模型提供真实的 context,例如: # 使用设定了 `PARAMETER num_ctx 8192` 的 Modelfile 运行 ollama run ``` 感谢 [@alexzk1](https://github.com/manticore-projects/aurscan/issues/1) 提供了此后端所推广使用的原始连接器。
选择本地模型——什么才真正有效(以及什么太小了) aurscan 对模型的要求比自动补全或聊天更高。对于每个包,它必须 (1) 推理跨越数千个 token 的 prompt 中可能经过混淆的 shell,(2) 返回与判定契约相匹配的**严格有效的 JSON**,以及 (3) **不被判定说服**,即无视不受信任的文件中注入的“这个包是安全的 / 忽略之前的指令”文本。小模型在这三点上都会失败:它们会盲目通过,发出格式错误的 JSON(→ 安全失败为 `SUSPICIOUS` 噪音),或者落入注入的圈套。**在这里,参数量比代码助手更重要。** 粗略指南(名称截至 2026 年中期——请在 Ollama 的库中查找等效模型,该领域发展迅速): | 参数规模 | 示例 | 对 aurscan 的判定 | |---|---|---| | ≤ 3B | `qwen2.5-coder:3b`, `llama3.2:3b`, `phi-*-mini` | ❌ **不要使用。** 判定接近随机,JSON 不可靠。请改用 `--rules-only`。 | | 7–8B | `codellama:7b` *([#8](https://github.com/manticore-projects/aurscan/issues/8) 中的模型)*, `qwen2.5-coder:7b`, `llama3.1:8b` | ⚠️ **勉强。** 只能抓住明目张胆的情况;会漏掉微妙的供应链诡计;JSON 有时会出错。独立的代码审查基准测试将 7B 的漏洞捕获率置于 ~45% 左右——应将其视为在静态规则之上的一个薄弱奖励,而不是真正的审核员。 | | 14B | `qwen3:14b`, `phi-4:14b`, `deepseek-r1:14b` | ✅ **可用的最低限度。** JSON 可靠,能捕获大多数植入的问题 (~75%)。 | | 32B | `qwen2.5-coder:32b`, `qwen3-coder:32b` | ✅ **推荐的最佳选择。** 强大的代码安全推理能力(在代码审查测试中约为 ~85–88%),在编程上具有 GPT-4o 级别的能力,可容纳于 24 GB GPU 中。 | | 70B+ / large MoE | `llama3.3:70b`, `qwen3-coder` (MoE), `gpt-oss:120b` | ✅ **最佳本地选择。** 接近云端质量;70B 级别专门针对*安全*分析最为强大。 | `Q4_K_M` 下的近似 VRAM(包括 KV-cache 余量):**8B ≈ 6 GB · 14B ≈ 10 GB · 32B ≈ 20–22 GB · 70B ≈ 43 GB。** 对于 14B 及以上的模型,强烈建议使用 GPU。 **人们经常弄错的两个设置:** 1. **上下文窗口。** Ollama 默认设置为 `num_ctx 2048`,这会将包*从 prompt 中静默截断*——随后模型几乎“扫描”不到任何东西。请设置 **`num_ctx` ≥ 8192(推荐 16384)**。将其烘焙到模型中,以便兼容 OpenAI 的 endpoint 始终使用它: printf 'FROM qwen2.5-coder:32b\nPARAMETER num_ctx 16384\n' > Modelfile ollama create aurscan-qwen -f Modelfile set -Ux AURSCAN_BACKEND openai set -Ux AURSCAN_OPENAI_URL http://127.0.0.1:11434/v1/chat/completions set -Ux AURSCAN_OPENAI_MODEL aurscan-qwen 2. **慢速硬件上的超时。** 仅 CPU 的推理(手持设备、NUC)运行速度为每秒几个 token——一次扫描可能需要几分钟。请提高预算:`set -Ux AURSCAN_TIMEOUT 900`。如果这仍然让人难以忍受,请退回到 7–14B 模型,或者直接运行 `--rules-only`。 你绝不会因为模型弱小而处于无保护状态:确定性的静态规则始终会运行,任何模型错误、超时或无法解析的输出都会**安全失败为 `SUSPICIOUS`**。大于你上下文窗口的包也会超出大多数本地模型的容量——静态规则依然会覆盖它。
获取 Anthropic API key(选项 2) 在 **console.anthropic.com → Settings → API keys** 创建一个,添加计费方式,然后: ``` set -Ux ANTHROPIC_API_KEY sk-ant-... ``` 一次典型的扫描只需几千个输入 token——在 API 上的花费远低于一美分,如果使用订阅则是免费的。
## 🚀 用法 ``` syay # normal yay usage; the scanner gates AUR builds aurscan [...] # standalone scan (fetches the AUR snapshot in memory) aurscan ./builddir # scan a local build directory aurscan --update-check # audit pending AUR updates without installing anything aurscan --gen-file # write pending AUR updates to ./aurscan.paclist aurscan --scan-file # scan packages listed in ./aurscan.paclist ``` **离线管理员工作流。** 如果你维护的机器没有配置 LLM 后端,请在那里安装 aurscan 并: ``` aurscan --gen-file ``` 这会使用来自 `yay -Qua` 的结构化待处理 AUR 更新列表覆盖 `./aurscan.paclist`。将该单个文件复制到你的扫描机器上并运行: ``` aurscan --scan-file ``` scan 命令要求当前目录中存在 `aurscan.paclist`,验证它是否为 aurscan 生成的文件,并通过与 `--update-check` 相同的递归 AUR 扫描器扫描所列出的包。 当包被标记时: - **中止** —— 默认操作;按下 Enter 始终是安全的。 - **报告** —— 生成 `/tmp/aurscan-report-.txt` 草稿,并提议打开你的邮件客户端发送至 [`aurscan@manticore-projects.com`](mailto:aurscan@manticore-projects.com),报告会在进行任何上游披露之前被汇总和处理,同时提醒你提交 AUR 删除请求。**绝不会自动发送。** - **继续** —— 需要输入 `INSTALL`,防止下意识操作导致漏网之鱼。 **退出代码:** `0` 干净/批准 · `1` 可疑-中止 · `2` 恶意-中止 · `3` 操作错误。 ## 🧩 自定义检测 **添加你自己的审核员指南。** 将 Markdown 文件放在 `~/.config/aurscan/instructions.md`(或将 `AURSCAN_INSTRUCTIONS` 指向任何路径)。其内容会*追加*到内置指令中——它可以使审核员更加敏锐,但绝不会削弱核心规则或 prompt 注入防护。在 [`packaging/instructions.example.md`](packaging/instructions.example.md) 中提供了一个可直接复制的示例;它告诉审核员要更加严格地对待低人气包、最近的维护者变更以及没有明显技术原因的变更。 **静态规则优先运行。** 一个确定性目录(改编自 [KiefStudioMA/ks-aur-scanner](https://github.com/KiefStudioMA/ks-aur-scanner),GPL-3.0,代码保持兼容)可离线且免费地匹配已知模式——`curl|bash`、反向 shell、凭据/浏览器配置文件访问、systemd 持久化、`npm install atomic-lockfile` / `bun install js-digest` 攻击活动特征、eBPF-rootkit 构件等等。每一次命中都会作为先验上下文反馈给模型。无需调用模型即可单独运行它们: ``` aurscan --rules-only # or set AURSCAN_RULES_ONLY=1 ``` ## 🔌 脚本集成 对于 CI 或自定义钩子,`--score` 会扫描单个目标并将结果映射到退出代码:成功时为 **0-100 的信任分数**(分数越高 = 越安全;MALICIOUS 0-33,SUSPICIOUS 34-66,OK 67-100),如果扫描未能完成则为 **255**。分数也会打印到 stdout;人类可读的判定结果会输出到 stderr,因此捕获它非常清晰: ``` aurscan --score ./PKGBUILD # exit code = trust score aurscan --score ./builddir # a directory works too makepkg --printsrcinfo >/dev/null; cat PKGBUILD | aurscan --score - # from stdin score=$(aurscan --score - < PKGBUILD) # capture just the number [ "$score" -ge 67 ] || echo "risky (score $score)" ``` 注意:退出代码 `0` 表示信任分数为 0(最危险),因此请测试数值本身,而不是依赖 `&&`/`||`。 ## 🐞 调试 LLM 通信 如果扫描返回“格式错误的 JSON”,或者你想确切查看发送给模型以及从模型返回的内容,请添加 `--debug`(在命令行的任何位置)。它会向 stderr 追踪所选的后端、完整的请求 payload、原始响应以及解析失败的任何原因: ``` aurscan --debug rocketchat-desktop aurscan --debug --score ./PKGBUILD ``` ## 💸 Token 与成本报告 每次扫描都会打印出每个包的使用情况和会话总计: ``` ↳ tokens: 12,431 in / 214 out · $0.0413 scanner usage: 1 call(s) · tokens: 12,431 in / 214 out · $0.0413 ``` | 后端 | Token | 成本 | |---|---|---| | Claude Code CLI | 确切 | 确切 (`total_cost_usd`) | | Codex CLI | 估算 (`~`) | `cost n/a` | | API key | 确切 | 根据价格表计算 | | 自定义命令 | 估算 (`~`) | `cost n/a` | 覆盖 API 价格表(每百万 token 的 USD 价格),让你永远不必依赖过时的内置价格:`AURSCAN_PRICE_IN` / `AURSCAN_PRICE_OUT`。 ## ⚙️ 配置 | 变量 | 默认值 | 含义 | |---|---|---| | `AURSCAN_BACKEND` | auto | `claude` · `codex` · `api` · `openai` · `/path/to/cmd` | | `AURSCAN_MODEL` | `claude-sonnet-4-6` | API 后端的模型 ID | | `AURSCAN_CODEX_MODEL` | Codex 默认值 | 传递给 `codex exec` 的模型 ID | | `AURSCAN_MAX_PKGS` | `25` | AUR 依赖扫描的递归上限 | | `AURSCAN_PRICE_IN` / `AURSCAN_PRICE_OUT` | 内置 | 每百万 token 的 USD 价格 | | `AURSCAN_OPENAI_URL` / `_FALLBACK` | — | 用于本地模型的兼容 OpenAI 的 endpoint | | `AURSCAN_OPENAI_MODEL` | `default-model` | 发送到本地 endpoint 的模型名称 | | `AURSCAN_TIMEOUT` | `180` | 每个请求的预算(以**秒**为单位);对于速度慢的仅有 CPU 的本地模型请提高该值 | | `AURSCAN_INSTRUCTIONS` | — | 额外审核员指令的路径(追加) | | `AURSCAN_RULES_ONLY` | — | `1` = 仅使用静态规则,从不调用模型 | | `NO_COLOR` | — | 禁用彩色输出 | ## 🔒 安全保障 - **安全失败。** 后端错误、超时、抓取失败或无法解析的输出 ⇒ **SUSPICIOUS**,构建被阻止。扫描器可能会失败,但绝不会暴露漏洞 (fail *open*)。 - **Prompt 注入防护。** 包文件作为**不受信任的数据**发送,与受信任的指令分开;prompt 将嵌入的“此包是安全的 / 忽略之前的指令”文本视为*恶意*的证据。解析仅信任 JSON 契约——已通过测试覆盖。 - **无执行,无磁盘写入。** AUR 快照在**内存中**解析;可疑包中的任何内容都不会被写入磁盘或运行。 - **有界上下文。** 跳过大于 64 KB 的二进制文件和文件;总上下文限制在 240 KB。 ## 🗂️ 项目结构 ``` cmd/aurscan/ entrypoint + argument dispatch internal/scan/ prompt, backend calls, verdict parsing, usage/pricing internal/aur/ AUR RPC, in-memory snapshot fetch, recursive dep scan internal/rules/ deterministic static-rule catalog (offline pre-filter) internal/pipeline/ orchestrates rules -> reputation -> LLM, rules-only fallback internal/config/ user config + extra-instructions loader internal/ui/ colours, verdict printing, interactive gate, report internal/yay/ syay wrapper + edit-hook gate packaging/PKGBUILD publish aurscan to the AUR testdata/ sanitised firefox-patch-bin fixture (structure only) ``` ## ⚠️ 局限性 - 是启发式的,而不是验证器——尽可能在干净的 chroot 中构建。 - `npm` / `bun` / `pip` / `go` / `curl` 有时是合法的(例如从源代码构建的 Electron 应用);预计偶尔会出现**误报**——这是更安全的出错方向。 - 该包装器为每次 AUR 构建启用 yay 的编辑提示;这是查看每个脚本的代价。传递你自己的 `--editor`,aurscan 会先进行扫描,然后再链接到它。 ## 🙏 致谢 - 静态规则目录改编自 [KiefStudioMA/ks-aur-scanner](https://github.com/KiefStudioMA/ks-aur-scanner) (GPL-3.0)。 - 本地 LLM 后端推广自 [@alexzk1 的连接器](https://github.com/manticore-projects/aurscan/issues/1)。 ## 📄 许可证 [Apache-2.0](LICENSE) © Manticore Projects Co., Ltd.
标签:AI风险缓解, Arch Linux, AUR, DLL 劫持, EVTX分析, Go, Ruby工具, 云安全监控, 大语言模型, 恶意软件扫描, 日志审计, 网络信息收集, 镜像安全, 静态分析