malandas/andas
GitHub: malandas/andas
一款专注于真实风险验证的跨平台安全 CLI 工具,通过实时验证凭证有效性和分析依赖漏洞可达性来过滤告警噪音。
Stars: 0 | Forks: 0
# andas
[](https://github.com/malandas/andas/actions/workflows/ci.yml)
[](https://github.com/malandas/andas/releases/latest)
[](LICENSE)
大多数安全扫描器会让你淹没在警报中。`andas` 回答了它们无法回答的问题:**对于*你的*项目来说,这种风险是真实存在的,还是无用的噪音?**
- 只有当检测到的密钥**仍然有效**时,它才构成紧急事件。`andas` 会以安全、只读的方式询问其提供商,并将失效的凭证降级,使其不再干扰你。
- 只有当 npm 依赖项中的 CVE **可从**你应用自身的代码到达时,它才至关重要。`andas` 会追踪你的 import 语句,并将无人 import 的包以及永远不会发布到生产环境的开发依赖项中的漏洞降级。
一个命令。一个无依赖的二进制文件。支持 Linux、macOS、Windows。
## 安装
从[最新发布版本](https://github.com/malandas/andas/releases/latest)获取预编译的二进制文件:
```
# macOS (Apple Silicon) 示例
curl -sSL -o andas https://github.com/malandas/andas/releases/latest/download/andas-darwin-arm64
chmod +x andas && ./andas version
```
使用 Go 工具链:
```
go install github.com/malandas/andas@latest
# 或者从 clone 获取:
go build -o andas .
```
## 用法
```
andas scan # scan the current directory
andas scan ./myproject # scan a specific path
andas scan . --history # also sweep git history for removed secrets
andas scan . --html out.html # write a shareable HTML report
andas scan . --sarif r.sarif # SARIF for CI / GitHub code scanning
andas scan . --json # machine-readable output
andas scan . --offline # no network calls at all
```
### 在已有技术债务的仓库中采用
```
andas scan . --baseline andas-baseline.json --update-baseline # accept today's state
andas scan . --baseline andas-baseline.json # now only NEW risk fails CI
```
### 保护你的提交
```
andas hook install # installs a git pre-commit hook
andas hook status # is it installed?
andas hook uninstall # remove it
```
该 hook 会在每次提交前运行 `andas scan . --offline --fail-on medium`,因此硬编码的密钥会在**进入历史记录之前**被捕获——这是你永远无法完全撤销的泄漏。使用 `git commit --no-verify` 可以跳过误报。
### 忽略路径
在仓库根目录下放置一个 `.andasignore` 文件,每行一个模式(类似于 `.gitignore`):路径片段(`testdata`、`src/generated`)、glob 匹配(`*.min.js`)或 `#` 注释。匹配的文件将被工作区扫描器跳过。
### 参数标志
| 标志 | 默认值 | 含义 |
|------|---------|---------|
| `--history` | off | 同时扫描完整的 git 历史,查找从 HEAD 中移除的密钥。 |
| `--baseline ` | — | 抑制记录在此基线文件中的发现结果。 |
| `--update-baseline` | off | 接受所有当前的发现结果到 `--baseline` 中,然后退出。 |
| `--no-entropy` | off | 禁用基于信息熵的未知/自定义密钥检测。 |
| `--html ` | — | 生成一个独立的 HTML 报告。 |
| `--sarif ` | — | 生成用于 CI / 代码扫描的 SARIF 2.1.0 报告。 |
| `--markdown ` | — | 生成 PR 评论风格的 Markdown 报告。 |
| `--no-validate` | off | 跳过密钥的有效性验证。 |
| `--offline` | off | 完全不进行网络调用(不验证,不进行 OSV 查询)。 |
| `--json` | off | 输出 JSON 而非表格。 |
| `--no-color` | off | 禁用彩色输出。 |
| `--timeout` | `8` | 每次验证的网络超时时间(秒)。 |
| `--fail-on` | `high` | 当真实风险达到此级别时以非零状态退出。 |
当**真实**风险达到 `--fail-on` 设定的级别时,退出代码为非零,因此你可以基于有效的密钥来控制 CI pipeline 的流转,同时忽略已失效的密钥。
## 真实风险评分的工作原理
每个发现结果都包含两个级别:
- **严重性** — 理论/基于模式的级别(其他工具提供给你的结果)。
- **真实风险** — 经过 `andas` 的上下文检查后:
- 密钥**验证为有效** → 提升至 `CRITICAL`
- 密钥**验证为失效** → 降级至 `INFO`(这就是我们要剔除的噪音)
- 无法验证 → 保持其理论上的严重性
## 实时验证究竟做了什么
对于每种带有验证器的密钥类型,`andas` 会向**该凭证自身的提供商发送一个只读请求**(例如 `GET api.github.com/user`)并读取 HTTP 状态码:`2xx` = 有效,`401/403` = 失效。它永远不会执行写入操作,也绝不会将密钥发送到除其合法提供商之外的任何地方。使用 `--no-validate` 可进行完全离线的扫描。
目前支持的验证器:GitHub(PAT + OAuth/App token)、GitLab、Slack、Stripe、npm、SendGrid、Telegram、OpenAI、DigitalOcean、Mailgun,以及配对的验证器 ——
**AWS**(一个 `AKIA…` 密钥 + 一个邻近的密钥,通过签名的 STS `GetCallerIdentity` 进行验证)和 **Twilio**(一个 `AC…` SID + 一个邻近的 auth token)。
仅检测不验证:Google、私钥块。
**andas 严格保持只读。** 它扫描文件并仅向凭证自身的提供商发出只读请求——它从不编辑你的代码、轮换密钥或创建 PR。它向你展示风险和修复方法;而采取行动的决定权在于你。
除了这些已知的格式外,一种**信息熵启发式算法**可以捕获自定义/内部的密钥:分配给类似密钥名称(`*token*`、`*apiKey*`、`*password*` 等)的高随机性值。这些是无法验证的,因此它们会被报告为 MEDIUM ——如果其中某个属于误报,`--baseline` 可以将其永久屏蔽。
## 影响范围 — 一个有效的密钥究竟能造成多大的破坏?
一个有效的密钥是致命的,但一个有效的*管理员*密钥则是五星级警报。由于 andas 已经与提供商进行了通信,它会读取凭证的**身份和权限**,并标记出危险项:
```
CRITICAL GitHub Personal Access Token
src/ci/deploy.js:8 ghp_••••••yz
▲ VERIFIED LIVE — rotate this credential now
identity: octocat
🔓 can access: repo, admin:org, workflow
⚠ HIGH-PRIVILEGE credential — maximum blast radius
```
- **GitHub** → OAuth scopes(`repo`、`admin:org`、`delete_repo` 等)
- **GitLab** → personal-access-token scopes(`api`、`sudo` 等)
- **SendGrid** → API-key scopes(`mail.send`、管理员权限等)
- **AWS** → 身份 ARN 和账户信息,标记为 root/admin
- **Stripe / npm** → 拥有完整访问权限的密钥被标记为特权
高权限的有效密钥会排在报告的最顶部——相同的严重性,更大的影响范围。
## 暴露时间线与攻击路径
另外两个只读信号,能将一堆发现结果列表转化为真实的图景:
- **暴露时间线** — 通过 git blame(以及针对历史泄漏的提交日期),andas 会告诉你一个密钥*已经暴露了多久*:`⏱ 暴露约 47 天(自 2025-11-08 起)`。几个月前泄漏的密钥与今天刚添加的密钥,其紧急程度截然不同。
- **攻击路径** — andas 会描述已确认的发现是如何串联起来的:
⚔ attack path
• 一个高权限的 AWS (arn:…:root) 有效凭证暴露——攻击者获得了账户访问权。
• 多个有效凭证(AWS、GitHub)同时暴露——一个泄漏的 repo 让攻击者一次性获取所有凭证。
• 一个已从代码中移除的凭证在 git 历史中仍然有效——删除代码行从未轮换过密钥。
每一行都基于 andas 实际验证过的内容——绝非虚构的风险。
## 依赖扫描 — 多种语言
`andas` 跨生态系统扫描依赖清单,并将每个包与 [OSV.dev](https://osv.dev) 进行交叉比对:
| 语言 | 清单文件 | 可达性 |
|----------|----------|--------------|
| JavaScript / TypeScript | `package.json` + `package-lock.json` / `yarn.lock` | ✅ import 级别 + 使用的符号 |
| Python | `requirements.txt` (固定版本) | — 按严重性排序 |
| Go | `go.mod` | — 按严重性排序 |
| Ruby | `Gemfile.lock` | — 按严重性排序 |
| Rust | `Cargo.lock` | — 按严重性排序 |
| PHP | `composer.lock` | — 按严重性排序 |
JS/TS 支持以下详述的完整可达性分析;其他语言则提供按实际严重性排序的漏洞发现(这些生态系统的可达性支持已列入路线图)。
## 深入了解可达性 (JS/TS)
对于包含 `package.json` 的项目,`andas` 还会:
1. 读取 `package.json` 和 lockfile —— `package-lock.json` (npm) 或
`yarn.lock` (Yarn v1 **以及** Berry/v2+) —— 以解析确切的完整依赖树。如果没有 lockfile,则回退到直接依赖。
2. 查询 [OSV.dev](https://osv.dev)(免费,无需 API key)以获取每个包的已知漏洞。
3. 解析你的 `.js/.jsx/.ts/.tsx` 源代码,查看你实际 import 了哪些包,然后遍历依赖图计算哪些是**可达的**。不在此集合中的易受攻击包——未使用的传递依赖,或从未打包进你的 React Native 生产环境的开发工具——将被降级为 `LOW`。
可达性处于 **import 级别**(即包是否被触及)。作为迈向函数级别可达性的第一步,`andas` 还会报告**你的代码实际使用了易受攻击包中的哪些 export**(`↳ 你的代码使用了:merge, template`)——作为分类排查的证据。它故意**不**根据这一信号降级:将安全公告映射到确切的函数是不可靠的,而且虚假的“安全”比误报更糟糕。
## Git 历史密钥扫描 (`--history`)
最棘手的地方。从你最新提交中删除的凭证仍然存活在 git 历史中——而一旦 repo 公开,历史记录也就公开了。使用 `--history`,andas 会扫描**所有分支和提交中的每一个 blob**,并且——因为它会实时验证——会报告真正重要的情况:
```
CRITICAL AWS Access Key ID (in git history)
git history @ 4f1a9c2 (Sara N., 2025-11-08) AKIA••••••7Q
▲ removed from HEAD but still recoverable — AWS accepted the key pair — LIVE
→ fix: Deactivate the key in IAM → Security credentials, then create a fresh pair.
```
仍处于工作区中的密钥将留给常规的文件扫描;`--history` 仅报告那些**已移除但从未轮换**的密钥。
## 报告与 CI
- `--html ` — 一个独立、支持主题的 HTML 报告,方便分享。
- `--sarif ` — SARIF 2.1.0;每个结果的级别由**真实风险**驱动,因此失效的密钥会显示为提示,而有效的密钥则显示为错误。使用 `github/codeql-action/upload-sarif` 上传它以填充 Security 选项卡。
- `--markdown ` — 紧凑的 PR 评论风格摘要。andas 仅写入文件;发布它(如果你需要的话)是你 CI 的工作——andas 保持只读。
- 每个发现结果都带有具体的**修复**指引(轮换链接、升级目标)。
在 [`examples/github-workflow.yml`](examples/github-workflow.yml) 中提供了一个现成可用的工作流。
## 开发
```
go build -o andas . # build
go test ./... # run the test suite
go vet ./... # static checks
```
测试套件直接覆盖了安全核心逻辑:真实风险判定表、信息熵精度(必须能抓取真实密钥并拒绝占位符)、npm/Yarn (v1 + Berry) lockfile 解析器、可达性 BFS 算法、影响范围 scope 解析器、基线读写测试(绝不能持久化存储原始密钥材料),以及对 CLI 布线和 git 历史扫描器的端到端测试。
CI 会运行 `vet` + `test`,并且每次推送时都会让 andas 扫描其自身的源代码。
发布历史请参阅 [CHANGELOG.md](CHANGELOG.md)。
## 状态
`v1.1.0` — **多语言依赖扫描**(JS/TS、Python、Go、Ruby、Rust、PHP)和 **12 个实时密钥验证器**,构建于一个具备影响范围评分、暴露时间线、攻击路径分析、信息熵检测、基线、pre-commit 防护、四种报告格式以及 48 个测试用例的单一真实风险核心之上。严格只读:
| 扫描器 | 检测目标 | 区分信号与噪音的上下文 |
|---------|---------|------------------------------------------|
| **secrets** | 12 种凭证类型 | 跨 8 家提供商的实时验证(包含签名的 AWS STS) |
| **deps** | npm/Yarn 漏洞 (v1 与 Berry) | import 可达性 + 你的代码实际调用的受漏洞影响的函数 |
| **git-history** | 从 HEAD 中移除的密钥 | 历史记录中**且**仍然有效 |
输出格式:终端、JSON、HTML、SARIF —— 每一种都包含修复建议。
## 许可证
MIT — 详见 [LICENSE](LICENSE)。
标签:CISA项目, EVTX分析, Go, Maven, Ruby工具, StruQ, 文档结构分析, 日志审计, 暗色界面, 漏洞验证, 聊天机器人