voip.ms API credentials leak into logs on every send and into the observability DB on failure #46

Closed
opened 2026-07-18 05:31:13 +00:00 by claude-bot · 1 comment
Contributor

_send_voipms_sms (app/services/notifiers/sms.py:141-166) sends
api_username/api_password as GET query parameters. httpx logs every request
URL (query string included) at INFO, and app logging is INFO
(app/main.py:21-24), so credentials hit the logs on every send. On non-2xx,
response.raise_for_status() raises an error whose message embeds the full
URL; it is logged and persisted unredacted via _record_sms_delivery
record_notifier_delivery, surfacing on the admin diagnostics page.

Fix: switch the voip.ms call to POST with credentials in the body; scrub URL
query strings from any exception text before logging/persisting delivery
errors (apply the scrubber in _record_sms_delivery and
record_notifier_delivery so all notifiers benefit). Rotate the voip.ms API
password after deploying the fix.

Acceptance criteria:

  • No credential material in httpx request logs for voip.ms sends
  • Persisted delivery errors contain no query strings/secrets
  • Test: failed voip.ms send records an error without the password
  • Operational: voip.ms API password rotated

Filed from the 2026-07-17 codebase audit (docs/.internal/report-2026-07-17.md), finding F-07.

`_send_voipms_sms` (app/services/notifiers/sms.py:141-166) sends `api_username`/`api_password` as GET query parameters. httpx logs every request URL (query string included) at INFO, and app logging is INFO (app/main.py:21-24), so credentials hit the logs on every send. On non-2xx, `response.raise_for_status()` raises an error whose message embeds the full URL; it is logged and persisted unredacted via `_record_sms_delivery` → `record_notifier_delivery`, surfacing on the admin diagnostics page. Fix: switch the voip.ms call to POST with credentials in the body; scrub URL query strings from any exception text before logging/persisting delivery errors (apply the scrubber in `_record_sms_delivery` and `record_notifier_delivery` so all notifiers benefit). Rotate the voip.ms API password after deploying the fix. **Acceptance criteria:** - [ ] No credential material in httpx request logs for voip.ms sends - [ ] Persisted delivery errors contain no query strings/secrets - [ ] Test: failed voip.ms send records an error without the password - [ ] Operational: voip.ms API password rotated --- _Filed from the 2026-07-17 codebase audit (`docs/.internal/report-2026-07-17.md`), finding F-07._
Author
Contributor

Fixed in #93 (merged to main). The voip.ms call now POSTs credentials in the request body (out of the URL entirely), a central scrub_secrets() strips URLs/credential params from persisted notifier errors in record_notifier_delivery (so all channels benefit), and httpx request logging is lowered to WARNING so full request URLs aren't logged at INFO. Tests confirm a failed voip.ms send records/logs no password, username, or query string.

⚠️ Operational action still required: rotate the voip.ms API password — it may already be present in historical container logs and the observability DB from before this fix.

Fixed in #93 (merged to `main`). The voip.ms call now POSTs credentials in the request body (out of the URL entirely), a central `scrub_secrets()` strips URLs/credential params from persisted notifier errors in `record_notifier_delivery` (so all channels benefit), and httpx request logging is lowered to WARNING so full request URLs aren't logged at INFO. Tests confirm a failed voip.ms send records/logs no password, username, or query string. ⚠️ **Operational action still required:** rotate the voip.ms API password — it may already be present in historical container logs and the observability DB from before this fix.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot#46
No description provided.