Bug: OAuth callback crashes on malformed `state` due to unhandled `decodeURIComponent` error
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- api, authentication
Research direction
Start at CallbackEndpoint.ts:44, where the OAuth callback decodes the state parameter inside Promise.all. Reproduce the endpoint request with the malformed state value from the issue and trace the response path. Done means malformed state no longer causes an unhandled URIError and returns a controlled 400 callback response.
Written by the indexing model from the issue text.
Description
Description
The OAuth callback endpoint decodes the state query parameter without guarding against invalid percent-encoding, which can throw a URIError and break the entire callback flow.
Code reference: CallbackEndpoint.ts:44
At that line, decodeURIComponent(state) is called directly inside Promise.all. If state contains malformed encoding (e.g., a trailing % or an invalid UTF-8 sequence), decodeURIComponent throws a URIError and the endpoint fails before building a safe callback response.
Steps to Reproduce
- Trigger the callback endpoint with a malformed
statevalue:
/api/apps/public/{appId}/callback?code=valid_code&state=%E0%A4%A - Observe server logs and response.
- The request fails before token exchange handling completes.
Expected Behavior
The endpoint should handle malformed state safely and return a controlled callback response (e.g., 400 with a user-friendly error page), not crash/fail via an unhandled decode error.
Actual Behavior
Malformed state causes decodeURIComponent to throw, which interrupts request handling and breaks the OAuth callback flow.
Impact
- Login flow can fail unexpectedly for users.
- Crafted callback URLs can cause repeated endpoint failures.
Suggested Fix Direction
- Wrap
statedecoding in atry/catchblock:
let decodedState: string;
try {
decodedState = decodeURIComponent(state);
} catch (e) {
return context.sendJson({ error: 'Invalid state parameter' }, 400);
}
- Validate
origin/statebefore use. - Return a controlled error response when
stateis invalid.
Note: This issue was identified while reviewing the OAuth callback implementation. A fix would improve robustness against both accidental and crafted malformed callback URLs.
- Dominant language
- JavaScript
- Stars
- 165
- Forks
- 381
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 1
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from RocketChat/EmbeddedChat
-
enhancement
Difficulty 1/5 Under an hour Newbie friendliness 84/100
RocketChat/EmbeddedChat#1360 · 1 comment ·
-
Permissions change-detection in useFetchChatData is dead — applyPermissions re-runs on every call Open
Difficulty 1/5 Under an hour Newbie friendliness 85/100
RocketChat/EmbeddedChat#1317 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
RocketChat/EmbeddedChat#1315 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
RocketChat/EmbeddedChat#1313 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
RocketChat/EmbeddedChat#1294 ·
All issues in RocketChat/EmbeddedChat
Similar issues
-
curation good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
amponce/archive-movie-browser#186 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
clerk/javascript#9852 ·
-
bug p1 tools
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
HarperFast/skills#96 ·
-
factory-active factory-automatic task-bug-reproduction-cannot-reproduce task-identify-harness-labels-done task-identify-issue-type-done
Difficulty 2/5 1-3 hours Newbie friendliness 84/100