duncanschwindt-code/website-risk-checker

GitHub: duncanschwindt-code/website-risk-checker

一个基于多源威胁情报的网站风险检测 Web 应用,通过被动查询和透明评分为用户提供 URL 安全与声誉参考。

Stars: 0 | Forks: 0

# 网站风险检测器 Website Risk Checker 是一个与 **Teens Against Scams** 相关的教育类 Web 应用程序。访客可以输入一个公开可访问的网站 URL,并通过配置的威胁情报查询和被动技术检查,获得对有限的、可观察风险指标的仔细评估。 自动化结果可能不完整、过时或不正确。低分不能保证网站是安全的,高分也不能证明存在欺诈、违法、恶意意图、所有权或犯罪行为。 ## 截图 ![Website Risk Checker 主页和结果截图的风格化占位符](https://static.pigsec.cn/wp-content/uploads/repos/cas/7f/7fc6bc0bb33148e519c2b46de8baef7193a5e9f110ef24c4f29c29ac81b6ee4a.svg) 在发布前,请将此占位符替换为已批准的部署截图。不要包含真实的 API 密钥、私有 URL、活跃的恶意 URL 或个人信息。 ## 首个版本的功能 - 仅接受公开的 `http` 和 `https` 地址。 - 在显示、记录、缓存或进行提供商查询之前,移除 URL 查询字符串和片段。 - 拒绝嵌入式凭据、内部名称、私有/保留地址、非标准端口和不安全的重定向。 - 在连接目标之前重新解析并验证 DNS,然后锁定已验证的地址。 - 使用有限的 `HEAD` 请求和可选的 TLS 握手;它不执行页面 JavaScript 或下载页面内容。 - 在一个 TypeScript 接口背后规范化提供商结果。 - 使提供商故障、缺失密钥、过期结果和配额耗尽不对评分产生影响。 - 将扫描结果保留在浏览器标签页的会话存储中,而不是公共或服务器端历史记录中。 - 区分实时模式和演示模式;演示案例使用保留域名和本地固定数据。 - 在 [`config/scoring-rules.json`](config/scoring-rules.json) 发布透明、带版本的评分文件。 - 包含一个私密的纠正邮件工作流,该工作流会生成一个参考编号而不存储表单。 它是一个声誉和风险指标工具——而不是漏洞扫描器。它从不执行端口扫描、登录尝试、表单提交、目录发现、CAPTCHA 绕过、漏洞测试、文件下载、恶意软件执行、对提交网站的浏览器自动化操作,或访问控制绕过。 ## 提供商合规性快照 该表是工程记录,而非法律建议。条款和配额可能会发生变化。每位运营者在启用提供商之前以及此后至少每 90 天必须审查链接的官方页面。以下审查于 **2026-07-30** 执行。 | 提供商 | 用途 | 需要免费密钥 | 非商业限制 | 典型配额(2026-07-30 验证) | URL 提交行为 | 隐私关注 | 默认启用 | 官方文档 | 最后验证时间 | | --------------------- | -------------------------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | Google Safe Browsing | 已知的社交工程、恶意软件和不受欢迎软件的 URL 匹配 | 是 | 是;免费的 Safe Browsing API 仅限非商业用途 | 默认项目配额;在 Google Cloud Console 中检查当前分配 | 仅查询;从不请求新扫描 | Google 声明提交的 URL 和相关数据可能会被使用和共享 | 否 | [v5 参考](https://developers.google.com/safe-browsing/reference), [条款](https://developers.google.com/safe-browsing/terms) | 2026-07-30 | | URLhaus | 已知的恶意软件分发 URL | 是 | 社区合理使用;商业或营利需求可能需要付费的增强访问权限 | 合理使用;固定的单次查询配额未公开承诺 | 仅查询;不提交恶意软件 URL | 披露了经编辑的查询 URL;社区数据有其自身的条款 | 否 | [社区 API](https://urlhaus.abuse.ch/api/) | 2026-07-30 | | PhishTank | 社区钓鱼数据库 | 实际速率限制需要 | 官方条款允许商业 API 数据使用 | 响应头中返回的动态小时限制;HTTP 509 表示超过限制 | 仅查询;不提交报告 | 披露了经编辑的查询 URL;社区提交可能包含错误 | 否 | [API](https://phishtank.org/api_info.php), [条款](https://phishtank.org/terms.php) | 2026-07-30 | | LevelBlue Labs OTX | 社区威胁情报脉冲 | 是 | 是;OTX 对终端用户免费用于非商业用途 | 未找到固定的公开数量;监控当前账户条款和响应头 | 仅指标查询;不提交内容 | OTX 条款允许保留、使用和分发提交的内容;本项目避免使用提交接口 | 否 | [DirectConnect](https://otx.alienvault.com/api), [OTX EULA](https://www.levelblue.com/legal/otx-eula-terms) | 2026-07-30 | | VirusTotal Public API | 现有的聚合 URL 分析报告 | 是 | 是;Public API 仅限非商业用途,不适用于业务工作流 | 4 次请求/分钟,每天 500 次 | 仅查询现有报告;不重新扫描 URL,不上传文件 | 请求了 URL 标识符;新提交将被共享,因此已禁用 | 否 | [Public vs Premium](https://docs.virustotal.com/reference/public-vs-premium-api), [URL 报告](https://docs.virustotal.com/reference/url-info) | 2026-07-30 | 完整的机器可读审查位于 [`config/provider-compliance.json`](config/provider-compliance.json)。它记录了每个适配器的署名、 保留、缓存、提交隐私、审查日期和运营者备注。 ### 非商业用途警告 `PROJECT_USE_MODE=noncommercial` 是默认设置。Google Safe Browsing、OTX 和 VirusTotal Public API 仅限于非商业用途。对于商业或营利用途,URLhaus 社区访问可能需要商业协议。 受限制的适配器拒绝商业模式。 添加广告、付费订阅、付费访问、赞助安排、数据销售或其他收入可能会改变资格,即使项目仍 具有教育或非营利性质。 在任何商业化之前: 1. 禁用受限制的适配器; 2. 直接从每个提供商获取书面许可或适当的套餐; 3. 审查隐私、署名和再分发义务; 4. 更新合规文件和公开披露。 应用程序永远不会自动切换到付费提供商或规避限制。 ## 架构 ``` Browser form │ public URL only; warning shown before submit ▼ Next.js route handler ── application rate limit + same-origin check │ ├── normalize and redact ── remove query/fragment; reject credentials/ports │ ├── DNS safety gate ── reject private/reserved targets │ ├── passive checker ── DNS recheck + pinned HEAD + redirect validation + TLS │ └── provider adapters ── fixed official endpoints; lookup only; bounded JSON │ ▼ normalized evidence ── transparent scoring ── device-local result page ``` 有关安全边界和权衡,请参阅 [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) 和 [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md)。 ## 仓库结构 ``` app/ Next.js pages and server route handlers components/ Accessible UI components config/ Scoring and provider compliance records docs/ Architecture, deployment, threat model, checklists lib/analysis/ Local heuristics, orchestration, transparent scoring lib/providers/ Independent provider adapters and schemas lib/security/ SSRF defenses, rate limits, redaction, bounded requests tests/ Unit, integration, fixtures, and Playwright tests .github/ CI, CodeQL, Dependabot, templates, policy files ``` 初始的隐私最小化版本不需要数据库,因此有意不包含 Prisma 和 SQLite。如果以后添加持久化的纠正存储, 请仅在本地开发中使用带有 SQLite 的 Prisma,并为部署的环境选择生产级的托管数据库。在启用存储之前, 请记录保留、加密、删除、授权、迁移和法律依据。 ## 本地设置 要求: - Node.js 24 或更高版本 - pnpm 11 或更高版本(推荐使用 Corepack) - 演示模式或测试不需要真实的提供商密钥 ``` git clone https://github.com/YOUR-ORG/website-risk-checker.git cd website-risk-checker corepack enable pnpm install --frozen-lockfile cp .env.example .env pnpm dev ``` 打开 [http://localhost:3000](http://localhost:3000)。要进行完全本地、无网络的产品 演示,请在 `.env` 中设置 `APP_MODE=demo`。 ### 环境变量 | 变量 | 是否必需 | 用途 | | ---------------------------------- | -------------------- | --------------------------------------------------------------------------- | | `APP_MODE` | 是 | `live` 或 `demo`;demo 仅接受内置示例案例 | | `PROJECT_USE_MODE` | 是 | `noncommercial` 或 `commercial`;受限适配器拒绝商业模式 | | `APP_BASE_URL` | 生产环境 | 用于同源检查和元数据的精确公共源 | | `ENABLE_*` | 每个提供商 | 对每个提供商明确选择启用;默认均为 `false` | | `*_API_KEY` / `URLHAUS_AUTH_KEY` | 每个启用的提供商 | 仅服务器端凭据;切勿以 `NEXT_PUBLIC_` 作为前缀 | | `STRICT_PROVIDER_TERMS` | 推荐 | 在严格模式下拒绝逾期的提供商 | | `PROVIDER_REVIEW_MAX_AGE_DAYS` | 否 | 警告前的最大审查间隔;默认为 90 天 | | `APP_RATE_LIMIT_*` | 是 | 实例级防滥用限制;多实例生产环境请使用共享存储 | | `PROVIDER_MAX_RETRIES` | 否 | 针对 timeout、网络故障和 HTTP 5xx 的有限重试次数;默认为 1 | | `PROVIDER_RETRY_BASE_MS` | 否 | 初始指数退避延迟;默认为 250 毫秒 | | `TRUST_PROXY` | 视生产环境而定 | 仅在配置的可信代理后信任 `X-Forwarded-For` | | `RATE_LIMIT_HASH_SECRET` | 生产环境 | 至少 32 个随机字符,用于 HMAC 短期速率限制密钥 | | `CORRECTION_EMAIL` | 发布前 | 纠正工作流使用的私密收件箱 | | `PRIVACY_EMAIL` / `SECURITY_EMAIL` | 发布前 | 私密运营者联系方式 | | `LEGAL_CONTACT` | 发布前 | 运营者提供的法律联系信息 | 请审查 [`.env.example`](.env.example) 中的每个值。切勿提交 `.env`。 ## 获取免费访问权限 仅使用官方提供商页面。构建、测试或运行演示模式不需要密钥。 - **Google Safe Browsing:** 请遵循官方 [入门指南](https://developers.google.com/safe-browsing/v4/get-started) 和当前的 [v5 参考](https://developers.google.com/safe-browsing/reference)。在启用前确认非商业资格和当前配额。 - **URLhaus:** 通过 [官方社区 API 页面](https://urlhaus.abuse.ch/api/) 创建免费的 Auth-Key。确认合理使用资格。 - **PhishTank:** 完成免费注册并获取 [官方 FAQ](https://phishtank.org/faq.php) 中描述的应用程序密钥。请尊重速率限制响应头。 - **OTX:** 创建 OTX 账户并从 [官方 API 页面](https://otx.alienvault.com/api) 获取 DirectConnect 密钥。确认非商业资格。 - **VirusTotal:** 获取 [入门](https://docs.virustotal.com/reference/getting-started) 中描述的 Community API 密钥。Public API 不能用于商业目的, 且不能通过跨账户来规避限制。 不要为了满足此仓库而输入信用卡、激活付费试用或接受付费套餐。如果提供商的免费途径或资格发生变化, 请保持适配器禁用并更新合规记录。提供商的定价和注册要求可能随时更改。 ## 实时模式和演示模式 ### 实时模式 `APP_MODE=live` 接受公开 URL,执行本地安全闸门,列出每个提供商状态, 并使用真实时间戳。缺失密钥将返回 `NOT_CONFIGURED`;它绝不会触发虚假结果或降低评分。 ### 演示模式 `APP_MODE=demo`: - 在每个页面上显示持久的模拟数据横幅; - 拦截 `/api/analyze`; - 仅接受 `/api/demo` 处的内置案例 ID; - 使用保留的 `.test` 名称和模拟提供商数据; - 不执行实时提供商或目标请求。 `/demo` 页面在实时部署中也可用,并保持清晰标记。 ## 评分 四个谨慎的类别是: - 0–24:**观察到的风险较低** - 25–49:**建议谨慎** - 50–74:**观察到的风险升高** - 75–100:**强烈警告指标** 强烈的当前数据库匹配比本地格式启发式方法具有更高的权重。所有弱 启发式方法合计上限为 24 分,因此它们无法独立产生风险升高或最大风险的结果。错误和不可用的来源总是贡献零分。 在更改任何权重之前,请阅读 [`SCORING.md`](SCORING.md) 和 [`config/scoring-rules.json`](config/scoring-rules.json)。评分更改 需要测试、误报分析、版本升级和文档记录。 ## 测试和质量检查 所有自动化测试均使用模拟提供商、本地 fixture、保留的示例域名和测试 DNS 解析器。它们从不访问真实的钓鱼、诈骗、恶意软件或漏洞利用网站。 ``` pnpm format:check pnpm lint pnpm typecheck pnpm test:unit pnpm test:integration pnpm build pnpm test:e2e:install pnpm test:e2e pnpm audit ``` 使用 `pnpm check` 一起运行常见的非浏览器检查。Playwright 会单独 安装浏览器,并有意不隐藏在构建脚本中。 ## Docker ``` cp .env.example .env docker compose build --pull docker compose up ``` 打开 [http://localhost:3000](http://localhost:3000)。最终镜像以非特权用户身份运行, 舍弃 Linux capabilities,在 Compose 中使用只读根文件系统,并包含健康检查。 停止它: ``` docker compose down ``` ## 部署 GitHub 应托管源代码仓库,而不是实时的服务器应用程序。实时部署 需要服务器端路由处理和密钥存储,因此 GitHub Pages 不是主要 部署目标。如果稍后添加静态 Pages 构建,它必须是一个清晰标记且没有 钥的演示。 请使用支持服务器的平台或容器主机,并遵循 [`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md)。至少: 1. 审查当前的提供商条款和免费/非商业资格; 2. 仅在平台的密钥管理器中配置已批准的提供商密钥; 3. 设置准确的 HTTPS `APP_BASE_URL`; 4. 对多实例部署使用共享速率限制器; 5. 尽可能使用网络出站控制来隔离出站检查; 6. 配置私密的纠正、隐私和安全联系方式; 7. 测试 SSRF、DNS rebinding、重定向、配额、错误和密钥脱敏; 8. 完成法律文件的律师审查; 9. 启用依赖项更新、CodeQL、密钥扫描和分支保护。 ## 隐私设计 - 没有账户、个人资料、广告追踪器、公共评论或公共扫描历史。 - 此版本中没有永久性扫描存储。 - 查询字符串和片段会被尽早丢弃。 - 结果保留在特定标签页范围的浏览器会话存储中,直到被清除或标签页关闭。 - 提供商缓存密钥是单向 hash;在提供商条款允许的情况下,值会在内存中过期。 - 原始 IP 地址不作为速率限制密钥保留。 - 从不提交未知 URL 进行新分析。 - 纠正表单会创建私密邮件草稿,不会由应用程序存储。 请阅读 [`PRIVACY.md`](PRIVACY.md)。运营者必须根据其实际的主机、日志、子处理者、 司法管辖区和保留行为对其进行更新。 ## 安全设计 安全控制包括 Zod 输入和提供商 schema、通过 React 进行的输出编码、CSP 和 安全标头、POST 路由上的同源检查、大小和时间限制、结构化日志脱敏、 仅服务器端密钥、每用户应用程序限制、每个提供商的请求计数器和队列、有界 指数退避、手动重定向、DNS 重查、IP 范围拒绝、地址锁定和安全 错误消息。内置的 VirusTotal 队列也会在其记录的每日 500 次请求限制处停止; 来自任何提供商的 HTTP 429/509 响应都会停止进一步的工作,且不对评分产生影响。 请阅读 [`SECURITY.md`](SECURITY.md) 和 [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md)。SSRF 防御是 分层的,但无法保证完美保护;仍建议进行生产环境出站隔离。 ## 纠正流程 每个结果都链接到 `/corrections`。所有者或授权代表可以请求: - 进行全新的自动检查; - 审查可能不准确或已过期的结果; - 确认之前遭到入侵的站点已修复; - 删除不必要保留的信息。 该应用程序会生成一个参考编号和一封私密邮件草稿。它不公开争议,也不存储 表单,并且不保证请求会改变评分。请在发布前配置 `CORRECTION_EMAIL`。 切勿将纠正引导至公共 GitHub issue。 ## 法律文件 该仓库包含 `DISCLAIMER.md`、`TERMS.md` 和 `PRIVACY.md` 作为谨慎的技术草案。 在公开发布之前,它们需要律师审查,特别是: - 运营者身份和联系信息; - 生效日期; - 适用法律和争议解决; - 赔偿语言; - 保修和责任限制; - 适用于儿童、非营利组织、网络安全服务和隐私的法律; - 每个提供商的 API/数据条款和所需署名。 任何技术设计、免责声明、开源许可证、条款文档或隐私政策都无法 保证零责任。不要声称该项目是“防诉讼的”。 ## GitHub 仓库设置 创建一个空的 GitHub 仓库后: ``` git init git add . git commit -m "Initial Website Risk Checker release" git branch -M main git remote add origin https://github.com/YOUR-ORG/website-risk-checker.git git push -u origin main ``` 然后: 1. 保护 `main` 分支并要求进行 CI 和 CodeQL 检查; 2. 要求至少一次审查并解决所有对话; 3. 启用私密漏洞报告; 4. 在可用时启用密钥扫描和推送保护; 5. 启用 Dependabot 安全更新; 6. 禁止 Actions 在分叉的 Pull Request 上访问生产环境密钥; 7. 添加仓库主题并替换运营者占位符; 8. 执行[发布前检查清单](docs/PRE_LAUNCH_CHECKLIST.md)。 ## 许可证和第三方材料 源代码在 [MIT 许可证](LICENSE) 下提供。MIT 许可证**不会**取代 网站条款、隐私披露、第三方 API 条款、数据许可、负责任的运营、 安全防护措施或律师审查。开源许可不会消除责任。 提供商数据和提供商名称受其自身条款管辖,不会根据 MIT 重新授权。 请参阅 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。 ## 路线图 - 独立的安全审查和针对 SSRF 的渗透测试。 - 运营者批准的生产级速率限制后端。 - 在进行单独审查后,提供可选的注重隐私的 Safe Browsing 本地列表模式。 - 审查翻译工作流以确保准确性和可读性。 - 带有明确保留和删除控制的、受审核的私密纠正案例管理。 - 针对提供商条款审查的定期自动化提醒。 公共指控板、用户评分的黑名单、漏洞扫描、未知 URL 提交、 文件分析和公共扫描历史明确不在范围之内。 ## 维护者检查清单 - [ ] 重新审查每个提供商的官方条款、配额、定价、署名和隐私行为。 - [ ] 确认非商业资格并确保 `PROJECT_USE_MODE` 如实反映。 - [ ] 禁用任何条款已更改或无法确认的适配器。 - [ ] 替换所有运营者、联系信息、司法管辖区、日期和部署占位符。 - [ ] 完成法律文件的律师审查。 - [ ] 运行格式化、lint、类型检查、单元、集成、构建、E2E、审计和容器检查。 - [ ] 测试私有/保留 IP、DNS rebinding、重定向到内部目标以及 timeout。 - [ ] 配置可信代理行为、共享应用程序限制和提供商配额。 - [ ] 验证密钥永远不会出现在浏览器包、日志、错误、截图或 CI 工件中。 - [ ] 确认纠正请求保持私密,并且保留披露符合实际情况。 - [ ] 启用分支保护、CodeQL、依赖项审查、Dependabot 和密钥扫描。 - [ ] 将完成的审查记录在 `config/provider-compliance.json` 和 `CHANGELOG.md` 中。
标签:TypeScript, URL风险检测, 反取证, 威胁情报, 安全插件, 安全评估, 开发者工具, 特征检测, 自动化攻击