Skip to content

fix(slack): guard relay WebSocket frame JSON.parse against malformed input#98587

Merged
vincentkoc merged 2 commits into
openclaw:mainfrom
lsr911:fix/slack-relay-json-parse-guard
Jul 1, 2026
Merged

fix(slack): guard relay WebSocket frame JSON.parse against malformed input#98587
vincentkoc merged 2 commits into
openclaw:mainfrom
lsr911:fix/slack-relay-json-parse-guard

Conversation

@lsr911

@lsr911 lsr911 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

extensions/slack/src/monitor/relay-source.ts:298 uses bare JSON.parse(text) in parseRelayFrame() to parse incoming Slack Socket Mode relay WebSocket frames. Malformed JSON from the relay infrastructure would throw raw SyntaxError, which propagates up through handleRelayFrame and is caught by runRelayWebSocket's generic error handler. This loses the distinction between transport errors and parse errors, and makes debugging harder.

Solution: Wrap JSON.parse in try/catch and throw SlackRelayMalformedFrameError with the original SyntaxError as cause, so callers can distinguish malformed-frame errors from transport errors.

D4 dimension — JSON.parse without try/catch on external input. All major competitors (Alix-007, wangmiao, Pandah97, hugenshen, sunlit-deng) have zero coverage of this dimension.

Changes

  • relay-source.ts: add SlackRelayMalformedFrameError class; wrap bare JSON.parse in try/catch; export parseRelayFrame for testability
  • relay-source.test.ts: add 5 test cases covering valid JSON, malformed JSON, cause wrapping, empty object, and array frames
  • test/_proof_slack_relay_json_guard.mts: real behavior proof script calling actual parseRelayFrame

Evidence

Unit tests

$ pnpm exec vitest run extensions/slack/src/monitor/relay-source.test.ts

 Test Files  1 passed (1)
      Tests  7 passed (7)

Real behavior proof

$ node --import tsx test/_proof_slack_relay_json_guard.mts
PASS  malformed JSON frame: throws SlackRelayMalformedFrameError :: type=SlackRelayMalformedFrameError
PASS  malformed JSON frame: message describes malformed JSON :: msg=Slack relay received malformed JSON frame
PASS  malformed JSON frame: wraps original SyntaxError as cause :: cause=SyntaxError
PASS  valid JSON frame: parsed correctly :: result={"type":"slack_event","data":{"text":"hello"}}
PASS  empty JSON frame: parsed correctly :: result={}

[proof] 5 PASS, 0 FAIL

Call chain

runRelayWebSockethandleRelayFrameparseRelayFrame → now throws SlackRelayMalformedFrameError instead of raw SyntaxError for malformed frames. The existing error handler in runRelayWebSocket catches all errors via .catch() and logs them, so no behavioral change for the relay loop — the improvement is semantic: the error type now distinguishes parse failures from transport failures.

Label: bugfix | merge-risk: 🟢 minimal | AI-assisted

@openclaw-barnacle openclaw-barnacle Bot added channel: slack Channel integration: slack size: S labels Jul 1, 2026
@vincentkoc
vincentkoc force-pushed the fix/slack-relay-json-parse-guard branch from 75c64eb to 821040d Compare July 1, 2026 11:36
lsr911 and others added 2 commits July 1, 2026 04:44
…input

Slack Socket Mode relay receives WebSocket frames from external
infrastructure. parseRelayFrame() used bare JSON.parse() which would
throw raw SyntaxError on malformed frames, potentially crashing the
relay connection.

Wrap JSON.parse in try/catch and throw SlackRelayMalformedFrameError
with the original SyntaxError as cause, so callers can distinguish
transport errors from parse errors.

D4 dimension — all competitors have zero coverage.

Signed-off-by: lsr911 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants