Skip to content

Enhance embed URL handling and validation system#7

Open
ShashankFC wants to merge 1 commit into
embed-url-handling-prefrom
embed-url-handling-post
Open

Enhance embed URL handling and validation system#7
ShashankFC wants to merge 1 commit into
embed-url-handling-prefrom
embed-url-handling-post

Conversation

@ShashankFC

@ShashankFC ShashankFC commented Jan 22, 2026

Copy link
Copy Markdown

Test 4

Summary by CodeRabbit

  • New Features

    • Added embedding functionality to display external website content in responsive iframes
    • Introduced RSS/ATOM feed polling to automatically create and update posts from external feeds
    • Added embed interface displaying top posts with dynamic height adjustment
  • Tests

    • Added comprehensive test coverage for embed functionality and feed polling
  • Chores

    • Added required dependencies and database schema updates to support embedding

✏️ Tip: You can customize this high-level summary in your review settings.


Replicated from ai-code-review-evaluation/discourse-coderabbit#4


Note

High Risk
Adds remote content fetching + raw-HTML rendering and relaxes validations for imported content, which is security- and data-integrity-sensitive. Also introduces new scheduled/async jobs that can affect background load and topic creation/update behavior.

Overview
Adds a new embedding surface: GET /embed/best renders an embed layout for displaying a topic’s “best” posts inside an iframe, with new JS/CSS assets to embed the iframe and auto-resize it via postMessage.

Introduces TopicEmbed plus background retrieval (Jobs::RetrieveTopic, TopicRetriever) and an hourly Jobs::PollFeed to create/update topics from remote pages or RSS/Atom feeds (using ruby-readability and simple-rss), gated by new embedding site settings.

Extends posts with a cook_method column and Post.cook_methods enum so imported posts can bypass the cooking pipeline and store raw HTML; PostCreator/PostRevisor are updated to support cook_method and optional validation skipping for imports. Also updates the Disqus import task to bootstrap topics via TopicEmbed.import_remote, and adds DB migrations + i18n strings for embedding settings/UI.

Written by Cursor Bugbot for commit 4f8aed2. Configure here.

@ShashankFC

Copy link
Copy Markdown
Author

bugbot run

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

window.onload = function() {
if (parent) {
// Send a post message with our loaded height
parent.postMessage({type: 'discourse-resize', height: document['body'].offsetHeight}, '<%= request.referer %>');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Iframe resize messages never reach parent

Medium Severity

parent.postMessage uses request.referer as targetOrigin, but that value includes a full URL path. Browsers match targetOrigin by origin, so the resize message is rejected and embed.js never receives height updates for discourse-embed-frame.

Fix in Cursor Fix in Web

url = i.link
url = i.id if url.blank? || url !~ /^https?\:\/\//

content = CGI.unescapeHTML(i.content.scrub)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Feed polling crashes on missing content

Medium Severity

poll_feed assumes every item has i.content and calls i.content.scrub. Many RSS/ATOM feeds only provide fields like description or omit content, so this can raise on nil and abort the polling run.

Fix in Cursor Fix in Web

url = i.id if url.blank? || url !~ /^https?\:\/\//

content = CGI.unescapeHTML(i.content.scrub)
TopicEmbed.import(user, url, i.title, content)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Raw feed HTML becomes stored XSS

High Severity

poll_feed imports external HTML directly and TopicEmbed.import stores it with cook_method set to raw_html. Post#cook then returns raw unchanged, so untrusted feed markup is treated as trusted cooked HTML, enabling stored script injection.

Additional Locations (2)

Fix in Cursor Fix in Web

@topic_view = TopicView.new(topic_id, current_user, {best: 5})
else
Jobs.enqueue(:retrieve_topic, user_id: current_user.try(:id), embed_url: embed_url)
render 'loading'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Embed loading can loop forever

Medium Severity

When no topic exists, embed#best always enqueues :retrieve_topic and renders loading, but it never verifies retrieval can succeed. If TopicRetriever rejects the URL host or cannot resolve embed_by_username, no topic is created and loading.html.erb keeps reloading indefinitely.

Additional Locations (2)

Fix in Cursor Fix in Web

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.

2 participants