fix: prevent reflected XSS in WebSub intent verification (Instagram & Facebook) - #8662
#8662fix: prevent reflected XSS in WebSub intent verification (Instagram & Facebook)#8662AnkitPorwal04 wants to merge 2 commits intoerxes:mainerxes/erxes:mainfrom AnkitPorwal04:fix/websub-reflected-xssAnkitPorwal04/erxes:fix/websub-reflected-xssCopy head branch name to clipboard
Conversation
… Facebook) Set Content-Type to text/plain when echoing hub.challenge in the WebSub subscription verification handlers. Express defaults to text/html for string responses, allowing a crafted hub.challenge parameter to inject arbitrary HTML/JS. Fixes erxes#7855
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR hardens the WebSub intent verification endpoints for Instagram and Facebook by explicitly setting the response Content-Type to text/plain when echoing the hub.challenge value, preventing reflected XSS while staying compliant with the WebSub spec. Sequence diagram for WebSub intent verification with safe hub.challenge echosequenceDiagram
actor Client
participant WebSubEndpoint
Client->>WebSubEndpoint: GET /subscription?hub.mode=subscribe&hub.verify_token&hub.challenge
alt hub.verify_token valid
WebSubEndpoint->>Client: res.type('text/plain').send(hub.challenge)
else hub.verify_token invalid
WebSubEndpoint->>Client: res.send('OK')
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe Facebook and Instagram webhook verification handlers now set ChangesWebhook Verification Response Type
Estimated code review effort: 1 (Trivial) | ~2 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Consider explicitly casting
req.query['hub.challenge']to a string before sending (e.g.String(...)) to avoid unexpected behavior if the query value is an array or other non-string type. - For consistency and to avoid any future ambiguity, you may also want to set
text/plainon the non-challenge responses in these handlers (e.g. the'OK'path) so all subscription verification responses use a predictable content type.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider explicitly casting `req.query['hub.challenge']` to a string before sending (e.g. `String(...)`) to avoid unexpected behavior if the query value is an array or other non-string type.
- For consistency and to avoid any future ambiguity, you may also want to set `text/plain` on the non-challenge responses in these handlers (e.g. the `'OK'` path) so all subscription verification responses use a predictable content type.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Cast hub.challenge to String() to handle array query params safely - Set Content-Type text/plain on all subscription verification responses for consistency (including the 'OK' fallback path)
|
Summary
Fixes a reflected XSS vulnerability in the WebSub (PubSub) intent verification handlers for both Instagram and Facebook integrations.
Problem
The
instagramSubscriptionandfacebookSubscriptionhandlers echo back thehub.challengequery parameter viares.send()without setting an explicit Content-Type. Express defaults totext/htmlfor string responses, which means a craftedhub.challengevalue containing<script>tags or other HTML will be rendered by the browser — a classic reflected XSS.Affected files:
backend/plugins/frontline_api/src/modules/integrations/instagram/controller/controller.tsbackend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.tsFix
Set
Content-Type: text/plainbefore sending the response usingres.type('text/plain').send(...). This ensures the browser treats the reflected value as plain text, not HTML. This is also consistent with the W3C WebSub specification which expects the challenge to be echoed as-is without HTML interpretation.Changes
res.send(req.query['hub.challenge'])→res.type('text/plain').send(req.query['hub.challenge'])Applied to both Instagram and Facebook subscription handlers.
Fixes #7855
Summary by Sourcery
Set WebSub intent verification responses for Instagram and Facebook to return the hub.challenge as plain text to mitigate reflected XSS.
Bug Fixes:
Summary by CodeRabbit
hub.challengevalue is sent consistently in the expected response format, improving compatibility with third-party verification callbacks.