Security & Reliability Fixes (commit bab38c4)
Three hardening fixes applied to the outbound relay in telegram-connector-overview. All work is in /Users/levander/coding/pmv2/telegram_connector-outbound on branch feat/outbound-relay.
Fix A — Bot Token Leak in Network Error Logs
Root Cause
reqwest::Error’sDisplayimpl embeds the full request URL, which contains/bot<TOKEN>/. Anytracinglog call on a rawreqwest::Errorleaks the secret bot token.
Resolution:
- Call
.without_url()on anyreqwest::Errorbefore passing it to atracingmacro. .without_url()consumesself, so the rebind pattern is required in match arms:Err(e) => { let e = e.without_url(); tracing::warn!("network error: {e}"); }- Extracted
classify_getme(status: u16, body: &str) -> bool— pure function, trivially unit-testable. - Added
TelegramClient::verify_token() -> anyhow::Result<bool>— GETs/bot{token}/getMe, delegates classification toclassify_getme, strips URL from any network error.
Gotcha — Move Semantics
without_url()consumesself. Do NOT writeErr(ref e)or try to borrow after calling it. Thelet e = e.without_url();rebind pattern is the correct idiom.
Fix B — Required Config Fields
Problem
TELEGRAM_CHAT_IDandNATS_TELEGRAM_NKEY_SEEDwere optional-with-default. Missing values failed silently at runtime rather than failing loudly at startup.
Resolution:
- Both fields promoted to required.
- Missing or empty value →
ConfigOutcome::Dormantreturned at startup. - Service goes dormant immediately rather than running until the first message triggers a failure.
Fix C — Startup Token Preflight
After constructing TelegramClient and before entering the relay loop, verify_token() is called:
| Result | Behaviour |
|---|---|
Ok(true) | Token valid — proceed |
Ok(false) | Hard bail — token known invalid upfront |
Err(_) | Warn and continue — network may not be ready at boot |
This catches typos and revoked tokens before any JetStream messages are consumed.
Test Coverage
34 tests total (up from 26). 8 new tests:
- Transient outcome on network error in
verify_token - Token sanitization assertion (URL not present in logged error string)
classify_getmebranches (ok/unauthorized/other status codes)ConfigOutcome::Dormanton missingTELEGRAM_CHAT_IDConfigOutcome::Dormanton missingNATS_TELEGRAM_NKEY_SEED
Related Notes
- telegram-connector-overview — system architecture
- task7-lib-bin-split-relay-loop-tests — prior relay loop work this builds on
- nats-jetstream-message-source — NATS source impl