Christian-Katzmann/dev-security
GitHub: Christian-Katzmann/dev-security
DëvSec 是一款本地优先的安全可观测性工具,在开发者本机编排多家开源扫描器并将结果转化为可操作的补救案例,全程不上传代码或扫描数据。
Stars: 4 | Forks: 1
# DëvSec — 本地优先的安全可观测性
为你实际工作的代码库提供实用的安全扫描。DëvSec 在你的本地机器上运行成熟的开源扫描器,将历史记录存储在本地 SQLite 中,并将扫描器的嘈杂信息转化为一小部分明确的下一步行动。
*(作为 `security-observatory` Python 包安装。CLI 命令是 `security-scan`。仪表盘品牌名为 DëvSec —— 同一个项目,你会在不同的地方遇到这三个名字。)*
**状态:** 0.2.x — 早期阶段。本地扫描运行良好;仪表盘如实展示了哪些功能仍是部分的。下方的[已实现 vs. 尚未实现](#whats-real-vs-whats-not-yet)表格列出了具体的差距。
https://github.com/user-attachments/assets/9df30c29-a9fc-40f2-83c4-3530b08c4818
*仪表盘将原始扫描器输出分组为案例 —— 每个案例都包含通俗易懂的风险描述、严重程度,以及可供 Agent 直接使用的交接 prompt。0.0 / 10 的安全态势得分是真实的:这是 DëvSec 扫描自身的结果。源视频 MP4:[design/trailer/trailer.mp4](design/trailer/trailer.mp4)。*
## 为什么会有这个项目
大多数安全平台会将你的源代码发送到 SaaS,按代码库收费,或者两者兼有。
DëvSec 的形式恰恰相反:扫描器在你已有的代码库克隆上本地运行。
结果保留在 `~/.security-observatory` 下,不上传任何内容,也不需要云 LLM。
仪表盘的存在是为了让你无需 grep 原始 JSON 就能读懂扫描器实际发现了什么。
有关本地优先立场背后的长篇论述,请参阅 [PROVOCATION.md](PROVOCATION.md)。关于系统结构视图中哪些内容保留在本地以及不存在的边界,请参阅[信任边界图](design/diagrams/trust-boundary.md)。
## 已实现 vs. 尚未实现
DëvSec 的状态栏写着*“仪表盘如实展示了哪些功能仍是部分的。”* 这是详细清单:
| 领域 | 已实现 | 尚未实现 |
|---|---|---|
| 本地扫描 | Semgrep、Gitleaks、TruffleHog、Trivy、OSV-Scanner、Grype、Syft、Checkov、Medusa、IOC-watch —— 全部在你的机器上运行 | — |
| 内置检测规则 | `install-hooks`、`workflow-audit` 和 `ai-static` 已发布并可检测 | — |
| 恢复手册 | 依赖升级、机密轮换、AI 配置收紧 | 长尾发现类别显示 *“coming soon”* 卡片 |
| 连接的平台安全态势检查 | 当你提供 token 时,`legitify` 和 OpenSSF Scorecard 可正常工作 | 默认关闭 —— 仅在主动选择时开启,绝不静默运行 |
| 扫描历史与趋势 | 每次扫描都存储在本地;仪表盘呈现安全态势随时间变化的迷你图,以及一个可以对比任意两次已保存扫描的 base/head 选择器 (`/api/scan-diff`),并为已解决的案例提供关闭证明 | — |
| 受保护的 AI 修复流程 | MCP 写入模式 (`devsec-mcp-rw`) 在分支上提出修复建议,并运行一次净室审查(仅能看到 diff 和不变量,绝看不到发现文本本身);仪表盘的“Code fixes”视图列出建议并落地已审查通过的建议。只有狭窄的低风险类别(action SHA 固定、单个 patch/minor 依赖版本提升、lockfile 更新)符合自动合并条件 | 宽泛或更高风险的修复 —— 以及抑制任何 high/critical 案例 —— 都需等待明确的人工确认,绝不自动应用。`land_fix` 仅进行授权;它绝不执行合并 |
| Honey Keys | 创建、插入到 `.devsec/honeykeys/` 下、仅存储 hash,触发时产生回调 | 你需要提供 webhook endpoint —— DëvSec 不运营任何 Honey Key 基础设施 |
| 托管安装 | `gitleaks v8.30.1` 是第一个托管安装的证明 | 其他扫描器使用检测到的 / Homebrew / uv 安装;更广泛的托管安装已推迟 |
| 外部资产面扫描 | — | Coming Soon 占位符 —— MVP 中不包含探测、无目标输入、无侦察 |
| IaC Pack | 通过 `security-scan --iac` 运行 Trivy + Checkov IaC 检查 | IaC Pack 页面本身在 pack-run 模式发布前只是一个 Coming Soon 的捆绑包 |
| 遥测、云 AI、许可证检查 | — | 均未发布 —— 这是设计决定,而不是“尚未实现”。请参阅 [PROVOCATION.md](PROVOCATION.md) |
## 它是什么
- 本地 CLI:`security-scan`
- 本地仪表盘:`security-scan dashboard`
- 位于 `~/.security-observatory` 下的本地 SQLite 历史存储
- 供本地 Agent 访问的只读 MCP server,以及一个显式的、受保护的 MCP 写入模式,用于 AI 案例解决(可选安装:`uv sync --extra mcp`)。参阅 [mcp/README.md](mcp/README.md)。
- 围绕成熟开源工具的扫描器编排层
- 将扫描器输出转换为一致原始发现格式的标准化器
- 将原始发现分组为人类可读的补救案例的案例构建器
- 用于防御性诱饵机密(称为 Honey Keys)的 honeytoken 系统
## 它不是什么
- 不是托管式安全平台
- 不是云端 AI 扫描器
- 不能替代人工审查、威胁建模或生产环境监控
- 扫描结果干净并不代表代码库绝对安全
- 不依赖于付费 API、基于 token 的分析或隐藏的 SaaS 服务
## 界面截图

*案例汇总为类别级别的手册 —— 41 个标准库 CVE 的原始发现变成了一个“升级易受攻击的依赖项”手册,包含具体步骤、实际耗时估计以及一个 AI prompt 交接,而不是 41 个单独的工单。*

*每个扫描器都标有名称及其安装状态(内置、本地检测到、托管安装、coming soon),以及限制网络访问、凭证和文件写入的逐工具策略 —— 目录就是契约;未经目录批准的内容绝不会运行。*

*代码库快照、历史记录和活跃的原始发现都存储在 `~/.security-observatory` 下的本地 SQLite 中;设置页面向你展示仪表盘本地保留的数据,并强调除非你主动导出,否则报告绝不会离开本机。*
## 从扫描器到下一步行动
*该流水线证明了 DëvSec 能将嘈杂的扫描器输出转化为本地、可审查的下一步行动,而无需将代码库数据发送到外部。*
```
+-- on your machine --------------------------------------------------+
| |
| your repo |
| | |
| v |
| scanners |
| Semgrep | Gitleaks | TruffleHog | Trivy | OSV | Grype |
| Syft | Checkov | Medusa | ai-static | IOC-watch |
| | |
| | raw output, deduped by stable fingerprint |
| v |
| raw findings -> cases -> action level |
| scanner decision fix_now | verify | watch | info |
| evidence units | |
| v |
| recovery playbook |
| + agent-ready follow-up |
| (markdown) |
| |
| history kept in SQLite under ~/.security-observatory |
| |
+--------------------------------------------------------------------+
|
v
you paste the follow-up into your own agent
(Claude | Cursor | Aider | ...)
```
## AI 后续工作流
扫描完成后,仪表盘可以将打开的案例交给 AI agent,而其本身不会将
任何东西发送到任何地方:
```
Run scan -> AI follow-up -> import/apply resolutions -> rescan
```
使用 **AI follow-up** 选择操作、划定案例范围、复制 prompt,
然后将 agent 的 JSON 结果粘贴回 DëvSec。误报、文档示例、
已接受的风险和已验证的修复都会通过经过审计的案例决策
路径写入;不明确的案例保持打开状态。
## 当前功能
### 工具目录与安全包 (Tool Catalog and Security Packs)
DëvSec 拥有一个只读的工具目录契约,说明每个扫描器/工具的作用,它是内置的、本地检测到的、DëvSec 托管的、不可用的,还是即将推出的,以及在执行任何操作之前适用哪些安全策略。
安全包 (Security Packs) 是为特定任务精选的目录条目组,例如 Starter、Secrets、Dependencies 和 AI Agent。包绝不会削弱工具的策略:网络访问、凭证、文件写入、破坏性操作以及 Agent Lab 的可用性都来自可强制执行的目录字段,而不是友好的卡片文案。
Docker 是可选的,而不是基础。外部资产面覆盖在 MVP 中是一个 Coming Soon 占位符,且仅用于展示:没有目标输入、探测、主动侦察、安装操作、运行操作或 agent 触发的外部扫描。
请参阅 [docs/tool-catalog.md](docs/tool-catalog.md)。
### 本地代码库扫描
Security Observatory 可以扫描单个代码库、开发根目录下发现的所有代码库,或从仪表盘选择的特定代码库。
当前扫描领域:
| 领域 | 当前覆盖范围 |
| --- | --- |
| 代码安全 | 带有本地规则的 Semgrep |
| 机密 | Gitleaks、TruffleHog、Trivy 机密扫描 |
| 依赖项 | Trivy、OSV-Scanner、Grype |
| SBOM | Syft CycloneDX 输出 |
| 文件系统与容器 | Trivy 和 Grype 文件系统扫描 |
| 基础设施即代码 | Trivy 配置错误检查和 Checkov |
| AI-agent 和 MCP 风险 | 内置的确定性检查以及 Medusa |
扫描器故障是隔离的。如果扫描器缺失、超时或返回不完整的输出,扫描将被标记为部分完成,其余证据仍会被保存。
### 扫描配置
| 配置 | 命令 | 用途 |
| --- | --- | --- |
| Default | `security-scan .` | 在主要扫描器集中进行均衡的本地扫描 |
| Quick | `security-scan --quick` | 针对明显代码、机密、依赖项和 AI-agent 风险的快速基线扫描 |
| Code | `security-scan --code` | 代码漏洞检查 |
| AI | `security-scan --ai` | Agent 指令、MCP 配置、编辑器配置和代码库投毒检查 |
| Dependencies | `security-scan --deps` | 依赖项漏洞和 SBOM 生成 |
| Trust | `security-scan --trust` | 可选的基于网络的 OpenSSF Scorecard 和 Criticality 富化,用于 SBOM 组件 |
| Trust cache only | `security-scan --trust-cache-only` | 附加先前缓存的依赖项信任数据,无需网络访问 |
| Platform posture | `security-scan --platform-posture` | 可选的连接式 legitify 检查,涵盖 SCM 分支保护、工作流权限、webhooks 和平台设置 |
| Secrets | `security-scan --secrets` | 使用多个扫描器进行机密检测 |
| IaC | `security-scan --iac` | 云和基础设施配置检查 |
| Full | `security-scan --full` | 最深度的配置本地扫描;连接的基于 token 的检查仍需明确开启 |
配置可以组合使用,例如 `security-scan --secrets --deps` 或 `security-scan --deps --trust`。
### 标准化报告
每次扫描都会保存:
- 原始扫描器输出(尽可能进行脱敏处理)
- 一个标准化的 `normalized-report.json`
- 扫描器可用性和错误状态
- 严重程度和类别计数
- 来自缺失或不完整工具的证据缺口
- 0 到 100 的代码库健康分数
- 带有修复指导的人类可读安全案例
原始发现通过稳定的指纹进行去重,因此重复的扫描器证据不会导致结果虚高。
### 安全案例
应用程序将原始发现分组为案例,这些案例比扫描器原始转储更容易采取行动。
每个案例包括:
- 通俗易懂的风险描述
- 严重程度和类别
- 操作级别:`fix_now`、`verify`、`watch` 或 `info`
- 置信度级别
- 受影响的文件
- 扫描器证据
- 建议的修复步骤
- 可供 Agent 使用的后续 prompt
与前一次扫描相比,仪表盘还会跟踪案例是新增的、重复发生的还是已解决的。
### 仪表盘
仪表盘是由 Python CLI 提供服务的 React/Vite 应用程序。它在本地 `127.0.0.1` 上运行。
当前仪表盘视图:
- Overview:主要风险、最佳下一步行动、扫描覆盖范围和健康度变动
- Cases:可搜索和可过滤的安全案例
- Honey keys:创建、插入、归档和调查诱饵机密
- Tool Catalog:本地扫描器清单、安全包、安装状态和设置指南
- Agent Lab:受限的本地 Agent 建议和批准记录
- Recovery playbooks:分组的案例响应计划
- Verification:扫描器覆盖范围、缺失的检查和证明限制
- Activity:已保存的扫描、案例、Honey Key 和项目状态事件
- Reports:已保存的原始报告和 AI 交接 prompt
- Settings:本地存储、项目选择和仪表盘环境详细信息
在仪表盘中,你可以:
- 选择代码库目标
- 添加自定义代码库路径
- 运行快速、特定类别或完整检查
- 按扫描器观察扫描进度
- 下载完整的 JSON 报告
- 下载后续工作的 AI 交接 prompt
- 将案例标记为已验证、误报、已接受风险或已修复
### Honey Keys
Honey Keys 是无权限的诱饵机密,充当陷阱。它们无法在任何真实系统中进行身份验证,但被触碰时会向你发出警报。
当前的 Honey Key 支持:
- 为选定的代码库创建诱饵密钥
- 复制生成的片段以创建逼真的诱饵文件
- 默认安全地插入到 `.devsec/honeykeys/` 下的诱饵
- 仅在明确确认的情况下允许高级放置
- 拒绝覆盖现有文件
- 拒绝写入选定代码库之外
- 创建后仅存储原始密钥的安全 hash
- 记录触发事件并对请求元数据进行脱敏
- 当密钥被触发时,将受影响的项目标记为关键状态
- 调查后归档密钥
操作指南请参阅 [docs/honey-keys.md](docs/honey-keys.md)。
### 本地报告与 AI 交接
每次扫描都可以呈现为:
- 完整的标准化 JSON 报告
- 本地 HTML 报告页面
- 用于 AI 编码 Agent 的 Markdown prompt
AI 交接 prompt 是从已保存的案例和原始发现在本地生成的。它要求 Agent 在修复任何内容之前先验证扫描器证据,并包含针对机密、依赖项升级和破坏性操作的护栏。
### 可选桌面启动器
代码库包含一个可选的 macOS 桌面应用包装器,用于启动带有自己 Dock 图标的本地仪表盘。
请参阅 [docs/desktop-launcher.md](docs/desktop-launcher.md)。
### 可选 CI 模板
在 [templates/security.yml](templates/security.yml) 提供了一个入门级的 GitHub Actions 工作流。CI 支持是可选的;主要工作流是本地扫描。
## 试用
没有托管的演示 URL —— 这是设计决定的。DëvSec 在你的机器上运行,我们托管的任何演示要么要求你上传代码(这正是我们要避免的核心问题),要么显示合成数据,这无法证明任何真实的东西。
看到 DëvSec 工作的最短路径是:
```
git clone https://github.com/Christian-Katzmann/dev-security.git
cd dev-security
./install-security-observatory.sh
security-scan .
security-scan dashboard
```
克隆代码库、安装程序、扫描此代码库,然后访问位于 `http://127.0.0.1:8765` 的本地仪表盘。在较新的 Mac 上,首次扫描大约需要两分钟。
如果你想查看使用了与[界面截图](#screens)部分相同的演示数据的仪表盘,请专门针对此代码库运行扫描 —— 这些截图就是 DëvSec 扫描自身的画面。
## 安装
要求:
- 优选 macOS
- Homebrew
- Python 3.11+
- 用于 Python CLI 工具的 `uv`
- 如果重新构建仪表盘,则需要 Node.js/npm
安装 CLI、扫描器工具、本地文件夹和仪表盘资产:
```
./install-security-observatory.sh
```
安装程序是幂等的。对于编译型扫描器,它优先使用 Homebrew;对于 Python CLI(如 Checkov 和 Medusa),优先使用 `uv tool`。
CLI 包装器安装到:
```
~/.local/bin/security-scan
```
如果你的 shell 找不到它,请将以下内容添加到你的 shell 配置文件中:
```
export PATH="$HOME/.local/bin:$PATH"
```
## 用法
扫描当前代码库:
```
security-scan .
```
扫描另一个代码库:
```
security-scan ~/Dev/myrepo
```
扫描 `~/Dev` 下发现的代码库:
```
security-scan --all-repos
```
将发现限制在不同的根目录:
```
security-scan --all-repos --dev-root ~/Dev/Projects
```
运行快速扫描:
```
security-scan --quick
```
运行完整扫描:
```
security-scan --full
```
开启依赖项信任丰富功能:
```
security-scan --deps --trust
```
在没有网络访问的情况下使用缓存的依赖信任数据:
```
security-scan --deps --trust-cache-only
```
使用内置的命名活动 IOC 起始包检查当前代码库:
```
security-scan ioc .
```
使用自定义 IOC 包扫描已发现的代码库中保存的 SBOM 证据:
```
security-scan ioc --all-repos --dev-root ~/Dev/Projects --feed ~/Dev/ioc-packs/current-campaign.yaml
```
开启连接的平台安全态势检查:
```
SCM_TOKEN= security-scan --platform-posture
```
平台安全态势检查刻意独立于默认、快速、本地和完整扫描模式。它会请求 legitify 检查已解析代码库目标的 SCM 设置,然后仅在本地存储经过脱敏处理的态势状态和原始发现。如果 legitify、凭证或代码库目标不可用,扫描将被保存为部分/跳过,而不会导致整个运行失败。
当达到严重性阈值时以非零状态退出:
```
security-scan . --fail-on high
```
将 JSON 摘要打印到 stdout:
```
security-scan . --json
```
打开本地仪表盘:
```
security-scan dashboard
```
使用自定义仪表盘端口:
```
security-scan dashboard --port 8766
```
检查已安装的扫描器工具:
```
security-scan doctor
```
打印 GitHub Actions 模板:
```
security-scan template
```
打印本地调度指南:
```
security-scan schedule
```
### 安全敏感命令
少数动词具有写入、删除或抑制功能,并且被排除在默认的 `--help`
界面之外。它们在
[docs/cli-security-surface.md](docs/cli-security-surface.md) 中有完整记录 —— 包括各自的代码级防护措施:
- `security-scan reset ` — 恢复出厂设置,永久删除某个代码库的
本地数据(除非使用 `--yes`,否则需要输入确认短语;`--backup-to `
会先写入备份;`--dry-run` 用于预览计划)。
- `security-scan cases import-resolutions --repo --input --apply` —
写入 AI 案例决策;`--preview` 仅验证而不应用,并且
必须使用 `--confirm-suppression` 才能抑制 high/critical 案例。
- `security-scan vex-import` / `vex-export` — 导入/导出本地 VEX 决策。
提议 → 净室审查 → 落地代码修复的流程不是 CLI 动词;它位于
受保护的 `devsec-mcp-rw` MCP 适配器上 —— 请参阅 [mcp/README.md](mcp/README.md)。
## 本地数据
默认情况下,所有扫描数据均存储在本地:
```
~/.security-observatory/
reports/
db/
cache/
repos/
logs/
```
你可以使用以下命令覆盖主目录:
```
SECURITY_OBSERVATORY_HOME=/path/to/store security-scan .
```
仪表盘默认从 `~/Dev/Projects` 发现项目。使用以下命令覆盖:
```
SECURITY_OBSERVATORY_PROJECTS_ROOT=/path/to/projects security-scan dashboard
```
## 隐私与安全默认设置
- 报告保留在本地机器上。
- 仪表盘绑定到 `127.0.0.1`。
- 不需要云 LLM 调用。
- OpenSSF Scorecard 和 Criticality 查找仅在使用 `--trust` 时运行。
- 缓存的信任数据存储在 `~/.security-observatory/cache/dependency-trust/` 下,可通过 `--trust-cache-only` 离线重用。
- 本地扫描禁用了 Semgrep 的指标和版本检查。
- 类似机密的值在写入标准化报告之前会进行脱敏处理。
- Honey Key 触发元数据将被脱敏,并且对 body 的捕获仅保留摘要。
- 默认情况下排除生成和运行时的临时文件夹。
默认扫描排除项包括:
```
.git, .claude, .codex, .vercel, .turbo, .cache, node_modules, dist, build,
.next, out, coverage, venv, .venv, vendor, target, tmp, temp, logs,
__generated__
```
## 健康分数
引擎内部会计算一个 0 到 100 的健康分数。CLI 会打印它,JSON 报告 (`security-scan . --json`) 也会以此 0–100 的范围输出。仪表盘会将相同的值除以 10,并显示为 `/ 10`(因此 JSON 中的 33 显示为 `3.3 / 10`)。下表使用的是仪表盘的 0–10 范围。
健康分数从 10.0 开始,并减去加权风险:
| 发现类型 | 惩罚(显示范围) |
| --- | ---: |
| 机密泄露 | -4.0,上限为 -8.0 |
| Critical 漏洞 | -2.5 |
| AI-agent 或代码库投毒风险 | -1.5,上限为 -4.5 |
| High 漏洞 | -1.0,上限为 -6.0 |
| Medium 漏洞 | -0.2,上限为 -2.5 |
| Low 漏洞 | -0.05,上限为 -1.0 |
| 缺失 SBOM | -0.3 |
最终分数在显示时被限制在 0.0 到 10.0 之间(内部为 0 到 100)。
## 开发
安装仪表盘依赖项:
```
make dashboard-install
```
构建由 Python CLI 提供服务的仪表盘资产:
```
make dashboard-build
```
运行仪表盘 UI 开发服务器:
```
make dashboard-dev
```
构建并安装可选的 macOS 桌面启动器:
```
make desktop-build
make desktop-install
```
停止桌面启动器服务器:
```
make desktop-quit
```
运行测试:
```
uv run pytest
```
## 项目结构
```
src/security_observatory/ Python CLI, scanners, storage, dashboard server
src/security_observatory/rules/ Local scanner rules
dashboard-ui/ React/Vite dashboard source
src/security_observatory/dashboard/ Built dashboard assets served by the CLI
docs/ Detailed operating docs
templates/ Optional CI workflow template
tests/ Python test suite
scripts/ Dashboard and desktop launcher scripts
```
## 文档
- [安装指南](docs/setup.md)
- [架构](docs/architecture.md)
- [信任边界图](design/diagrams/trust-boundary.md) — 保持在本地的内容以及使本地优先立场得以执行的缺失路径
- [威胁模型](docs/threat-model.md) — 资产、边界、主要风险、缓解措施、已知差距
- [安全敏感 CLI 表面](docs/cli-security-surface.md) — 隐藏在 `--help` 之外的写入/删除/抑制动词,每个都有其代码级防护
- [失败模式](docs/failure-modes.md) — 误报、漏报、扫描器崩溃、规则回归、陈旧数据
- [术语表](docs/glossary.md) — finding、case、action level、confidence、honey key、evidence gap
- [架构决策](docs/decisions/) — 已接受的 ADR 以及用于考虑过但被拒绝的路径的 `REJECTED/` 文件夹
- [工具目录与安全包](docs/tool-catalog.md)
- [当前扫描器目录映射](docs/tool-catalog-current-scanners.md)
- [扫描器说明](docs/scanners.md)
- [IOC 包](docs/iocs.md)
- [添加扫描器](docs/adding-scanners.md)
- [Honey Keys](docs/honey-keys.md)
- [误报](docs/false-positives.md)
- [故障排除](docs/troubleshooting.md)
- [桌面启动器](docs/desktop-launcher.md)
- [事件日志](docs/incidents/) — 特定时间点的 IOC 扫描和产品经验教训记录
## 操作说明
- 将扫描器输出视为证据,而非真理。在更改代码之前请进行验证。
- 部分扫描仍然有用,但未安装或不可用的工具限制了应用程序能证明的内容。
- 原始机密发现应谨慎处理:先轮换,然后再清理代码或历史记录。
- Honey Keys 在被触碰时会发出警报;它们不会阻止访问,也不会识别请求背后的具体个人。
- 在大型代码库上进行完整扫描可能会很慢。当你想要快速获取基线时,请从 `--quick` 开始。
标签:DevSecOps, SQLite, StruQ, 上游代理, 对抗攻击, 敏感信息检测, 本地优先, 请求拦截, 逆向工具