clivoa/harppia
GitHub: clivoa/harppia
一款 OSINT 凭证扫描器,通过扫描多个公共来源监控与用户关键词匹配的泄漏密钥,并支持 GitHub Actions 自动化运行与 Telegram 告警。
Stars: 0 | Forks: 0
# harppia
/getUpdates`。
- 频道 ID 以 `-100` 开头。
### 4. 生成 GitHub 个人访问令牌 (PAT)
GitHub Search 和 Gist 扫描器使用 PAT 以更高的速率限制访问 API(经过身份验证的为 30 次请求/分钟,未经验证的为 10 次请求/分钟)。该 token 仅需要公开内容的读取权限。
1. 前往 **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens**。
2. 点击 **Generate new token**。
3. 设置名称(例如 `harppia-scanner`),并在 Repository access 下选择 **Public Repositories (read-only)**。
4. 复制 token。
### 5. 添加 GitHub Secrets
前往您的 repo → **Settings → Secrets and variables → Actions → New repository secret**。
| Secret | 值 | 需求方 |
|---|---|---|
| `TELEGRAM_BOT_TOKEN` | 来自 @BotFather 的 Bot token | 所有扫描器(警报) |
| `TELEGRAM_CHAT_ID` | 频道/聊天 ID | 所有扫描器(警报) |
| `GH_PAT` | 步骤 4 中的 GitHub PAT | GitHub Search, Gists |
| `SOURCEGRAPH_TOKEN` | Sourcegraph 访问 token(可选) | Sourcegraph(更高的速率限制) |
在本地运行时,请参阅 `.env.example` 获取相同的变量。Harppia 会直接读取环境变量;在您的 shell 中导出它们,或者传递 CLI 标志,例如 `--gh-pat`、`--telegram-token` 和 `--telegram-chat`。
### 6. 启用 GitHub Actions
前往您 repo 中的 **Actions** 标签页,如果出现提示,请点击 **Enable workflows**。
每个 workflow 都会在其计划时间自动运行。您也可以通过 **Actions → [workflow name] → Run workflow** 手动触发任何 workflow。
### Workflow 计划
| Workflow | 计划 | 扫描器 |
|---|---|---|
| `swaggerhub-scanner.yml` | 每 6 小时的 `:00` | SwaggerHub |
| `gist-scanner.yml` | 每 6 小时的 `:15` | GitHub Gists |
| `github-search-scanner.yml` | 每 6 小时的 `:30` | GitHub 代码搜索 |
| `formatter-scanner.yml` | 每 6 小时的 `:45` | 格式化粘贴网站 |
| `sourcegraph-scanner.yml` | 每 12 小时的 `:15` | Sourcegraph |
| `npm-scanner.yml` | 每天 `08:30` | npm registry |
| `compile-reports.yml` | 每 6 小时的 `:55` | 报告汇总 |
| `quality.yml` | push / PR / 手动 | 语法 + 单元测试 |
## 了解发现结果
### 输出结构
```
data/
swaggerhub/
2026-07-02_matches.json
github_search/
2026-07-02_matches.json
github_gists/
2026-07-02_matches.json
sourcegraph/
2026-07-02_matches.json
npm/
2026-07-02_matches.json
pastebin/
2026-07-02_matches.json ← only present when run ad-hoc
formatters_2026-07-02_matches.json
reports/
2026-07-02_credential.csv ← Telegram alerts were sent for these rows
2026-07-02_token.csv
2026-07-02_pii.csv
2026-07-02_infrastructure.csv
2026-07-02_summary.json
seen_hashes.json ← deduplication state (committed by CI)
```
当使用 CLI (`harppia.py`) 时,发现结果会打印到终端。使用 `--output` 将它们保存到文件中。`data/` 和 `reports/` 目录仅在由计划扫描器创建,或在直接运行单个扫描器时创建。
### 发现结果 schema
```
{
"source": "sourcegraph",
"keyword": "target-name",
"url": "https://sourcegraph.com/github.com/user/repo/-/blob/config/app.yml",
"repository": "github.com/user/repo",
"path": "config/app.yml",
"pattern_name": "generic_api_key",
"matched_value": "api_...alue (21 chars)",
"matched_value_hash": "c38f4f6a16...",
"category": "credential",
"timestamp": "2026-07-02T12:00:00+00:00"
}
```
默认情况下,在终端输出、保存的 JSON/CSV、报告和 Telegram 警报中,`matched_value` 会被脱敏。仅当需要确切的泄漏值以进行受控的本地分类时,才使用 `--show-secrets`。当直接运行单个扫描器模块时,仅当您特意希望将原始值写入磁盘时,才设置 `HARPPIA_SHOW_SECRETS=1`。
### 类别
| 类别 | 捕获内容 | 警报 |
|---|---|---|
| `credential` | API key、密码、私钥、数据库连接字符串、支付密钥 | Telegram + CSV |
| `token` | Bearer token、JWT、会话 ID — 常见于 API 文档中,信号较低 | 仅 CSV |
| `pii` | 电子邮件地址、CPF、CNPJ | 仅 CSV |
| `infrastructure` | IP 地址、对象存储 URL | 仅 CSV |
## 检测模式
`utils/patterns.py` 中定义了 68 种模式,涵盖:
- **云和基础设施凭证**:访问密钥 ID、secret key、服务账户标识符、存储连接字符串、对象存储 URL 和网络指标。
- **私钥**:常见的 PEM/私钥块格式及相关密钥材料指标。
- **开发和自动化 token**:源代码控制 token、包 registry token、问题跟踪器 token、bot token、webhook 和嵌入式 URL 凭证。
- **通信和通知密钥**:消息传递、电子邮件传递、电话和 bot 凭证。
- **支付和金融 API 凭证**:处理器 token、商户密钥、client ID、client secret 以及与支付相关的环境变量。
- **数据库连接字符串**:SQL、文档存储、和 JDBC 风格的带有嵌入式凭证的 URI。
- **AI 和应用平台密钥**:模型提供商 API key、后端服务密钥以及应用平台服务凭证。
- **密钥管理和可观测性值**:vault 风格的 token、监控 DSN、API token 和服务角色密钥。
- **泄漏指标**:凭证 JSON 块、证书路径、本地包认证文件以及其他高信号配置片段。
- **通用赋值**:带有误报防护的 `secret_key`、`api_key` 和 `password` 赋值模式。
### 添加模式
必须同时更新 `utils/patterns.py` 中的 `PATTERNS`(正则表达式)和 `PATTERN_CATEGORY`(类别字符串)。模块加载时的断言强制执行了这一点:
```
# 在 PATTERN_CATEGORY 中
"my_pattern": "credential",
# 在 PATTERNS 中
"my_pattern": r"MY_PREFIX_[A-Za-z0-9]{32}",
```
如果这两个字典不同步,导入时会立即引发 `AssertionError`。
## 去重
每个发现结果的哈希值为 `SHA256(source | normalized_url | pattern_name | matched_value)`,并存储在 `seen_hashes.json` 中。后续运行会跳过任何已存在的哈希值 — 同一文件中的相同密钥不会被重复警报,而同一模式的新值仍可以被检测到。
GitHub 原始 URL 会被标准化(去除 commit SHA),以便不同 commit 中的同一文件映射到同一个哈希值。
诸如 SwaggerHub 规范和 Gist 文件之类的可变源会在后续运行中重新访问,因此不会遗漏新添加的密钥。去重会抑制已经见过的值的重复警报。
CLI (`harppia.py`) 默认参与相同的去重过程。传递 `--no-dedup` 可执行忽略历史记录的全新扫描。
## 速率限制
| 来源 | 未经认证 | 已认证 |
|---|---|---|
| GitHub 代码搜索 | 10 次请求/分钟 | 30 次请求/分钟(使用 `GH_PAT`) |
| GitHub Gists 时间线 | 60 次请求/小时 | 5,000 次请求/小时(使用 `GH_PAT`) |
| SwaggerHub | 无需认证 | — |
| Sourcegraph | 免费层级(受限) | 更高限制(使用 `SOURCEGRAPH_TOKEN`) |
| npm registry | 无需认证 | — |
| Pastebin Scraping API | 需要 IP 白名单 | 需要 Pro 账户 |
扫描器在请求之间包含 `time.sleep()` 调用以保持在限制范围内。如果您添加了许多关键词:
- 减少 `scanners/github_gist.py` 中的 `TIMELINE_PAGES` 以扫描更少的 gist 时间线页面。
- 减少 `scanners/github_search.py` 中的 `EXTENSIONS` 以减少每个关键词搜索的文件类型。
- SwaggerHub 为每个关键词请求前 100 个 `BEST_MATCH` 规范。
- 默认情况下,Sourcegraph 将每个关键词的搜索结果限制为 50 个(`scanners/sourcegraph.py` 中的 `_COUNT`)。
- npm 将每个关键词的完整元数据获取限制为 50 次(`scanners/npm_registry.py` 中的 `_MAX_FULL_FETCH`)。
## 开发
运行 quality workflow 所使用的相同检查:
```
python3 -m py_compile harppia.py compile.py scanners/*.py utils/*.py tests/*.py
python3 -m unittest discover -s tests
```
测试涵盖了脱敏、去重、报告加载(所有源)、GitHub 搜索 URL/内容处理以及边界感知的关键词匹配。
## 许可证
MIT — 详见 [LICENSE](LICENSE)。
标签:ESC4, GitHub Actions, OSINT, 泄露监控, 自动化告警, 自动笔记, 逆向工具