GP-commits/Git-Secrets
GitHub: GP-commits/Git-Secrets
这款 Python 命令行工具能深入扫描 GitHub 仓库的提交历史及当前代码,快速发现意外泄露的 API 密钥和敏感令牌。
Stars: 120 | Forks: 17
一款强大的 CLI 工具,用于扫描 GitHub 仓库中意外提交的机密信息——API 密钥、令牌、密码、私钥等。
Like a digital metal detector for your codebase. Find what shouldn't be public before someone else does.
## ⚡ 功能
## 之前的更新
- TURBO 并行扫描 —— 使用新的 --jobs 标志同时扫描多个仓库(提速 5 倍)
- 高级降噪 —— 自动跳过 venv、site-packages 和其他库文件夹
- 智能去重 —— 智能地优先处理特定类型的机密信息而非通用类型
- 交互式命令指南 —— 使用新的 --guide 标志获取所有功能的分类概览
- 20 多种机密模式 —— AWS、GitHub、Google、Stripe、Slack、Discord、Telegram、JWT、SSH 密钥、数据库 URI 等
- 完整提交历史扫描 —— 检测已提交但随后被删除的机密信息
- 可选 PAT 支持 —— 扫描私有仓库或绕过速率限制
- 清晰的 ASCII 报告 —— 极易阅读的审计日志,无表情符号或冗余命中信息的干扰
- JSON 导出 —— 适用于 CI/CD 流水线的机器可读输出
- Fork 过滤 —— 默认跳过 fork 以专注于原始代码
- CI 友好 —— 发现机密信息时以代码 1 退出
## 🏗️ 架构

### 工作原理
1. **输入** — 你提供一个 GitHub 用户名或组织名称
2. **发现** — 工具查询 GitHub API 以获取所有仓库(分页),并过滤掉 fork
3. **克隆** — 每个仓库都被克隆到一个临时目录(快速模式下使用 `--depth 1`)
4. **扫描** — 运行两次扫描:
- **文件扫描**:遍历工作树,读取每个文本文件,并根据 20 多种正则表达式模式进行匹配
- **历史扫描** *(默认)*:运行 `git log -p --all` 以检查完整提交历史中的每个新增行
5. **去重** — 合并两次扫描中相同的发现结果
6. **报告** — 打印彩色终端报告;导出可选的 JSON 文件
7. **清理** — 自动删除临时克隆目录
## 安装
### 前置条件
- **Python 3.8+** — [下载 Python](https://www.python.org/downloads/)
- **Git** — [下载 Git](https://git-scm.com/downloads)
### 设置
```
# 1. Clone 或下载此 project
git clone https://github.com/your-username/git-secrets-scanner.git
cd git-secrets-scanner
# 2. (推荐)创建一个 virtual environment
python -m venv venv
# On Windows
venv\Scripts\activate
# On macOS/Linux
source venv/bin/activate
# 3. 安装 dependencies
pip install -r requirements.txt
```
### 依赖
| Package | Purpose |
|---------|---------|
| `requests` | GitHub API 调用 |
| `colorama` | 跨平台彩色终端输出 |
## 🚀 使用方法
### 基本扫描(完整历史 —— 推荐)
```
python scanner.py
```
这会克隆每个非 fork 的仓库,并扫描当前文件**以及完整的提交历史**中的机密信息。这是最彻底的模式 —— 它可以捕获已提交但随后被删除的机密信息。
### 快速模式(仅最新提交)
```
python scanner.py --fast
```
仅扫描文件的当前状态。速度更快,但无法捕获已删除的机密信息。
### 使用 GitHub Personal Access Token
```
python scanner.py --token ghp_your_token_here
```
使用 PAT 来:
- 扫描你拥有的**私有仓库**
- 避免 GitHub API **速率限制**(未认证 60 次/小时 → 使用令牌 5,000 次/小时)
### 将结果导出为 JSON
```
python scanner.py --output report.json
```
生成结构化的 JSON 文件,以便与 CI/CD 流水线或仪表板集成。
### 包含 fork 的仓库
```
python scanner.py --include-forks
```
默认情况下,为了专注于原始代码,会排除 fork。使用此标志可包含它们。
### 详细输出
```
python scanner.py --verbose
```
显示扫描的每个文件和提交的详细进度。
### 不安全的机密显示
```
python scanner.py --unsafe-show-secrets --yes
```
### 所有选项组合
```
python scanner.py myorg \
--token ghp_xxxxxxxxxxxx \
--fast \
--output report.json \
--include-forks \
--verbose
```
### 命令行参考
```
usage: scanner.py [-h] [--token TOKEN] [--fast] [--output OUTPUT]
[--include-forks] [--unsafe-show-secrets] [--yes]
[--verbose] [--jobs JOBS] [--guide] username
positional arguments:
username GitHub username or organization name
options:
-h, --help show this help message and exit
--token, -t TOKEN GitHub Personal Access Token (optional)
--fast, -f Fast mode: scan only the latest commit (skip history)
--output, -o OUTPUT Export results as JSON to this file path
--include-forks Include forked repositories (excluded by default)
--unsafe-show-secrets Show the full unredacted secrets in the output
--yes, -y Bypass interactive confirmation for --unsafe-show-secrets
--verbose, -v Show detailed progress output
--jobs, -j JOBS Number of concurrent repo scans (default: 4)
--guide Show the visual command guide
```
## 🔍 检测到的机密类型
| Category | Secret Type | Example Pattern |
|----------|------------|-----------------|
| **AWS** | Access Key ID | `AKIA...` (20 chars) |
| **AWS** | Secret Access Key | `aws_secret_access_key = ...` |
| **GitHub** | Personal Access Token (classic) | `ghp_...` |
| **GitHub** | Fine-grained PAT | `github_pat_...` |
| **GitHub** | OAuth Access Token | `gho_...` |
| **Google** | API Key | `AIza...` (39 chars) |
| **Google** | OAuth Client Secret | `client_secret = ...` |
| **Stripe** | Secret Key | `sk_live_...` |
| **Stripe** | Publishable Key | `pk_live_...` |
| **Slack** | Bot Token | `xoxb-...-...-...` |
| **Slack** | Webhook URL | `https://hooks.slack.com/services/...` |
| **Discord** | Bot Token | `M...` / `N...` (base64 format) |
| **Telegram** | Bot Token | `123456789:ABC-DEF...` |
| **SendGrid** | API Key | `SG....` |
| **Mailgun** | API Key | `key-...` (32 hex chars) |
| **Twilio** | API Key | `SK...` (32 hex chars) |
| **Heroku** | API Key | `heroku_api_key = ...` (UUID) |
| **NPM** | Access Token | `npm_...` |
| **Azure** | Storage Account Key | `AccountKey = ...` (88 chars) |
| **Firebase** | Cloud Messaging Key | `AAAA...:...` |
| **Auth** | JSON Web Token (JWT) | `eyJ...eyJ...` |
| **Auth** | Private Key (RSA/DSA/EC/SSH) | `-----BEGIN ... PRIVATE KEY-----` |
| **Database** | Connection String | `mongodb://...`, `postgres://...` |
| **Generic** | Password/Secret assignments | `password = "..."`, `api_key = "..."` |
## 📊 示例输出
```
██████╗ ██╗████████╗ ███████╗███████╗ ██████╗██████╗ ███████╗████████╗███████╗
██╔════╝ ██║╚══██╔══╝ ██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝╚══██╔══╝██╔════╝
██║ ███╗██║ ██║ ███████╗█████╗ ██║ ██████╔╝█████╗ ██║ ███████╗
██║ ██║██║ ██║ ╚════██║██╔══╝ ██║ ██╔══██╗██╔══╝ ██║ ╚════██║
╚██████╔╝██║ ██║ ███████║███████╗╚██████╗██║ ██║███████╗ ██║ ███████║
╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝
[*] Fetching repositories for @your-username …
[✓] Found 12 repositories (forks excluded).
[*] [1/12] Cloning my-project …
[SECRET] 2 potential secret(s) in current files
════════════════════════════════════════════════════════════════════════
SCAN REPORT — @your-username
════════════════════════════════════════════════════════════════════════
Repositories scanned : 12
Files scanned : 347
Commits scanned : 1203
Duration : 42.3s
🔑 2 potential secret(s) found!
┌─ my-project (2 finding(s))
├── AWS Access Key ID
│ config/settings.py:L14 [file]
│ AKIAIO********************
│
└── Generic Secret Assignment
.env.example:L3 [file]
DB_PASSWORD="sup3r_********************
```
### JSON 导出结构
```
{
"username": "your-username",
"repos_scanned": 12,
"files_scanned": 347,
"commits_scanned": 1203,
"scan_duration_seconds": 42.3,
"total_findings": 2,
"findings": [
{
"repo": "my-project",
"file": "config/settings.py",
"line_number": 14,
"secret_type": "AWS Access Key ID",
"snippet": "AKIAIO********************",
"source": "file"
}
],
"errors": []
}
```
## 🔧 配置
### `scanner.py` 中的可调常量
| Constant | Default | Description |
|----------|---------|-------------|
| `MAX_FILE_SIZE` | 2 MB | 跳过大于此值的文件 |
| `REPOS_PER_PAGE` | 100 | GitHub API 分页大小 |
| `BINARY_EXTENSIONS` | 40+ types | 要跳过的文件扩展名 |
| `SKIP_DIRS` | `.git`, `node_modules`, etc. | 要完全忽略的目录 |
### 添加自定义机密模式
在 `scanner.py` 中的 `SECRET_PATTERNS` 列表添加新模式:
```
SECRET_PATTERNS.append((
"My Custom Token",
re.compile(r"\b(myapp_[A-Za-z0-9]{32})\b")
))
```
## 🔄 CI/CD 集成
当发现机密信息时,扫描器返回**退出代码 1**,这使其易于集成到 CI 流水线中:
### GitHub Actions 示例
```
name: Secret Scan
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install requests colorama
- run: python scanner.py ${{ github.repository_owner }} --fast --output report.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: secret-scan-report
path: report.json
```
## ⚠️ 法律与道德声明
## 🤝 贡献
1. Fork 该仓库
2. 创建一个功能分支 (`git checkout -b feature/new-pattern`)
3. 添加你的更改
4. 针对你自己的仓库进行测试
5. 提交一个 pull request
### 贡献思路
- 添加更多机密模式(Cloudflare、DigitalOcean 等)
- `.gitsecretsignore` 文件用于抑制误报
- Webhook 通知(Slack、Discord、电子邮件)
- Pre-commit hook 集成
- HTML 报告生成
## 📝 许可证
本项目在 MIT 许可证下获得许可。有关详细信息,请参阅 [LICENSE](LICENSE)。
专为关注安全的开发者用心打造。
标签:API密钥, DevSecOps, Git扫描, LNA, Python, Secrets Detection, Token检测, 上游代理, 二进制发布, 云安全监控, 代码审查, 安全扫描, 密码检测, 开源工具, 无后门, 时序注入, 私钥管理, 结构化查询, 网络安全, 网络安全研究, 自动化安全, 逆向工具, 隐私保护, 静态分析