Varpost/Scout

GitHub: Varpost/Scout

Scout 是一款面向独立开发者的本地命令行静态安全扫描工具,帮助他们在发布前发现密钥泄露、注入漏洞和依赖风险等常见安全问题。

Stars: 0 | Forks: 0

# Scout **CLI 中的 AI 安全团队。** 在黑客之前发现漏洞——免费、本地、无需注册。 [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://python.org) [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![PyPI](https://img.shields.io/pypi/v/scout-security)](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 重新验证。 [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Scout_MCP-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](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) [![Add to Cursor](https://img.shields.io/badge/Cursor-Add_Scout_MCP-111111?style=flat-square&logoColor=white)](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技术, 图数据库, 安全专业人员, 无后门, 逆向工具, 错误基检测, 静态代码分析