WimLee115/wimsalabim
GitHub: WimLee115/wimsalabim
一款完全本地运行、默认被动且具备授权门控机制的网站安全与隐私侦察工具,生成可签名、可验证的审计级报告。
Stars: 0 | Forks: 0

# `wimsalabim`
### **诚实、可审计级别的网站安全与隐私侦察。**
#### *意图即代码 · 证据即输出 · 没有机器学习的Cargo Cult · 没有遥测*
[](LICENSE)
[](https://www.python.org/downloads/)
[](https://github.com/WimLee115/Privacy-VerzetNL)
[](.github/workflows/ci.yml)
[](#testing--coverage)
[](#typing)
[](#linting)
[](#security-audit)
[](#privacy-guarantees)
[](#cryptographic-integrity)
[](#output-formats)
## 一句话概述
## 目录
|
**入门指南**
- [为什么选择 `wimsalabim`](#why-wimsalabim)
- [30 秒教程](#30-second-tour)
- [安装](#installation)
- [快速开始](#quick-start)
**功能特性**
- [十大升级](#the-ten-upgrades)
- [内置分析器](#built-in-analyzers)
- [输出格式](#output-formats)
- [授权路径](#authorization-paths)
- [密码学完整性](#cryptographic-integrity)
- [监控列表模式](#watchlist-mode)
**内部机制**
- [架构](#architecture)
- [Schema 与契约](#schema--contracts)
- [风险引擎](#the-risk-engine)
- [插件开发](#plugin-development)
- [隐私保障](#privacy-guarantees)
|
**运维指南**
- [配置](#configuration)
- [性能与资源](#performance--resources)
- [故障排除](#troubleshooting)
- [常见问题解答](#faq)
**合规性**
- [法律合规](#legal-compliance)
- [威胁模型](#threat-model)
- [安全审计](#security-audit)
**开发指南**
- [作为库使用](#use-as-a-library)
- [贡献指南](#contributing)
- [测试与覆盖率](#testing--coverage)
- [发布流程](#releasing)
- [路线图](#roadmap)
**参考信息**
- [与其他工具的对比](#comparison-with-other-tools)
- [许可证](#license)
- [引用](#citation)
- [致谢](#acknowledgements)
|
## 为什么选择 `wimsalabim`
网站安全扫描器领域已经非常拥挤。大多数工具不外乎以下三类:
| 类别 | 示例 | 问题 |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------- |
| **SaaS 扫描器** | SecurityHeaders, SSL Labs, Detectify | 会将你的目标列表发送给第三方。用于公开规范检查没问题;但不适用于敏感范围。 |
| **大型攻击性框架** | Nuclei, Burp, ZAP | 默认采取主动行为。功能强大,但前提是你了解自己的法律边界。 |
| **单域名 CLI 工具** | sslyze, testssl.sh, dnsrecon | 各管一摊。需要你自己拼凑。 |
`wimsalabim` 则属于另一个类别:**一个单一且固执己见的 CLI 工具,它:**
1. **完全在本地运行** —— 没有向 SaaS 的扇出,没有遥测,没有分析。
2. **默认被动** —— 主动分析器会拒绝运行,除非你证明已获授权。
3. 生成**经过签名的、确定性的、机器可读的报告**,可作为取证证据。
4. 使用**透明的基于规则的风险引擎** —— 每一个评分对于非技术读者(或法官)都是可解释的。
5. 附带**严格的类型检查、测试和安全审计**,使工具本身达到它对目标所要求的标准。
如果你需要一个能经得起偏执的 CISO 代码审查的扫描器,就是它了。
## 30 秒教程
```
# 安装
pipx install wimsalabim
# 扫描域名(仅被动扫描 — 适用于任何目标)
wimsalabim scan example.com
# 获取用于 CI 的 JSON
wimsalabim scan example.com --format json -o report.json
# 签名报告 (Ed25519)
wimsalabim keys init
wimsalabim scan example.com --sign --format json -o signed.json
wimsalabim verify signed.json # → ✓ valid
# 主动端口扫描(需要授权证明)
wimsalabim scan example.com \
--auth-self-owned ./my-domains.txt \
--enable ports
```
示例输出:
```
─────────────────────────── wimsalabim · example.com ───────────────────────────
target example.com started 2026-05-10T02:04:30Z duration 363 ms
dns_recon grade A 1 finding(s) 205 ms
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ sev ┃ id ┃ title ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ low │ dns.caa.absent │ No CAA record │
└──────────┴────────────────┴───────────────┘
headers grade D 7 finding(s) 351 ms
[…]
╭─────────────────── RISK B 28.0/100 engine=rules ────────────────────╮
│ Grade B (28.0/100) — 1 high — 4 rule(s) fired total. │
│ ● WSL-HEADERS-001 +12 Strict-Transport-Security header missing │
│ → HSTS absent — downgrade attacks possible on first connect. │
│ […] │
╰─────────────────────────────────────────────────────────────────────────╯
```
## 安装
### 推荐:`pipx`
```
pipx install wimsalabim
```
### 备选:虚拟环境中的 `pip`
```
python -m venv .venv
source .venv/bin/activate
pip install wimsalabim
```
### 从源码安装
```
git clone https://github.com/WimLee115/wimsalabim.git
cd wimsalabim
pip install -e ".[dev]"
```
### 可选依赖
| 功能 | 安装命令 |
| ---------------------- | ---------------------------------------------------- |
| OpenTimestamps 锚点 | `pipx install opentimestamps-client` |
| Tor 传输 | 运行中的本地 Tor 守护进程(端口 9050) |
### 支持的环境
| 操作系统 | Python | 状态 |
| ---------- | --------------------------------- | ------ |
| Linux | 3.10 / 3.11 / 3.12 / 3.13 | ✓ CI |
| macOS | 3.10 / 3.11 / 3.12 / 3.13 | ✓ CI |
| Windows | 3.10 / 3.11 / 3.12 / 3.13 | ✓ CI |
| FreeBSD | 3.11+ | 尽力支持 |
## 快速开始
```
# 显示帮助和全局选项
wimsalabim --help
# 列出所有已注册的 analyzers 及其法律类别
wimsalabim analyzers
# 纯净的被动扫描(DNS + TLS + headers,无端口扫描)
wimsalabim scan example.com
# 选择特定的 analyzers
wimsalabim scan example.com --enable dns_recon --enable headers
# 跳过嘈杂的项
wimsalabim scan example.com --disable headers
# 输出格式
wimsalabim scan example.com --format json
wimsalabim scan example.com --format markdown
wimsalabim scan example.com --format sarif
# 在终端渲染的同时保存报告
wimsalabim scan example.com --format json -o report.json
# 验证已签名的报告
wimsalabim verify signed-report.json
# 管理签名密钥
wimsalabim keys init
wimsalabim keys show
```
## 十大升级
`wimsalabim v0.2.0` 是对 v0.1 的彻底重构。以下每一个支柱都是对先前设计的深思熟虑后的偏离:
| # | 支柱 | 实现方式 |
| -- | ------------------------------------- | ----------------------------------------------------------------------------- |
| 01 | **授权门控** | 主动分析器在没有经过验证的证明下会拒绝运行。参见[法律合规](#legal-compliance)。 |
| 02 | **溯源引擎** | 每个 `Finding` 都带有一个 `Source` 块(类型、目标、时间戳、正文哈希)。 |
| 03 | **加密签名报告** | 基于 RFC-8785 规范 JSON 的 Ed25519 签名;可选 OpenTimestamps 锚点。 |
| 04 | **诚实风险引擎** | 基于规则、可追溯、可解释。没有带硬编码 `training_samples=500` 的 `IsolationForest` 装饰。 |
| 05 | **插件架构** | `@analyzer(...)` 装饰器 + 能力清单;显式注册。 |
| 06 | **标准感知导出** | SARIF 2.1.0、规范 JSON、GitHub 风格 Markdown、富终端。 |
| 07 | **监控列表模式** | SQLite 快照 + 随时间推移的差异检测。 |
| 08 | **隐私优先设计的基础设施** | 在 HTTP 客户端层面强制执行的遥测黑名单;默认隐去 WHOIS 个人身份信息(PII)。 |
| 09 | **严格的 QA** | `mypy --strict`,`ruff` 40 多条规则集,`bandit`,`pip-audit`,≥ 70% 测试覆盖率。 |
| 10 | **华丽的 TUI** | Rich 实时渲染、颜色分级、结构化面板。 |
## 内置分析器
| 分析器 | 法律类别 | 用途 |
| ------------ | ----------- | ---------------------------------------------------------------------- |
| `dns_recon` | passive | A / AAAA / MX / NS / TXT / SOA / CNAME / CAA + DNSSEC 状态 |
| `tls` | passive | 单次 TLS 握手;叶证书有效性、过期时间、协议、密码套件 |
| `headers` | passive | 单次 GET 请求;安全与信息泄露头 |
| `ports` | **active** | 在保守的端口集上进行异步 TCP 连接扫描(需要授权) |
**法律类别语义:**
- **passive** —— 仅使用公开数据(DNS、CT、WHOIS、单次 GET 请求、单次 TLS 握手)。不属于荷兰法律 Sr 138ab 所规定的 "binnendringen"(非法侵入)。
- **active** —— 执行超出普通客户端范畴的网络探测。除非 `Authorization` 证明操作者拥有目标所有权或正在运行授权的漏洞赏金计划,否则将被拒绝执行。
- **intrusive** —— 可能会改变或给目标状态造成压力的任何操作。除非获得授权**并且**提供了 `--allow-intrusive`,否则将被拒绝执行。
## 输出格式
### Rich(默认)
带颜色编码、表格化的终端输出,并在最后附带一个风险面板。支持 `NO_COLOR` 和 `TERM=dumb` 环境变量。
### JSON(规范格式)
```
wimsalabim scan example.com --format json -o report.json
```
- RFC-8785 规范键排序(已排序,无多余空格)。
- ISO-8601 UTC 时间戳。
- Schema 版本:`wimsalabim/2.0`。
- 幂等性:相同的输入 + 相同的日内时间会产生逐字节完全相同的输出(`started_at` 除外)。
```
{
"schema_version": "wimsalabim/2.0",
"tool_version": "0.2.0",
"target": "example.com",
"started_at": "2026-05-10T02:04:30Z",
"duration_ms": 363.0,
"config_hash": "ea1b…",
"analyzers": {
"dns_recon": {
"name": "dns_recon",
"legal_class": "passive",
"status": "ok",
"report": {
"analyzer": "dns_recon",
"grade": "A",
"findings": [{"id": "dns.caa.absent", "severity": "low", …}],
"metadata": {"dnssec": true, "total_records": 9}
}
}
},
"risk": {
"engine": "rules",
"overall_score": 28.0,
"grade": "B",
"rules_fired": [{"rule_id": "WSL-HEADERS-001", …}]
}
}
```
### Markdown
GitHub 风格,适合直接发布在 PR 评论或 issue 中:
```
wimsalabim scan example.com --format markdown
```
### SARIF 2.1.0
适用于 GitHub Code Scanning、GitLab Security Dashboard、Defect Dojo:
```
wimsalabim scan example.com --format sarif -o sarif.json
# 上传至 GitHub Code Scanning:
gh codeql database upload sarif.json
```
发现项包含 CWE-id 以及(适用的)CVSS 向量,以便接收系统能正确地进行优先级排序。
## 授权路径
有三种方式可以证明你有权对目标运行主动分析器。任选其一;验证失败会有明显提示。
### 1 · 自有清单
包含每行一个主机的本地文件:
```
# my-domains.txt
example.com
api.example.com
internal.lab.example.com
```
```
wimsalabim scan api.example.com \
--auth-self-owned ./my-domains.txt \
--enable ports
```
用例:拥有独立所有权证据的开发/CI 环境。
### 2 · DNS TXT 记录
在 `_wimsalabim-auth.
` 处发布一条 TXT 记录:
```
_wimsalabim-auth.example.com. IN TXT "v=wimsalabim1 pubkey="
```
```
wimsalabim scan example.com \
--auth-dns-txt "" \
--enable ports
```
用例:每位研究人员拥有稳定公钥的漏洞赏金计划。
### 3 · Well-known 文件
将已签名的清单发布在 `https:///.well-known/wimsalabim-auth.txt`:
```
v=wimsalabim1 pubkey= sig= target=example.com
```
```
wimsalabim scan example.com \
--auth-well-known "" \
--enable ports
```
用例:偏好基于文件声明的漏洞赏金计划(HackerOne 风格)。
## 密码学完整性
### 签名
```
wimsalabim keys init
wimsalabim scan example.com --sign --format json -o signed.json
```
执行流程:
1. 报告被规范化(RFC 8785)。
2. 剥离 `signature` 和 `signing_pubkey` 字段。
3. 对剩余字节进行 SHA-256 哈希。
4. 使用 Ed25519 签名该哈希(私钥位于 `~/.wimsalabim/keys/signing.key`,权限为 0600)。
5. 将签名和公钥重新添加回 JSON 中。
### 验证
```
wimsalabim verify signed.json
```
输出:
```
✓ valid pubkey a4er2DIQ/HIwnIHp… digest 0ea1269b8089d100…
```
如果报告被篡改:
```
✗ INVALID signature
$ echo $?
2
```
### 使用 OpenTimestamps 锚定(可选)
```
# 安装上游客户端
pipx install opentimestamps-client
# 计算摘要,并加盖时间戳
sha256sum signed.json | awk '{print $1}' > signed.digest
ots stamp signed.digest
# 等待几个小时以完成升级
ots upgrade signed.digest.ots
# 根据 Bitcoin 区块头进行验证
ots verify signed.digest.ots
```
`.ots` 证明是一个锚定在比特币链上的客观可验证时间戳。无需信任任何单一方。
## 监控列表模式
`wimsalabim watch` 子命令按固定间隔重新扫描一个或多个目标,将每次结果持久化到 SQLite 基线中,并与上一次快照进行对比报告差异(新增/移除的发现项、评级变化)。
```
# 每小时扫描 example.com,默认数据库位于 ~/.wimsalabim/watch.sqlite
wimsalabim watch example.com
# 多个目标,15分钟间隔,仅打印存在差异的轮次
wimsalabim watch --interval 900 --diff-only a.example b.example
# 一次性冒烟测试(记录基线 + 退出)
wimsalabim watch --once example.com
```
在收到 `SIGINT` / `SIGTERM` 时会干净地停止。失败的扫描不会导致守护进程崩溃;它会记录错误并继续处理下一个目标。授权选项(`--auth-self-owned`、`--auth-dns-txt`、`--auth-well-known`)在启动时对每个目标进行一次验证。
### 编程式使用
```
from pathlib import Path
import asyncio
from wimsalabim.core.orchestrator import Orchestrator, OrchestratorConfig
from wimsalabim.core.authorization import AuthorizationGate
from wimsalabim.core.registry import all_analyzers
import wimsalabim.analyzers # registers built-ins
from wimsalabim.watch import BaselineStore
store = BaselineStore(Path("./baseline.sqlite"))
async def watch(target: str) -> None:
orch = Orchestrator(
config=OrchestratorConfig(target=target, enabled=("dns_recon", "tls", "headers")),
registrations=list(all_analyzers().values()),
gate=AuthorizationGate(),
)
report = await orch.run()
diff = store.diff_against_previous(report)
if diff and diff.is_meaningful:
notify(diff)
store.record(report)
asyncio.run(watch("example.com"))
```
`Diff` 对象列出了每个分析器新增的发现项、移除的发现项以及评级变化。
## 架构
```
%%{init: {'theme':'dark'}}%%
flowchart TD
CLI["CLI
(click)"]
Orch["Orchestrator
(async, per-analyzer timeout)"]
Gate["AuthorizationGate
(legal_class check)"]
HTTP["HTTP client factory
(telemetry blacklist hook)"]
Reg["Registry
(@analyzer decorator)"]
Risk["HeuristicRiskEngine
(rule-based)"]
Disp["Renderers
rich · json · md · sarif"]
Crypto["Ed25519 sign/verify
+ OTS anchor"]
CLI --> Orch
Orch --> Gate
Orch --> HTTP
Orch --> Reg
Reg -.-> A1["dns_recon"]
Reg -.-> A2["tls"]
Reg -.-> A3["headers"]
Reg -.-> A4["ports (active)"]
Orch --> Risk
Risk --> Disp
Disp --> Crypto
classDef gate fill:#221,stroke:#fc6,color:#fff
class Gate gate
```
### 模块分解
```
src/wimsalabim/
├── cli.py Click entrypoint, slim
├── analyzers/
│ ├── base.py BaseAnalyzer ABC + AnalysisContext
│ ├── dns_recon.py DNS analyzer (passive)
│ ├── tls.py TLS analyzer (passive)
│ ├── headers.py HTTP headers analyzer (passive)
│ └── ports.py TCP-connect scan (active)
├── core/
│ ├── schema.py Pydantic v2 frozen models
│ ├── exceptions.py Typed exception hierarchy
│ ├── logging.py structlog setup
│ ├── registry.py @analyzer + capabilities
│ ├── authorization.py AuthorizationGate + verification helpers
│ ├── orchestrator.py Async runner with timeouts
│ ├── http_client.py httpx factory + telemetry guard
│ ├── privacy.py WHOIS redact + telemetry blacklist
│ ├── canonical.py RFC 8785 canonical JSON
│ ├── crypto.py Ed25519 sign/verify
│ └── timestamps.py OpenTimestamps wrapper
├── risk/
│ ├── rules.py Rule registry
│ └── heuristic.py Rule executor + grading
├── display/
│ ├── rich_renderer.py Rich terminal output
│ ├── markdown.py GitHub Markdown export
│ └── sarif.py SARIF 2.1.0 export
└── watch/
└── baseline.py SQLite snapshot store + Diff
```
## Schema 与契约
分析器产生的每个 `BaseReport` 都满足此契约:
```
class BaseReport(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")
analyzer: str
target: str
started_at: datetime # always UTC
duration_ms: float # ≥ 0
grade: Grade = "N/A" # Literal["A","B","C","D","F","N/A"]
findings: list[Finding]
metadata: dict[str, str|int|float|bool]
```
每个 `Finding` 都带有溯源信息:
```
class Finding(BaseModel):
id: str # e.g. "tls.cert.expiring_soon"
title: str
description: str
severity: Severity # Literal["critical","high","medium","low","info"]
source: Source # required
cwe: str | None # CWE-NNN
cvss_vector: str | None # CVSS v4.0 if applicable
cvss_score: float | None # 0.0–10.0
remediation: str | None
references: list[str]
```
每个 `Source` 都回答了*这是从哪里来的*:
```
class Source(BaseModel):
kind: str # "http","dns","tls","ct_log","whois",…
target: str
timestamp: datetime # always UTC
body_sha256: str | None # 64-hex when applicable
metadata: dict[str, str]
```
这些是 pydantic v2 的冻结模型 —— 一旦生成,即不可变。这正是让我们能够安全地对它们进行哈希、签名和时间戳戳记的原因。
## 风险引擎
两种引擎,都很诚实:
### `--engine=rules`(默认)
分数中的每一分都可以追溯到具有 id、、CWE 和依据的已注册 `Rule`。添加规则只需向 `src/wimsalabim/risk/rules.py` 中的 `RULE_REGISTRY` 追加即可。
```
Rule(
rule_id="WSL-TLS-002",
name="TLS certificate expiring within 7 days",
severity="critical",
points=25.0,
cwe="CWE-298",
predicate=lambda r: _has_finding(r, "tls", "tls.cert.expiring_soon"),
rationale_fn=lambda _: "Leaf certificate expires within 7 days — outage risk imminent.",
)
```
评级是**严重性感知**的:任何未缓解的 Critical(严重)问题都会将最终评级拉低到 D 或更差,即使原始分数总和落在 C 区也是如此。这反映了理性的操作者在现实中如何对待 Critical 级别问题。
### `--engine=ml`(计划中,视条件而定)
只有当满足以下所有条件时,我们才会发布 `ml` 引擎:
- 仓库中包含真实的模型文件(`models/risk_v0.X.onnx`)并发布了 SHA-256。
- 包含 `model_card.md`,描述训练数据、特征、预期准确率和已知偏差。
- 可复现的训练:数据集哈希、训练脚本、固定种子、训练/验证/测试划分。
- 验证保留样本模型预测的测试套件。
在这些实现之前,**没有 ML 引擎**。以前版本的 "ML 模块" 只是导入了 sklearn 类却从未训练——这是不诚实的,已被移除。
## 插件开发
### 编写你自己的分析器
```
# my_org/scanners/cookie_audit.py
from datetime import datetime, timezone
from wimsalabim.analyzers.base import AnalysisContext, BaseAnalyzer
from wimsalabim.core.exceptions import NetworkError
from wimsalabim.core.registry import Capabilities, analyzer
from wimsalabim.core.schema import BaseReport, Finding, Source
@analyzer(
"cookie_audit",
legal_class="passive",
capabilities=Capabilities(network=("https",), rate_limit_per_second=2, timeout_seconds=10.0),
description="Inspect Set-Cookie attributes (Secure, HttpOnly, SameSite).",
)
class CookieAnalyzer(BaseAnalyzer):
async def analyze(self, context: AnalysisContext) -> BaseReport:
started = datetime.now(tz=timezone.utc)
try:
response = await context.http.get(f"https://{context.target}/")
except Exception as exc:
raise NetworkError(kind="http", target=context.target, message=str(exc)) from exc
findings: list[Finding] = []
# ... inspect response.cookies and emit findings ...
return BaseReport(
analyzer="cookie_audit",
target=context.target,
started_at=started,
duration_ms=(datetime.now(tz=timezone.utc) - started).total_seconds() * 1000,
findings=findings,
metadata={},
)
```
然后在你的项目中注册它:
```
# my_project/__init__.py
import my_org.scanners.cookie_audit # imports trigger @analyzer
```
### 能力声明
| 字段 | 用途 |
| ------------------------ | -------------------------------------------------- |
| `network` | 你将接触的协议(`dns`、`https` 等)。授权门控会参考此信息以进行法律类别的强制执行。 |
| `rate_limit_per_second` | 为编排器的限速器提供的提示(编排器级别的限速在路线图中)。 |
| `timeout_seconds` | 编排器将强制执行的每次调用软超时。 |
### 法律类别
| 类别 | 何时选择它 |
| ----------- | ------------------------------------------------------------ |
| `passive` | 你只读取公开数据(DNS、CT、单次 GET、单次 TLS 握手)。 |
| `active` | 你的探测超出了普通客户端的范畴。 |
| `intrusive` | 你可能会改变目标状态(写入、模糊测试、负载)。 |
如果有疑问:选择更严格的选项。框架将拒绝在未证明授权的情况下运行你。这比引入法律风险要好。
## 隐私保障
```
┌────────────────────────────────────────────────────────────────┐
│ │
│ 1. No telemetry. No analytics. No phone-home. Ever. │
│ 2. WHOIS PII (registrant name/email/phone) redacted unless │
│ --show-pii is explicitly set. │
│ 3. Bodies hashed up to 64 KB; full content never stored or │
│ transmitted. │
│ 4. Reports stored locally; signing keys local + 0600. │
│ 5. --via-tor routes both HTTP and DNS via SOCKS5+Tor. │
│ 6. --offline forbids any outbound network call. │
│ │
└────────────────────────────────────────────────────────────────┘
```
验证依据:
- `core/privacy.TELEMETRY_BLACKLIST` 通过 `make_client()` 中的 httpx 事件钩子强制执行。
- `tests/test_no_telemetry.py`(21 个用例)静态禁止导入已知的遥测 SDK。
- `tests/test_privacy.py` 验证隐去逻辑。
## 配置
### 完整的 CLI 标志
```
Usage: wimsalabim scan [OPTIONS] TARGET
Options:
-e, --enable TEXT Enable only these analyzers (repeatable).
-d, --disable TEXT Disable these analyzers (repeatable).
--via-tor Route HTTP via local Tor SOCKS5 (127.0.0.1:9050).
--offline Forbid any outbound network call.
--show-pii Do not redact PII (use only on data you own).
--allow-intrusive Permit intrusive analyzers (extra confirmation).
--auth-self-owned PATH Path to self-owned domains manifest.
--auth-dns-txt TEXT Verify _wimsalabim-auth. TXT record.
--auth-well-known TEXT Verify /.well-known/wimsalabim-auth.txt manifest.
--format [rich|json|markdown|sarif]
Output format (default: rich).
-o, --output PATH Write report to file (also rendered to stdout).
--sign Sign the report (Ed25519).
--keys-dir PATH Signing key directory (default: ~/.wimsalabim/keys).
--verbose / --quiet
-h, --help Show this message and exit.
```
### 环境变量
| 变量 | 效果 |
| ------------------------ | ----------------------------------------------------------- |
| `NO_COLOR` | 禁用 Rich 渲染中的颜色。 |
| `WIMSALABIM_KEYS_DIR` | 覆盖默认的 `~/.wimsalabim/keys`(计划在 v0.3 中实现)。 |
### 配置文件(计划在 v0.3 中实现)
`~/.config/wimsalabim/config.toml` 将允许持久化标志。在 v0.2.0 中,所有配置均通过 CLI 标志进行。
## 性能与资源
以下数据来自在家庭宽带下对 `example.com` 的被动扫描:
| 指标 | 值 |
| --------------------- | ---------------------- |
| 实际耗时 | ~360 毫秒 |
| 并发分析器 | 3(通过 asyncio 并行) |
| 峰值内存 | ~25 MB |
| 出站 HTTP | 向 `https://target/` 发起 1 次 GET 请求 |
| 出站 DNS | 9 次记录查询 |
| 出站 TLS | 1 次握手 |
| 磁盘 I/O | 1 次 SQLite 写入(如果在监控模式下),1 个 JSON 文件(如果指定了 `-o`) |
`ports` 分析器的耗时随端口列表大小而变化;对于响应及时的主机,默认的 23 个端口可在 1-3 秒内完成。
## 作为库使用
```
import asyncio
from wimsalabim.core.orchestrator import Orchestrator, OrchestratorConfig
from wimsalabim.core.authorization import AuthorizationGate
from wimsalabim.core.registry import all_analyzers
from wimsalabim.risk.heuristic import HeuristicRiskEngine
import wimsalabim.analyzers # register built-ins
async def scan(target: str) -> None:
orch = Orchestrator(
config=OrchestratorConfig(
target=target,
enabled=("dns_recon", "headers"),
),
registrations=list(all_analyzers().values()),
gate=AuthorizationGate(),
)
report = await orch.run()
risk = HeuristicRiskEngine().assess(report.analyzers)
print(report.model_dump_json(indent=2))
print("RISK:", risk.grade, risk.overall_score)
asyncio.run(scan("example.com"))
```
稳定的公共 API 接口(自 v1.0 起遵循 semver):
- `wimsalabim.core.schema` — `Source`、`Finding`、`BaseReport`、`ScanReport`、`RiskAssessment`、…
- `wimsalabim.core.orchestrator` — `Orchestrator`、`OrchestratorConfig`
- `wimsalabim.core.authorization` — `AuthorizationGate`、`Authorization`
- `wimsalabim.core.registry` — `analyzer` 装饰器、`Capabilities`、`all_analyzers`
- `wimsalabim.risk.heuristic` — `HeuristicRiskEngine`
- `wimsalabim.display` — `render_rich`、`render_markdown`、`render_sarif`
- `wimsalabim.watch` — `BaselineStore`、`Diff`
## 法律合规
### 荷兰 Sr 第 138ab 条 — 计算机犯罪
`AuthorizationGate` 拒绝在没有经过验证的证明的情况下运行 `active` 和 `intrusive` 分析器。CLI 中没有逃生舱——没有 `--yolo`,也没有 `--force`。这是 *binnendringen alleen met toestemming*(仅在获得许可时侵入)原则的技术实现。
### 欧盟 GDPR / 荷兰 AVG
| 条款 | 我们的遵守方式 |
| ---------- | --------------------------------------------------------------------- |
| 第 5 条 | 数据最小化:正文被哈希处理(不存储原文),WHOIS 个人隐私信息被隐去。 |
| 第 6 条 | 我们仅处理公开数据及操作者控制的目标。 |
| 第 25 条 | 隐私保护设计:在 HTTP 客户端层强制执行遥测黑名单。 |
| 第 32 条 | 处理过程的安全性:签名报告,本地 0600 权限的密钥。 |
### 欧盟 AI 法案
`HeuristicRiskEngine` 在 AI 法案下**不属于 AI 系统**:
- 没有学习到的模型。没有训练。没有统计泛化。
- 每一个分数都确定性地源自一个已注册的规则。
- 完全可解释;没有缺乏人类可读谓词的“自动化决策”。
如果我们未来发布 `--engine=ml`,它将同样通过此可解释性测试,并附上数据集和模型卡片。
### NCSC 负责任的披露
由 `wimsalabim` 产生的发现项:
1. 生成一份带有签名的 JSON 或 SARIF 报告。
2. 发送给目标的安全联系人(首先查找 `security.txt`,然后依据 `RFC 9116`)。
3. 适用 90 天的披露窗口(行业标准),除非接收方要求更短的时间。
## 威胁模型
我们使用 STRIDE 进行自我分析。完整表格见 [`docs/PENTEST_REPORT.md`](docs/PENTEST_REPORT.md)。概要:
| 威胁 | 状态 | 缓解措施 |
| ----------------------- | ------------- | ------------------------------------------------------------ |
| 操作者身份欺骗 | 已缓解 | 授权路径要求由操作者控制的 DNS/文件。 |
| 报告被篡改 | 已缓解 | 基于 Ed25519 签名的规范 JSON + 通过 `verify` 进行篡改检测。 |
| 抵赖 | 已缓解 | 报告中的 `signing_pubkey` + `verified_at` 块。 |
| 信息泄露 | 已缓解 | WHOIS 个人隐私信息隐去,限制正文哈希,无遥测。 |
| 通过缓慢的分析器发起的 DoS | 已缓解 | 由编排器强制执行的单分析器超时。 |
| 权限提升 | 已缓解 | `AuthorizationGate.check()` 是强制性的且默认拒绝。 |
## 安全审计
完整的渗透测试报告已提交至仓库中的 [`docs/PENTEST_REPORT.md`](docs/PENTEST_REPORT.md)。
摘要:
| 工具 | 结果 |
| ------------ | --------------------------------------- |
| `mypy --strict` | 30 个源文件 0 个错误 |
| `ruff`(40 多条规则集) | 所有检查通过 |
| `bandit` | 5 个低级(OTS 中可接受的子进程),0 个中级,0 个高级 |
| `pip-audit` | 没有已知漏洞 |
| `pytest` | 118 / 118 通过 |
| 覆盖率 | 76.42%(超过 70% 阈值) |
手动审查涵盖了 SSRF、路径遍历、命令注入、正则表达式 DoS、竞态条件、机密/凭证泄露。**零 Critical 或 High 级别发现。**
## 与其他工具的对比
| 功能 | `wimsalabim` | `nuclei` | `sslyze` | `dnsrecon` | SecurityHeaders.com |
| ---------------------------------------- | ------------ | -------- | -------- | ---------- | ------------------- |
| 本地执行(非 SaaS) | ✓ | ✓ | ✓ | ✓ | ✗ |
| 默认被动且具有硬性门控 | ✓ | ✗ | n/a | n/a | ✓ |
| 签名报告 (Ed25519) | ✓ | ✗ | ✗ | ✗ | ✗ |
| OpenTimestamps 锚点 | ✓ (可选) | ✗ | ✗ | ✗ | ✗ |
| SARIF 2.1.0 输出 | ✓ | ✓ | ✗ | ✗ | ✗ |
| Pydantic 验证的 schema | ✓ | partial | ✗ | ✗ | n/a |
| 基于规则的可解释风险评分 | ✓ | (按模板) | ✗ | ✗ | ✓ (不透明) |
| WHOIS 个人隐私信息默认隐去 | ✓ | n/a | n/a | n/a | n/a |
| `mypy --strict` 纯净 | ✓ | n/a (Go) | partial | ✗ | n/a |
| 用于自定义分析器的插件 API | ✓ | ✓ | ✗ | ✗ | ✗ |
其他工具的卓越之处:
- **nuclei**:庞大的漏洞检测模板生态系统。我们是补充,而不是替代。
- **sslyze**:更深度的 TLS 分析(我们只做单次握手;sslyze 会进行密码套件枚举)。
- **dnsrecon**:更多的 DNS 模式(区域传送、暴力破解)——按设计,我们保持被动。
## 测试与覆盖率
```
make test # full suite + coverage
make lint # ruff check + format
make typecheck # mypy --strict
make audit # bandit + pip-audit
make all # everything in CI order
```
不使用 `make` 的情况下:
```
pytest -v # 118 tests
pytest --cov=wimsalabim --cov-report=term-missing # with coverage
ruff format --check src tests
ruff check src tests
mypy src
bandit -r src --severity-level low
pip-audit
```
### 类型检查
严格度:
```
[tool.mypy]
strict = true
disallow_untyped_defs = true
disallow_any_generics = true
warn_unused_ignores = true
warn_redundant_casts = true
warn_unreachable = true
no_implicit_optional = true
```
结果:整个代码库中存在 **0 个错误**。
### 代码检查
活跃的规则集:`E`、`F`、`W`、`I`、`N`、`UP`、`B`、`C4`、`SIM`、`RUF`、`ASYNC`、`TRY`、`PTH`、`PL`。结果:**0 个违规**。
## 发布流程
1. 在 `pyproject.toml` 中提升 `version`。
2. 更新 [`CHANGELOG.md`](CHANGELOG.md)。
3. 打标签:`git tag -s v0.X.Y -m "release v0.X.Y"`。
4. 推送标签:`git push origin v0.X.Y`。
5. 发布 CI 将构建 wheels + sdist,运行测试 + 审计,对构件签名,并上传到 PyPI。
(发布 CI 工作流目前处于[计划阶段](#roadmap) —— 当前通过 `make build` 在本地生成构件。)
## 路线图
```
2026 Q2 · Public release of v0.2.0 [DONE]
2026 Q2 · `wimsalabim watch` CLI subcommand [DONE]
2026 Q2 · Mock TLS server for tls.py coverage ≥ 85% [next]
2026 Q2 · Socket-mock fixture for ports.py coverage ≥ 85%
2026 Q2 · Periodic re-verification of authorization in watch sessions
2026 Q3 · CycloneDX VEX export
2026 Q3 · Mutation testing (mutmut) with ≥ 80% kill rate
2026 Q3 · Atheris fuzzing on parsers (cert, headers)
2026 Q4 · Remediation wizard (interactive --fix flow)
2026 Q4 · Shell completions (bash / zsh / fish)
2027 · PQC hybrid keys (X25519 + ML-KEM)
2027 · Distributed-watch federation across PVNL operators
```
## 故障排除
### 扫描输出中显示 `denied`
这意味着 `AuthorizationGate` 拒绝了某个主动分析器。你可以:
- 仅使用被动分析器:`--enable dns_recon --enable headers --enable tls`。
- 提供授权证明:`--auth-self-owned`、`--auth-dns-txt` 或 `--auth-well-known`。
### `OpenTimestampsUnavailable: 未找到 ots CLI`
安装上游客户端:
```
pipx install opentimestamps-client
```
OTS 锚定是可选的;`wimsalabim` 的其余部分可以在没有它的情况下正常工作。
### `NetworkError: 已拦截:目标位于遥测黑名单中`
你扫描的域名与遥测黑名单存在重叠(例如 `*.google-analytics.com`)。这是故意的 —— `wimsalabim` 不会与已监控端点通信。如果你确实需要扫描此类主机,这超出了本工具的范围。
### `httpx.ConnectError: 所有连接尝试均失败`
目标在你的网络中不可达。请检查网络连通性、DNS 和防火墙。
### 对未签名报告的签名验证失败
`wimsalabim verify` 要求同时包含 `signature` 和 `signing_pubkey` 字段。请在生成时使用 `--sign`。
## 常见问题解答
### 为什么不直接用 `nmap` + `sslyze` + `dnsrecon`?
你可以这么做。我们需要的是一个这样的工具:
- 在设计上拒绝未经授权的主动扫描。
- 生成一份单一的签名报告,而不是三个文本日志。
- 在 CI 中运行且不需要 root 权限。
### 为什么没有 GUI?
CLI 工具可以进行组合;而 GUI 不能。`--format markdown` 的输出在任何 Markdown 查看器中都能很好地渲染;SARIF 可以直接被 GitHub/GitLab 仪表盘消费。
### 为什么用 Python 而不是 Go/Rust?
速度不是瓶颈——网络 I/O 才是。带有 asyncio 的 Python 足够快,而且生态系统(pydantic、rich、structlog、click)让我们能快速获得安全性和用户体验。如果基准测试有要求,我们可能会用 Rust 重写热点路径。
### 我可以在 CI 中运行它吗?
可以。固定版本,使用 `--format sarif` 上传到 GitHub Code Scanning,并使用 `--auth-self-owned` 配合提交到你仓库的清单文件。工作流示例片段:
```
- name: Wimsalabim scan
run: |
pipx install wimsalabim
wimsalabim scan ${{ vars.TARGET_DOMAIN }} \
--auth-self-owned ./security/owned-domains.txt \
--format sarif -o sarif.json
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: sarif.json }
```
### 这能替代真正的渗透测试吗?
不能。它能抓住简单的 80%。真正的渗透测试能发现困难的 20%(身份验证流缺陷、业务逻辑错误、复杂的漏洞利用链)。请两者并用。
## 贡献指南
我们欢迎各种贡献。请阅读 [`CONTRIBUTING.md`](CONTRIBUTING.md) 和 [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)。
快速开始:
```
git clone https://github.com/WimLee115/wimsalabim.git
cd wimsalabim
make dev # creates venv, installs dev deps, hooks
make all # lint + typecheck + test + audit
```
我们正在寻找以下方面的贡献:
- 新的被动分析器(cookie 审计、security.txt、robots.txt、sitemap.xml 等)。
- `tls.py` 和 `ports.py` 的模拟夹具以提升覆盖率。
- 为现有发现项添加更多 CWE/CVSS 映射。
- 面向用户的字符串翻译(目前我们呈现的是英文)。
我们不接受以下内容:
- 没有明确授权说明的主动攻击功能。
- 遥测、分析或回传电话。
- 没有发布模型卡片作为支撑的“AI”功能。
## 安全披露
关于 `wimsalabim` 本身的漏洞:参见 [`SECURITY.md`](SECURITY.md)。90 天的披露窗口。
## 许可证
代码采用 **AGPL-3.0-or-later** 许可;文档采用 **CC BY-SA 4.0** 许可。
详见 [`LICENSE`](LICENSE)。
## 引用
如果你在学术工作中使用了 `wimsalabim`,请引用:
```
@software{wimsalabim_2026,
title = {wimsalabim: Honest, audit-grade website security and privacy reconnaissance},
author = {WimLee115},
year = {2026},
url = {https://github.com/WimLee115/wimsalabim},
note = {Under PVNL flag — Privacy Verzet NL}
}
```
提供了 `CITATION.cff` 文件,以便自动引用工具使用。
## 致谢
- `cryptography`、`pydantic`、`httpx`、`click`、`rich`、`structlog`、`dnspython` 社区提供了底层构建块。
- OpenTimestamps 团队让时间戳锚定变得简单且免费。
- OASIS SARIF 工作组制定了结果交换格式。
- 在 **PVNL** (Privacy Verzet NL) 旗帜下的同行者们——坚信隐私是一项公民权利,而非一个产品特性。
```
╔═══════════════════════════════════════════════════════════╗
║ ║
║ "Wet als code. Bewijs als output." ║
║ ║
║ CAPTAIN WIMLEE115 · MMXXVI ║
║ ║
║ PVNL · Privacy Verzet NL ║
║ ║
╚═══════════════════════════════════════════════════════════╝
```
**[文档](docs/)** · **[渗透测试报告](docs/PENTEST_REPORT.md)** · **[法律框架](docs/legal.md)** · **[PVNL 总览](https://github.com/WimLee115/Privacy-VerzetNL)**
标签:Ed25519, GraphQL安全矩阵, Python, SARIF, URL发现, 代码安全, 安全扫描器, 安全报告, 安全检测, 安全测试, 审计工具, 密码管理, 开源安全工具, 攻击性安全, 无后门, 无线安全, 无遥测, 杀软绕过, 漏洞枚举, 网站安全, 网络安全, 网络安全, 自动化侦察, 计算机取证, 运行时操纵, 逆向工具, 逆向工程平台, 隐私保护, 隐私保护, 隐私合规, 隐私验证