Varpost/Scout
GitHub: Varpost/Scout
Scout 是一款面向独立开发者的本地命令行静态安全扫描工具,帮助他们在发布前发现密钥泄露、注入漏洞和依赖风险等常见安全问题。
Stars: 0 | Forks: 0
# Scout
**CLI 中的 AI 安全团队。** 在黑客之前发现漏洞——免费、本地、无需注册。
[](https://python.org)
[](LICENSE)
[](https://pypi.org/project/scout-security/)
## 为什么选择 Scout?
AI 编码助手经常会写出不安全的代码——硬编码的机密信息、SQL 注入、缺失的身份验证。独立开发者因为没有安全团队而将其发布。
**Scout 就是那个团队。** 静态分析可以捕获 AI 助手最常犯的错误——密钥泄露、字符串拼接的 SQL、`shell=True`、缺失的安全 HTTP 头。无需 API 密钥,无需配置,完全免费。
## 安装
零安装——使用 [uv](https://docs.astral.sh/uv/) 通过一条命令进行尝试(无需 venv,冷启动约 1 秒):
```
uvx scout-security scan ./my-project
```
或者将其永久安装:
```
pip install scout-security
```
## 用法
```
# 扫描项目 — 确定性 static analysis:无需 API keys,无需 tokens,无需注册
scout scan ./my-project
# 将发现结果转换为可直接粘贴的 fix prompts,供您的 AI 助手使用
scout scan ./my-project --format ai-prompt
```
## 输出格式
一次扫描,四种视图——使用 `--format` (`-f`) 进行选择:
```
# Layer 1 — 人类可读的 Markdown 报告(默认)
scout scan ./my-app
scout scan ./my-app -o security-report.md
# Layer 2 — 可直接粘贴的 prompts,供您自己的 AI 使用(Cursor、Claude、Copilot…)
scout scan ./my-app --format ai-prompt # writes security-prompts.md
scout scan ./my-app --format ai-prompt -o prompts.md
# Layer 3 — 机器可读的 JSON,用于 piping 到 agentic tooling / CI 中
scout scan ./my-app --format json # prints JSON to stdout
scout scan ./my-app --format json -o report.json
scout scan ./my-app --format json | jq '.findings[]'
# Layer 4 — 用于 GitHub Code Scanning 的 SARIF 2.1.0(PR annotations)
scout scan ./my-app --format sarif -o scout.sarif
```
相同的底层引擎驱动着它们——Scout 负责发现问题;你自己的 AI(已经了解你的代码库)负责应用修复。
## 用作 CI 门控
当存在 `--fail-on`(默认值:`high`)级别或更高级别的发现时,`scout scan` 会以 **1** 退出,因此你的 pipeline 会在遇到真正的问题时失败:
```
scout scan . --fail-on high # default — fail on HIGH or CRITICAL findings
scout scan . --fail-on critical # fail only on CRITICAL
scout scan . --fail-on never # report-only mode — always exit 0
```
GitHub Action 封装了安装 + 扫描 + SARIF 上传过程,因此扫描结果会通过 GitHub Code Scanning 显示为 PR 注释:
```
jobs:
scout:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: Varpost/Scout@v0.1.7
with:
fail-on: high # also: path, format, upload-sarif
```
喜欢普通的步骤?手动操作也是一样的(该 job 仍然需要 `security-events: write` 权限):
```
- run: |
pip install scout-security
scout scan . --no-ai --format sarif -o scout.sarif --fail-on never
- uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: scout.sarif
```
## Pre-commit Hook
在被提交之前就捕获扫描发现:
```
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Varpost/Scout
rev: v0.1.7 # use the latest tag
hooks:
- id: scout
```
该 hook 会在每次提交时从你的仓库根目录运行 `scout scan . --no-ai --fail-on high`,因此你的 `[tool.scout]` 配置会生效。可以通过 `args: ["--fail-on", "critical"]` 来调整阈值。当扫描失败时,Scout 会写入包含详细信息的 `security-report.md`——建议将其添加到你的 `.gitignore` 中。
## 抑制扫描结果
在被标记的代码行末尾添加注释即可屏蔽误报:
```
result = eval(trusted_expression) # scout: ignore
result = eval(trusted_expression) # scout: ignore[injection]
```
单独的 `scout: ignore` 会屏蔽该行上的所有扫描结果。限定作用域的形式只会屏蔽指定的扫描器(`secrets`、`injection`、`headers`、`deps`)或结果 ID(例如 `injection/eval_usage`——即 `--format json` 中的 `id` 字段)。无法携带行内注释的扫描结果——例如应用级别的 CSRF 检查没有实质的代码行,而 lockfile 的结果存在于生成的 JSON 中——可以通过 `[tool.scout]` scanners`(见下文)关闭相应的扫描器,或者将它们接受为基线(见下文)。
## 配置
使用 `--exclude` 跳过路径(可重复使用;相对于扫描根目录,支持通配符):
```
scout scan . --exclude tests/fixtures --exclude "*.min.js"
```
或者在 `pyproject.toml` 中设置项目默认值——Scout 会从被扫描的项目中读取 `[tool.scout]`:
```
[tool.scout]
exclude = ["tests/fixtures", "vendor"] # paths or glob patterns to skip
scanners = ["secrets", "injection"] # run a subset: secrets, injection, headers, deps
fail_on = "medium" # default threshold for --fail-on
```
CLI 参数优先:`--exclude` 会替换配置列表,`--fail-on` 会覆盖 `fail_on`。
## 在现有代码库中采用 Scout(基线)
不想在开启 CI 门控之前修复积累多年的扫描结果?接受当前状态,然后只针对新的扫描结果失败:
```
scout scan . --write-baseline # accept current findings → .scout-baseline.json
scout scan . --baseline .scout-baseline.json # report and fail only on NEW findings
```
提交 `.scout-baseline.json`。扫描结果的身份是基于内容的——即规则、文件以及被标记行的哈希值,特意**不包含行号**——因此当不相关的编辑导致它们在文件中上下移动时,被基线化的结果仍保持已接受状态。更改被标记的行本身会使该结果重新进入待审核状态。
## 扫描 Git 历史记录中的机密信息
提交后又被删除的机密信息仍然处于泄露状态——对今天的代码进行扫描是看不到它的:
```
scout scan . --git-history # secrets in every added line of every commit, all branches
```
扫描结果会锚定在引入它们的 commit 上(`config.py @ 1a2b3c4d5e6f`)——**轮换它报告的任何内容**;删除那一行并不能撤销已经泄露的凭证。需要 PATH 中存在 `git`;扫描的是历史记录,而*不是*工作区。
诚实的范围说明:[Gitleaks](https://github.com/gitleaks/gitleaks) 和 [TruffleHog](https://github.com/trufflesecurity/trufflehog) 将深入、快速的历史记录审计作为其核心工作——Scout 的扫描只是内置的便利功能,并非替代品。
## 它能发现什么
| 扫描器 | 检测内容 | 严重程度 |
|---------|---------|----------|
| `secrets` | AWS/Google 密钥、GitHub/GitLab token、Anthropic 和 OpenAI 密钥、Slack/npm/PyPI token、Stripe 密钥、数据库 URL、私钥、密码 | CRITICAL |
| `injection` | SQL 注入、命令注入、eval()、XSS | CRITICAL |
| `headers` | 缺失的安全 HTTP 头、通配符 CORS、缺失的 CSRF | LOW–MEDIUM |
| `deps` | pip + npm 依赖项中的已知漏洞(通过 OSV.dev) | HIGH |
### 语言范围
深度分析——**injection**(SQL/命令/XSS)和**安全 HTTP 头**——针对的是 **Python 和 JS/TS**,因为这些检测模式具有特定的编程习惯用法。**机密信息检测与语言无关**:它会在 Scout 收集的每一个通用源文件和配置文件(Go、Java、Ruby、PHP、C/C++、Rust、shell、`.env`、`Dockerfile`、`docker-compose`、Terraform 等)上运行,因此无论使用哪种语言泄露了硬编码的密钥都会被捕获。依赖项扫描涵盖 `requirements.txt` 和 `package-lock.json`。
## 示例输出
```
$ scout scan ./my-app
Scout v0.1.7 scanning: ./my-app
Scanning 47 files...
Found 6 issues:
🔴 2 critical
🟠 3 high
🟡 1 medium
Report written to: ./my-app/security-report.md
```
报告包含:
- 用通俗英语解释的每一个漏洞
- 带有上下文的严重性评级(为什么它很危险)
- 针对每个问题的确切修复说明
- 分阶段的修复计划(优先处理零风险的修复)
## 可选:AI 确认环节
**核心扫描始终是静态的、确定性的、离线的,且零 token 消耗的——同样的扫描,同样的结果,无需 API 密钥。** 这是默认设置,且永远不会改变。
如果你想要一个额外的误报过滤器,Scout 可以选择性地将每个启发式发现的*仅被标记的代码片段*(绝不是整个文件)发送给 AI 提供商,该提供商可以**下调**其严重程度或将其作为误报**驳回**。依赖项(OSV)和项目级别的发现是确定性的事实,绝不会受到二次猜测。任何提供商错误都会使扫描结果保持原样——该环节以“开放失败”原则运行,因此它永远不会隐藏真正的问题。
它**默认关闭**。可以在每次运行时启用它:
```
# Anthropic(需要 ANTHROPIC_API_KEY)— 默认使用便宜的 Haiku tier
scout scan . --model anthropic
# OpenAI(需要 OPENAI_API_KEY)
scout scan . --model openai
# Local Ollama(无需 key,无需云)— 任何数据都不会离开您的机器
scout scan . --model ollama --ollama-model llama3
```
提供商的解析优先级是 `--model` > `SCOUT_AI_PROVIDER` 环境变量 > `none`。可以通过 `SCOUT_AI_MODEL` 为每个提供商覆盖模型。`--no-ai` 会无视配置强制关闭该环节。使用 `pip install "scout-security[ai]"` 安装相应的 SDK(Ollama 不需要额外依赖)。
## MCP 服务器(Agent 验证器)
将 Scout 作为 [MCP](https://modelcontextprotocol.io) 工具运行,你的编码 Agent 可以在“扫描 → 修复 → 重新扫描”的循环中调用它——具有确定性、离线、零 token 消耗、无推理成本。Scout 发现问题;你的 Agent 修复它;Scout 重新验证。
[](https://vscode.dev/redirect/mcp/install?name=scout&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22scout-security%5Bmcp%5D%22%2C%22scout-mcp%22%5D%7D)
[](https://varpost.github.io/Scout/#ai-assistant)
*(GitHub 会过滤掉 `cursor://` 深层链接,因此 Cursor 徽章会通过该网站的一键按钮进行跳转。)*
### 安装为 Claude Code 插件
一键命令路径——该插件捆绑了 MCP 服务器,因此不需要单独执行 `claude mcp add`:
```
/plugin marketplace add Varpost/Scout
/plugin install scout@scout
```
这会注册 `scan_path` 工具和 `/scout-scan [path]` 命令。要求你的 PATH 中存在 [uv](https://docs.astral.sh/uv/)——该插件使用 `uvx` 启动服务器(首次运行会下载包;后续运行会命中缓存)。没有 uv?请使用下面的手动设置,改为使用 `pip install "scout-security[mcp]"` 和 `"command": "scout-mcp"`。
### 手动设置(任何 MCP 宿主)
每个 MCP 宿主都采用相同的服务器定义——通过 [uv](https://docs.astral.sh/uv/) 实现零安装:
```
{
"mcpServers": {
"scout": {
"command": "uvx",
"args": ["--from", "scout-security[mcp]", "scout-mcp"]
}
}
}
```
没有 uv?执行 `pip install "scout-security[mcp]"`,然后使用 `"command": "scout-mcp"` 且不带 `args` 参数。
该定义应放置的位置:
| 宿主 | 位置 |
|------|-------|
| **Claude Code** | 上面的[插件](#install-as-a-claude-code-plugin),或者 `claude mcp add scout -- uvx --from "scout-security[mcp]" scout-mcp` |
| **Cursor** | 你项目中的 `.cursor/mcp.json`,或者用于所有项目的 `~/.cursor/mcp.json` |
| **Claude Desktop** | `claude_desktop_config.json`(Settings → Developer → Edit Config) |
| **Cline** | `cline_mcp_settings.json`(MCP Servers → Configure MCP Servers) |
| **Windsurf** | `~/.codeium/windsurf/mcp_config.json` |
| **VS Code**(原生 MCP) | `.vscode/mcp.json`——服务器对象相同,但位于 `"servers"` 键下,而不是 `"mcpServers"` |
它暴露了一个工具——**`scan_path(path)`**——返回与 `--format json` 相同的 Layer-3 JSON(包含文件、行号、严重程度、稳定 ID、说明和修复指导的发现结果)。将 Agent 的修复循环指向它,然后再次调用以确认问题已解决。
## 将 Scout 与你的 AI 助手结合使用
整个理念可以用一句话概括:**Scout 确定性地发现问题 → 你的 AI 进行修复 → Scout 重新验证。** 每次扫描都一样,结果都一样,并且每次检查都零 token 消耗——因此重新检查修复内容永远不会产生推理成本。选择适合你工作方式的使用界面;这三种方式都运行相同的底层引擎。
### 1. 你 + 聊天助手(Claude、Cursor、Copilot Chat)
```
scout scan . --format ai-prompt # writes security-prompts.md
```
打开 `security-prompts.md`,将其中一个代码块粘贴到你的助手中。每一块都是独立的——包含发现的问题、修复方法,以及一个指令,用于扫描你代码的其余部分是否存在同类问题。在它编辑完成后,重新验证:
```
scout scan . # clean? the loop is closed
```
### 2. 自行调用 Scout 的 Agent(Claude Code、Cursor Agent)
接入 [MCP 服务器](#mcp-server-agent-verifier),然后将循环交给 Agent:
Agent 会调用 `scan_path`,应用修复,然后再次调用。Scout 是循环*内部*具有确定性且零 token 消耗的验证器,因此每次重新检查都是免费的。
### 3. CI / pre-commit(使循环成为强制要求)
将该循环转变为一个门控——在扫描发现的问题被修复之前,构建将失败:
```
scout scan . --fail-on high # exit 1 on HIGH+ findings
```
有关 GitHub Action,请参阅[用作 CI 门控](#use-as-a-ci-gate),并使用 [Pre-commit Hook](#pre-commit-hook) 在提交之前捕获扫描发现。在现有仓库中采用?[基线](#adopting-scout-on-an-existing-codebase-baseline)可以接受今天的扫描结果,并且仅针对新出现的结果失败。
## 添加自定义扫描器
```
from scout.scanners import register_scanner
from scout.scanners.base import BaseScanner
from scout.models import Finding
from pathlib import Path
@register_scanner
class MyScanner(BaseScanner):
name = "my-scanner"
description = "Detects my custom pattern"
def scan_file(self, file_path: Path, content: str) -> list[Finding]:
findings = []
# detection logic here
return findings
```
在 `scout/scanners/__init__.py` 中添加一个导入 → 完成。
## 开发
```
git clone https://github.com/Varpost/Scout.git
cd Scout
pip install -e ".[dev,ai]"
pytest
ruff check scout/ tests/
```
## 文档
完整文档和交互式指南:[https://varpost.github.io/Scout/](https://varpost.github.io/Scout/)
## 许可证
MIT——永远免费。
标签:AI风险缓解, CLI, DOE合作, Petitpotam, Python, WiFi技术, 图数据库, 安全专业人员, 无后门, 逆向工具, 错误基检测, 静态代码分析