fix(discord,slack): harden delivery against non-JSON failures and token leakage (#865)#1138
Conversation
…en leakage (Tracer-Cloud#865) Align Slack and Discord delivery helpers with Telegram's redaction behavior: non-JSON failure bodies (HTML, plain text) no longer cause crashes, and bot tokens / access tokens are redacted in logs and return values to prevent secret leakage.
Greptile SummaryThis PR hardens Slack and Discord delivery helpers to gracefully handle non-JSON error bodies and redact tokens from logs and return values, matching Telegram's existing behavior. The Discord changes are complete and correct; the Slack changes have one gap:
Confidence Score: 4/5Holds off on merge until the missing _redact_token call in _post_direct's API-error branch is added. One P1 gap exists where the new _extract_error result is logged without redaction, directly contradicting the PR's stated goal of scrubbing tokens from all log lines. The Discord side is fully correct, tests are thorough, and the overall approach is sound — a single two-line fix resolves the blocker. app/utils/slack_delivery.py — specifically the
|
| Filename | Overview |
|---|---|
| app/utils/slack_delivery.py | Adds _redact_token and _extract_error helpers; applies redaction to transport-exception path in _post_direct and send_slack_report, but the API-error branch of _post_direct logs and returns error without calling _redact_token. Also defines _ACCESS_TOKEN_RE that is never used. |
| app/utils/discord_delivery.py | Adds _redact_token and _extract_error helpers; both post_discord_message and create_discord_thread correctly redact tokens on all failure paths. _discord_error_from_data is now dead code that was not removed. |
| tests/utils/test_slack_delivery.py | Adds 7 new test classes covering redaction, extract_error fallbacks, non-JSON body handling, and log scrubbing; good coverage but no test for the missing redaction in _post_direct's API-error branch. |
| tests/utils/test_discord_delivery.py | Adds 10 new tests covering Discord redaction, extract_error fallbacks, non-JSON responses, and log scrubbing; comprehensive and well-structured. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[_post_direct called] --> B{response.ok?}
B -- No: transport exception --> C[_redact_token applied ✅]
C --> D[logger.error + return exception=...]
B -- Yes --> E{response.data\nok is not True?}
E -- No --> F[return True, '']
E -- Yes --> G[data.get 'error']
G -- present --> H[use error as-is]
G -- absent --> I[_extract_error\ncan use response.text]
H --> J[⚠️ logger.error — NO redaction]
I --> J
J --> K[return slack_error=error — NO redaction]
K --> L[send_slack_report\ncalls _redact_token here ✅]
Comments Outside Diff (1)
-
app/utils/slack_delivery.py, line 262-274 (link)Missing redaction in
_post_directAPI-error log pathWhen
response.data.get("ok") is not Trueand nodata["error"]field is present,_extract_erroris called withresponse.textas the fallback. The resultingerrorstring is then passed directly tologger.errorand returned — without_redact_tokenapplied. Ifresponse.textever contains the access token (e.g., a proxy echo-back or a misconfigured error body), the token appears in logs unredacted, which is the exact leak this PR targets.The transport-exception branch above it correctly calls
_redact_token; the API-error branch below does not.if response.data.get("ok") is not True: error = response.data.get("error") if not error: error = _extract_error(dict(response.data), response.status_code, response.text) error = _redact_token(error, token) # add this response_meta = response.data.get("response_metadata", {}) logger.error( "[slack] Direct post FAILED: error=%s, metadata=%s (channel=%s, thread_ts=%s)", error, response_meta, channel, thread_ts, ) return False, f"slack_error={error}"
Reviews (1): Last reviewed commit: "fix(discord,slack): harden delivery agai..." | Re-trigger Greptile
|
@muddlebee this is ready for review. I addressed the automated review feedback and CI is green |
|
😤 @kespineira said "I will fix this" and then actually fixed it. Legendary behavior. 👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome. |

Fixes #865
Describe the changes you have made in this PR -
This PR hardens Slack and Discord delivery helpers to match Telegram's existing safety behavior.
Changes made:
HTTP <status>when structured JSON is unavailable.xox*token-pattern fallback for response bodies that contain a Slack token even when it does not exactly match the token argument._discord_error_from_datahelper after replacing all call sites with_extract_error.Demo/Screenshot for feature changes and bug fixes -
Before:
After:
Non-JSON error body behavior:
Local verification:
CI verification:
Code Understanding and AI Usage
Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?
If you used AI assistance:
Explain your implementation approach:
This fixes a reliability and security gap in Slack and Discord delivery. Telegram already handled non-JSON failures and redacted bot tokens before propagating errors; Slack and Discord now follow the same pattern.
I kept the implementation local to the delivery helpers instead of centralizing it in
delivery_transport.pybecause each provider has different credential shapes and response semantics. The transport layer should stay provider-neutral, while Slack and Discord know how to redact their own tokens and extract their own API errors.Key functions added or updated:
slack_delivery._redact_token()replaces exact Slack access-token matches and also uses a defensivexox*pattern fallback.slack_delivery._extract_error()extracts Slack API errors from JSON first, then raw text, then HTTP status.discord_delivery._redact_token()replaces Discord bot-token matches before logging or returning errors.discord_delivery._extract_error()extracts Discordmessage/errorfields first, then raw text, then HTTP status._post_direct()now redacts both transport errors and API response-body errors before logging or returning them.post_discord_message()andcreate_discord_thread()now redact every propagated failure string.Checklist before requesting a review
Note: Please check Allow edits from maintainers if you would like us to assist in the PR.