4c104cddd291a5e27c69e0f848e15d48743b10ff
- FastAPI + htmx + Jinja2 web frontend, started with --web flag - JWT HS256 auth (WEB_SECRET_KEY) with httpOnly cookies; access (15 min) + refresh (7 day) tokens; refresh rotation + JTI revocation in data/web.db - RBAC: superadmin > admin > reader enforced per route - Live SSE dashboard fed by tui/events broadcast queue - Config editor: keyword groups and channel list saved to data/runtime_config.json and hot-reloaded in-process (scorer.reload_from_config, signal_channel_changed) - config.py migrated to load groups/channels from runtime_config.json; falls back to hardcoded defaults when file absent - tui/events.py: subscribe/unsubscribe broadcast, set_bot_context/signal_channel_changed - utils/scorer.py: import config as _config (fixes local binding); reload_from_config() - utils/database.py: count_by_severity, recent_for_domains, count_by_severity_for_domains - 53 new tests (events bus, JWT lifecycle, web DB CRUD, RBAC enforcement, config round-trip); total 141 passing
ULP Credential Monitor
A Telegram-based credential exposure monitor for threat intelligence teams. Watches channels for combo/stealer log files and alerts you when your organization's credentials appear in them.
How it works
User session (Telethon)
└─ watches N channels
└─ detects file attachments (.txt, .zip, .7z, .rar)
└─ downloads → extracts → searches line by line
└─ hit? → writes to data/ + sends bot alert
└─ no hit? → deletes file, moves on
Project structure
ulp_monitor/
├── main.py Entry point
├── config.py All settings (keywords, channels, paths)
│
├── core/ Telegram I/O pipeline
│ ├── scraper.py Live listener + backfill
│ ├── tdl_downloader.py Fast downloads via tdl (Go MTProto)
│ ├── bot_downloader.py Inline button / bot-dispatched file flows
│ ├── processor.py Archive extraction + line-by-line search
│ └── notifier.py hits.txt / hits.csv writer + bot alerts
│
├── utils/ Pure logic — no Telegram dependencies
│ ├── scorer.py Hit severity scoring
│ ├── cache.py Seen-file deduplication
│ └── database.py SQLite persistence layer
│
├── tui/ Textual TUI frontend
│ ├── app.py MonitorApp + all Screen classes
│ └── events.py Thread-safe event bus (bot thread → TUI)
│
└── data/ Runtime-generated (gitignored)
├── hits.db SQLite database
├── hits.txt Human-readable hit log
├── hits.csv CSV hit log (importable into Excel / pandas)
├── dedup.json Deduplication hashes
├── cache.json Seen file-ID cache
└── logs/monitor.log
Setup
1. Get Telegram API credentials
- Go to https://my.telegram.org → API development tools
- Create an app → note your
api_idandapi_hash
2. Create a bot
- Message @BotFather →
/newbot - Start a chat with your new bot before running
3. Get your chat ID
- Message @userinfobot
4. Configure
cp .env.example .env
# fill in API_ID, API_HASH, BOT_TOKEN, NOTIFY_CHAT_ID
Open config.py and set:
TARGET_KEYWORDS— your org's domains and email patterns. Keywords with@(e.g.r"@myorg\.cl") are employee email domains → CRITICAL. Keywords without@are plain domain matches → LOW baseline.WATCHED_CHANNELS— channel usernames or numeric IDsBACKFILL_LIMIT— past messages to scan per channel on startup
5. Install dependencies
pip install -r requirements.txt
# rarfile needs the unrar binary:
# Ubuntu/Debian: sudo apt install unrar
# macOS: brew install rar
5a. Install tdl (strongly recommended)
curl -sSL https://raw.githubusercontent.com/iyear/tdl/main/scripts/install.sh | bash
tdl login -n monitor_session
6. First run — complete Telegram auth
python main.py --no-tui
# follow the phone + 2FA prompts once
7. Run
python main.py # TUI mode (recommended)
python main.py --no-tui # plain CLI
TUI keybindings
| Key | Action |
|---|---|
s |
Search hits database |
h |
Browse hits by severity |
k |
Edit keyword patterns live |
c |
Clear logs |
r |
Refresh stats |
q |
Quit |
Output
| File | Description |
|---|---|
data/hits.db |
SQLite — all hits with scores, severity, dedup flag |
data/hits.txt |
Human-readable grouped log |
data/hits.csv |
CSV — easy to pull into Excel / pandas |
data/logs/monitor.log |
Full run log |
Telegram alerts fire for CRITICAL / HIGH / MEDIUM only. LOW is stored silently.
Notes
- Session files are sensitive — equivalent to a logged-in account. Gitignored, never share.
- Flood limits —
FloodWaitErroris handled automatically. - Private channels — your user account must already be a member.
Description
Telegram channel monitor: downloads, extracts, scores, and alerts on credential leaks
Languages
Python
91.1%
HTML
6.5%
CSS
2.4%