High-performance Certificate Transparency log monitor for bug bounty hunting
ct-scout monitors Certificate Transparency logs in real-time to discover newly issued SSL/TLS certificates matching your target domains. Perfect for bug bounty hunters, security researchers, and penetration testers.
- PostgreSQL/Neon Database - Persistent storage with full historical analysis
- HackerOne Integration - Auto-sync watchlist from your H1 programs
- Intigriti Integration - Auto-sync watchlist from your Intigriti programs
- Zero Configuration - Just add API tokens, programs sync automatically
- Historical Queries - Query matches by domain, program, date range
- Multi-Instance Support - Shared database enables distributed deployments
- Direct CT Log Monitoring - No external dependencies, monitors CT logs directly via RFC 6962
- 187 CT Logs Supported - Monitor up to 187 logs from Google's list (exceeds gungnir's 49-60)
- Full Certificate Metadata - Extracts domains, validity dates, fingerprints, and more
- Precertificate Support - Get notified 1-5 minutes before final certificate issuance
- State Persistence - Resume monitoring from where you left off after restarts
- Multiple Output Formats - Human-readable, JSON, CSV, or Silent mode
- Health Tracking - Automatic 404 detection with exponential backoff
- High Throughput - 36,804+ messages/minute tested
- Efficient Resource Usage - 50-250MB memory depending on log count
- 100% Parse Success Rate - Robust X.509 certificate parsing
- Flexible Watchlist - Match domains, hosts, IPs, and CIDR ranges
- Program-Based Organization - Tag matches by bug bounty program
- Root Domain Filtering - Filter output to specific root domains
- Deduplication - Avoid duplicate notifications
- Webhook Support - HTTP POST with HMAC-SHA256 signatures
- Live Stats - Real-time processing statistics
- Progress Indicators - Visual feedback during operation
- Rust 1.70 or higher
- Cargo (comes with Rust)
git clone https://github.com/klumz33/ct-scout.git
cd ct-scout
cargo build --releaseThe binary will be at ./target/release/ct-scout
# config.toml
[logging]
level = "info"
[watchlist]
domains = ["*.example.com", "*.target.com"]
hosts = []
ips = []
cidrs = []
[ct_logs]
poll_interval_secs = 10
batch_size = 256
parse_precerts = true
max_concurrent_logs = 50
state_file = "ct-scout-state.toml"
[output]
format = "human" # or "json", "csv", "silent"
destination = "stdout"./target/release/ct-scout --config config.toml[2025-12-15 12:34:56] MATCH: new.example.com
All Domains: new.example.com, www.new.example.com
Issuer: Let's Encrypt
Valid: 2025-12-15 β 2026-03-15
Fingerprint: a1b2c3d4...
Standard (Default) - 36 logs, ~95% coverage:
[ct_logs]
# Uses default settingsMatch gungnir - ~49-60 logs, ~97% coverage:
[ct_logs]
include_readonly_logs = true
include_pending = trueMaximum Coverage - 187 logs, 100% of Google's list:
[ct_logs]
include_all_logs = true
max_concurrent_logs = 187Custom Logs - Add your own:
[ct_logs]
include_all_logs = true
additional_logs = [
"https://historical-log-1.com/ct/v1/",
"https://historical-log-2.com/ct/v1/",
]Human-readable (default):
[output]
format = "human"
destination = "stdout"JSON (for pipelines):
[output]
format = "json"
destination = "file"
file_path = "matches.jsonl"CSV (for spreadsheets):
[output]
format = "csv"
destination = "file"
file_path = "matches.csv"[webhook]
url = "https://your-webhook.com/ct-alerts"
secret = "your-secret-key"
timeout_secs = 10Webhook payload format:
{
"timestamp": 1734262800,
"matched_domain": "new.example.com",
"all_domains": ["new.example.com", "www.new.example.com"],
"cert_index": 12345678,
"not_before": 1734262800,
"not_after": 1741951999,
"fingerprint": "a1b2c3d4e5f6...",
"program_name": "Example Bug Bounty"
}PostgreSQL/Neon Database:
[database]
enabled = true
url = "postgresql://user:pass@neon.tech/ctscout?sslmode=require"
max_connections = 20HackerOne Integration:
[platforms.hackerone]
enabled = true
username = "your-username"
api_token = "your-h1-api-token"Intigriti Integration:
[platforms.intigriti]
enabled = true
api_token = "your-intigriti-token"Full Enterprise Stack:
[logging]
level = "info"
[database]
enabled = true
url = "postgresql://neon.tech/ctscout?sslmode=require"
max_connections = 20
[platforms]
sync_interval_hours = 6
[platforms.hackerone]
enabled = true
username = "your-username"
api_token = "your-h1-token"
[platforms.intigriti]
enabled = true
api_token = "your-intigriti-token"
[ct_logs]
include_all_logs = true
max_concurrent_logs = 187
parse_precerts = true
[watchlist]
# Optional - platforms will auto-populate
domains = []
[webhook]
url = "https://your-webhook.com/alerts"
secret = "your-secret"Result: Zero-configuration bug bounty automation with full historical tracking!
Organize targets by bug bounty program:
[[programs]]
name = "Example Bug Bounty"
domains = ["*.example.com"]
[[programs]]
name = "Target Security Program"
domains = ["*.target.com", "*.target.io"]
hosts = ["192.0.2.0/24"]Monitor target domains for newly issued certificates to discover:
- New subdomains
- Development/staging environments
- Internal infrastructure
- Third-party services
- Track certificate issuance patterns
- Identify certificate authorities used
- Monitor for suspicious certificates
- Research domain takeover opportunities
- Expand attack surface during reconnaissance
- Discover forgotten subdomains
- Find development/test environments
- Identify certificate misconfigurations
Based on production testing:
| Metric | Value |
|---|---|
| Throughput | 36,804+ msg/min |
| Parse Success Rate | 100% |
| Memory Usage | 50-250MB |
| CT Logs Monitored | 36-187 (configurable) |
| Coverage | 95-100% of new certs |
ct-scout automatically handles failed CT logs:
- Exponential Backoff: 1min β 2min β 4min β ... β 1hour
- Automatic Recovery: Returns to normal when logs respond
- Health Summary: Logged every 5 minutes
ct-scout saves its position in each CT log:
# ct-scout-state.toml (auto-generated)
"https://ct.googleapis.com/logs/argon2024/" = 12345678
"https://ct.cloudflare.com/logs/nimbus2024/" = 87654321Resume monitoring after restart without missing entries.
Enable early detection (1-5 minutes before final certificate):
[ct_logs]
parse_precerts = true # Default: true- QUICKSTART.md - Detailed usage guide
- PHASE1_FINAL.md - Complete feature documentation
- GUNGNIR_SUMMARY.md - Comparison with gungnir
- CERTIFICATE_METADATA_FIX.md - Technical details
- Check your watchlist patterns:
*.example.commatches subdomains only - Verify CT logs are responding: check INFO logs for successful polls
- Increase coverage: set
include_all_logs = true
- Reduce
max_concurrent_logs - Decrease
batch_size - Disable precertificate parsing if not needed
- ct-scout automatically handles 404s and failures
- Check health summary logs (every 5 minutes)
- Failed logs will retry with exponential backoff
- PostgreSQL/Neon database integration
- HackerOne API integration (auto-sync watchlist)
- Intigriti API integration
- REST API server
- WebSocket streaming
- Historical backfill mode
- Prometheus metrics
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details
- Certificate Transparency project
- Google's CT log list
- Rust community
- Issues: GitHub Issues
- Documentation: See docs/ directory
Built with β€οΈ for the bug bounty community
π€ Generated with Claude Code