You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement embeddable Discourse comments system with iframe support
Add RSS/ATOM feed polling for automatic topic creation and updates
Support raw HTML rendering for imported content with URL absolutization
Add embed controller with host validation and rate limiting
Diagram Walkthrough
flowchart LR
A["External Site"] -->|embed_url| B["EmbedController"]
B -->|validate host| C["TopicRetriever"]
C -->|check cache| D["TopicEmbed"]
C -->|poll feed| E["PollFeed Job"]
E -->|parse RSS| F["SimpleRSS"]
F -->|import content| G["TopicEmbed.import"]
G -->|create post| H["PostCreator"]
H -->|raw_html cook| I["Post"]
I -->|render| J["Embed View"]
J -->|iframe| A
Below is a summary of compliance checks for this PR:
Security Compliance
⚪
Clickjacking exposure
Description: X-Frame-Options is set to "ALLOWALL", which disables clickjacking protection and allows the page to be framed by any site, enabling potential UI redress attacks. embed_controller.rb [28-28]
Description: The postMessage target origin is set to the unvalidated request referer, allowing a malicious referer to receive sensitive data via window.postMessage. embed.html.erb [7-15]
Referred Code
(function() {
window.onload = function() {
if (parent) {
// Send a post message with our loaded height
parent.postMessage({type: 'discourse-resize', height: document['body'].offsetHeight}, '<%= request.referer %>');
}
}
})();
</script>
Unvalidated external fetch
Description: External feed content and links are fetched and used without URL allowlisting or timeouts, and HTML is unescaped and imported, potentially enabling SSRF or importing malicious content. poll_feed.rb [28-37]
Description: Posts are created with cook_method raw_html and skip_validations true, allowing raw HTML from external sources to be stored and rendered, increasing XSS risk if sanitization is bypassed. topic_embed.rb [22-37]
Referred Code
creator=PostCreator.new(user,title: title,raw: absolutize_urls(url,contents),skip_validations: true,cook_method: Post.cook_methods[:raw_html])post=creator.createifpost.present?TopicEmbed.create!(topic_id: post.topic_id,embed_url: url,content_sha1: content_sha1,post_id: post.id)endendelsepost=embed.post# Update the topic if it changedifcontent_sha1 != embed.content_sha1revisor=PostRevisor.new(post)revisor.revise!(user,absolutize_urls(url,contents),skip_validations: true,bypass_rate_limiter: true)embed.update_column(:content_sha1,content_sha1)
Weak origin check
Description: Origin check uses indexOf substring match instead of strict equality, which can be bypassed by attacker-controlled domains containing the trusted domain as a substring. embed.js [16-21]
Follow the guide to enable codebase context checks.
Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code
Objective: Ensure all identifiers clearly express their purpose and intent, making code self-documenting
Status: Passed
Generic: Secure Logging Practices
Objective: To ensure logs are useful for debugging and auditing without exposing sensitive information like PII, PHI, or cardholder data.
Status: Passed
🔴
Generic: Security-First Input Validation and Data Handling
Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent vulnerabilities
Status: Raw HTML Rendering: Posts imported from external sources are rendered as raw HTML without explicit sanitization, creating potential XSS via untrusted content.
Referred Code
# If there is no embed, create a topic, post and the embed.ifembed.blank?Topic.transactiondocreator=PostCreator.new(user,title: title,raw: absolutize_urls(url,contents),skip_validations: true,cook_method: Post.cook_methods[:raw_html])post=creator.createifpost.present?TopicEmbed.create!(topic_id: post.topic_id,embed_url: url,content_sha1: content_sha1,post_id: post.id)end
⚪
Generic: Comprehensive Audit Trails
Objective: To create a detailed and reliable record of critical system actions for security analysis and compliance.
Status: Missing Auditing: Critical actions like enqueueing topic retrieval and access validations do not emit audit logs capturing user, timestamp, action, and outcome.
Generic: Robust Error Handling and Edge Case Management
Objective: Ensure comprehensive error handling that provides meaningful context and graceful degradation
Status: Input Validation: External feed content (URLs and HTML) is parsed and imported without explicit validation or error handling around network failures or malformed content beyond basic presence checks.
Objective: To prevent the leakage of sensitive system information through error messages while providing sufficient detail for internal debugging.
Status: Error Detail: Raised errors include specific reasons like 'invalid referer host' that may reveal validation logic to end users if surfaced directly.
A new raw_html post type bypasses sanitization, creating a stored XSS vulnerability from imported RSS/ATOM feed content. To fix this, all imported HTML must be strictly sanitized before being stored.
# app/models/post.rbdefcook(*args)# Bypasses sanitization for raw_html postsreturnrawifcook_method == Post.cook_methods[:raw_html]# Default cooking/sanitizationPlugin::Filter.apply(:after_post_cook,self,post_analyzer.cook(*args))end# app/models/topic_embed.rbdefself.import(user,url,title,contents)# ...# Creates a post with raw HTML from a feed, without sanitizationcreator=PostCreator.new(user,raw: absolutize_urls(url,contents),cook_method: Post.cook_methods[:raw_html])# ...end
After:
# app/models/topic_embed.rbdefself.import(user,url,title,contents)# ...# Sanitize the HTML content before storing itsanitized_contents=sanitize_html(contents)# Creates a post with the sanitized HTMLcreator=PostCreator.new(user,raw: absolutize_urls(url,sanitized_contents),cook_method: Post.cook_methods[:raw_html])# ...end# A new helper method for sanitizationdefself.sanitize_html(html)# Use a library like Loofah or Nokogiri::HTML::Sanitizer# with a strict allow-list of tags and attributes.# Example:Loofah.fragment(html).scrub!(:prune).to_htmlend
Suggestion importance[1-10]: 10
__
Why: The suggestion correctly identifies a critical stored XSS vulnerability introduced by bypassing the sanitization pipeline for raw_html posts, which is a major security flaw.
High
More
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
PR #4
PR Type
Enhancement
Description
Implement embeddable Discourse comments system with iframe support
Add RSS/ATOM feed polling for automatic topic creation and updates
Support raw HTML rendering for imported content with URL absolutization
Add embed controller with host validation and rate limiting
Diagram Walkthrough
File Walkthrough
14 files
New embed controller for comment displayAsync job to retrieve embedded topicsScheduled job for RSS/ATOM feed pollingAdd raw HTML cook method supportNew model for managing embedded topicsTopic retrieval with validation and throttlingSupport cook_method parameter in post creationAdd skip_validations option to post revisionView template for embedded comments displayLoading state view for embedded commentsEmbed layout with postMessage height resizingClient-side embed script with iframe integrationStyling for embedded comments displayRefactor Disqus import to use TopicEmbed5 files
Add embed best comments routeCreate topic_embeds table with indexesAdd cook_method column to posts tableAdd force true to top_topics table creationAdd embedding configuration settings1 files
Fix trailing whitespace in migration file2 files
Add embedding category to admin settingsAdd embed-related i18n strings and settings1 files
Add ruby-readability and simple-rss gems4 files
Tests for embed controller functionalityTests for feed polling job executionTests for topic embed model and importTests for topic retriever validation logic