Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix: prevent reflected XSS in WebSub intent verification (Instagram & Facebook) - #8662

#8662
Open
AnkitPorwal04 wants to merge 2 commits into
erxes:mainerxes/erxes:mainfrom
AnkitPorwal04:fix/websub-reflected-xssAnkitPorwal04/erxes:fix/websub-reflected-xssCopy head branch name to clipboard
Open

fix: prevent reflected XSS in WebSub intent verification (Instagram & Facebook)#8662
AnkitPorwal04 wants to merge 2 commits into
erxes:mainerxes/erxes:mainfrom
AnkitPorwal04:fix/websub-reflected-xssAnkitPorwal04/erxes:fix/websub-reflected-xssCopy head branch name to clipboard

Conversation

@AnkitPorwal04

@AnkitPorwal04 AnkitPorwal04 commented Jul 9, 2026

Copy link
Copy Markdown

Summary

Fixes a reflected XSS vulnerability in the WebSub (PubSub) intent verification handlers for both Instagram and Facebook integrations.

Problem

The instagramSubscription and facebookSubscription handlers echo back the hub.challenge query parameter via res.send() without setting an explicit Content-Type. Express defaults to text/html for string responses, which means a crafted hub.challenge value 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.ts
  • backend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.ts

Fix

Set Content-Type: text/plain before sending the response using res.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:

  • Prevent reflected XSS in Instagram WebSub subscription verification by sending the hub.challenge with a text/plain content type.
  • Prevent reflected XSS in Facebook WebSub subscription verification by sending the hub.challenge with a text/plain content type.

Summary by CodeRabbit

  • Bug Fixes
    • Improved webhook verification responses for the Facebook and Instagram integrations by returning the verification challenge as plain text.
    • Ensures the hub.challenge value is sent consistently in the expected response format, improving compatibility with third-party verification callbacks.

… 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
@sourcery-ai

sourcery-ai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This 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 echo

sequenceDiagram
    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
Loading

File-Level Changes

Change Details Files
Force plain-text responses when echoing WebSub hub.challenge in subscription handlers to prevent reflected XSS.
  • Update Instagram subscription handler to send hub.challenge with Content-Type text/plain instead of default text/html
  • Update Facebook subscription handler to send hub.challenge with Content-Type text/plain instead of default text/html
backend/plugins/frontline_api/src/modules/integrations/instagram/controller/controller.ts
backend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#7855 Prevent reflected XSS in the Instagram WebSub intent verification by ensuring the echoed hub.challenge value is not served with an HTML content type.
#7855 Apply the same WebSub intent verification XSS mitigation to the Facebook integration’s facebookSubscription handler, ensuring hub.challenge is returned as plain text.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4e0315a-c2a3-48b3-9e70-992290ea249c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6ede5 and 8cc1e51.

📒 Files selected for processing (2)
  • backend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.ts
  • backend/plugins/frontline_api/src/modules/integrations/instagram/controller/controller.ts
✅ Files skipped from review due to trivial changes (1)
  • backend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/plugins/frontline_api/src/modules/integrations/instagram/controller/controller.ts

📝 Walkthrough

Walkthrough

The Facebook and Instagram webhook verification handlers now set Content-Type: text/plain before returning the hub.challenge value or the fallback OK response.

Changes

Webhook Verification Response Type

Layer / File(s) Summary
Set text/plain content type on challenge response
backend/plugins/frontline_api/src/modules/integrations/facebook/controller/controller.ts, backend/plugins/frontline_api/src/modules/integrations/instagram/controller/controller.ts
Both webhook subscription handlers now set res.type('text/plain') before sending the verification challenge or fallback OK response, and the challenge value is explicitly converted to a string.

Estimated code review effort: 1 (Trivial) | ~2 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix: preventing reflected XSS in WebSub intent verification for Instagram and Facebook.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/plain on 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.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
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)
@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential reflected XSS in the WebSub intent verification

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.