Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed errors on /app/articles/app/page.tsx and added types for isomorphic-dompurify #1179

Merged
merged 3 commits into from
Oct 28, 2024

Conversation

petercr
Copy link
Contributor

@petercr petercr commented Oct 26, 2024

✨ Codu Pull Request 💻

Fixes
It is related to issue #1168 and E2E testing, but more importantly it fixes an issue on the articles page which would not load the corresponding article without crashing.

Pull Request details

  • I tried to view /articles and then click the corresponding link.
  • The Next web server would crash with error: can't resolve module @tiptap/html
  • I fixed the import issues with tiptap/html
  • I then added the types for the isomorphic-dompurify package
  • Manual testing confirms the feature is now working.

Any Breaking changes

None.

Associated Screenshots

Screenshot of the issue now resolved with current PR:
Screenshot_26-10-2024_121041_localhost

@petercr petercr requested a review from a team as a code owner October 26, 2024 16:42
Copy link

vercel bot commented Oct 26, 2024

@petercr is attempting to deploy a commit to the Codú Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Oct 26, 2024

Walkthrough

The changes in this pull request primarily involve modifications to the page.tsx file related to the ArticlePage component. The import of generateHTML has been updated from @tiptap/html to @tiptap/core. The rendering logic has been enhanced to include error handling for null content and to utilize Markdoc.renderers.react for rendering non-Tiptap content. These updates improve the robustness and integration of content rendering within the application.

Changes

File Path Change Summary
app/(app)/articles/[slug]/page.tsx Updated import of generateHTML from @tiptap/html to @tiptap/core. Enhanced rendering logic for Tiptap and non-Tiptap content, including error handling for null values.

Possibly related PRs

Suggested labels

hacktoberfest-accepted, hacktoberfest

Suggested reviewers

  • NiallJoeMaher

🐇 In the land of code where changes bloom,
A shift in imports made room for new gloom.
With Tiptap and Markdoc now dancing in line,
Rendering articles, oh how they shine!
Robust and ready, no errors in sight,
Hopping through changes, everything feels right! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

Hello @petercr, thanks for opening your first Pull Request. The maintainers will review this Pull Request and provide feedback as soon as possible. Keep up the great work!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
app/(app)/articles/[slug]/page.tsx (3)

Line range hint 63-71: Consider enhancing DOMPurify configuration for stricter sanitization.

While the current sanitization is good, consider adding specific DOMPurify configuration options to further restrict allowed content based on your application's needs.

 const renderSanitizedTiptapContent = (jsonContent: JSONContent) => {
   const rawHtml = generateHTML(jsonContent, [...TiptapExtensions]);
-  return DOMPurify.sanitize(rawHtml);
+  return DOMPurify.sanitize(rawHtml, {
+    ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li', 'code', 'pre'],
+    ALLOWED_ATTR: ['href', 'class'],
+    ALLOW_DATA_ATTR: false
+  });
 };

121-123: Document security measures for future maintainers.

While the content is properly sanitized, it's important to document the security measures in place when using dangerouslySetInnerHTML.

 <div
-  dangerouslySetInnerHTML={{ __html: renderedContent ?? "" }}
+  // Security: Content is sanitized via DOMPurify in renderSanitizedTiptapContent
+  dangerouslySetInnerHTML={{ __html: renderedContent ?? "" }}
   className="tiptap-content"
 />
🧰 Tools
🪛 Biome

[error] 122-122: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


Line range hint 90-102: Consider adding runtime type validation for content.

To enhance robustness, consider adding runtime type validation for the content before rendering.

   if (isTiptapContent && parsedBody) {
+    // Validate expected structure of Tiptap content
+    if (typeof parsedBody.content === 'undefined') {
+      console.error('Invalid Tiptap content structure');
+      return <div>Error loading article content</div>;
+    }
     const jsonContent = parsedBody;
     renderedContent = renderSanitizedTiptapContent(jsonContent);
   } else {
+    // Validate Markdoc content
+    if (typeof post.body !== 'string') {
+      console.error('Invalid Markdoc content type');
+      return <div>Error loading article content</div>;
+    }
     const ast = Markdoc.parse(post.body);
     const transformedContent = Markdoc.transform(ast, config);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 871253f and 0ff28cb.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json, !**/*.json
  • package.json is excluded by !**/*.json
📒 Files selected for processing (1)
  • app/(app)/articles/[slug]/page.tsx (2 hunks)
🧰 Additional context used
🪛 Biome
app/(app)/articles/[slug]/page.tsx

[error] 122-122: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (2)
app/(app)/articles/[slug]/page.tsx (2)

17-19: LGTM: Import changes look secure and correct.

The switch to @tiptap/core and the use of isomorphic-dompurify for sanitization are appropriate choices for secure content handling.


126-130: LGTM: Proper handling of non-Tiptap content.

The use of Markdoc.renderers.react for non-Tiptap content is correct and secure.

@@ -119,11 +119,15 @@ const ArticlePage = async ({ params }: Props) => {

{isTiptapContent ? (
<div
dangerouslySetInnerHTML={{ __html: renderedContent }}
dangerouslySetInnerHTML={{ __html: renderedContent ?? "" }}
Copy link
Contributor

Choose a reason for hiding this comment

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

If we fallback to "" should we not have an error thrown?

Copy link
Contributor Author

@petercr petercr Oct 27, 2024

Choose a reason for hiding this comment

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

So without the extra || "" you get a Typescript error warning you that if it ends up getting passes a null value, there will be problems.

It seems like an easy fix, but if you wanted to default to something else I will be happy to change it 👍🏻

Or if you want me to pass in or throw a new error I could add that too.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think if there is no content it should probably be notFound since there is no data (or content) for that page? That make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great I will just bring in the NotFound component then, and replace the empty string instance with that 👍

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
app/(app)/articles/[slug]/page.tsx (2)

Line range hint 63-73: Consider adding error logging for JSON parsing failures.

While the error handling is good, adding error logging would help diagnose content parsing issues in production.

 const parseJSON = (str: string): JSONContent | null => {
   try {
     return JSON.parse(str);
   } catch (e) {
+    console.error('Failed to parse article content:', e);
     return null;
   }
 };

Potential XSS vulnerability in CoursePreview component

The verification revealed inconsistent HTML sanitization across components:

  • app/(app)/articles/[slug]/page.tsx properly uses DOMPurify for sanitization
  • components/Course/CoursePreview.tsx uses dangerouslySetInnerHTML without sanitization for the description prop
  • components/ArticleMenu/ArticleMenu.tsx uses innerHTML safely (only for comparison, not for rendering)

Action items:

  • Add DOMPurify sanitization to CoursePreview component before rendering description
  • Consider creating a shared sanitization utility to ensure consistent usage across components
🔗 Analysis chain

Line range hint 69-73: Verify HTML sanitization is consistently applied.

While the current implementation properly sanitizes Tiptap content using DOMPurify, let's verify that all content paths are properly sanitized.

Also applies to: 123-125

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any direct HTML rendering without sanitization
rg -n "dangerouslySetInnerHTML|innerHTML" --type tsx

# Search for DOMPurify usage to ensure sanitization
rg -n "DOMPurify.sanitize" --type tsx

Length of output: 148


Script:

#!/bin/bash
# Search for any direct HTML rendering without sanitization, trying different file extensions
rg -n "dangerouslySetInnerHTML|innerHTML" --type-add 'web:*.{tsx,jsx,ts,js}'  --type web

# Search for DOMPurify usage to ensure sanitization
rg -n "DOMPurify.sanitize" --type-add 'web:*.{tsx,jsx,ts,js}'  --type web

# Look for imports of DOMPurify
rg -n "import.*DOMPurify" --type-add 'web:*.{tsx,jsx,ts,js}'  --type web

Length of output: 664


Script:

#!/bin/bash
# Check the context around dangerouslySetInnerHTML usage in CoursePreview
rg -B 5 -A 5 "dangerouslySetInnerHTML" components/Course/CoursePreview.tsx

# Check if CoursePreview has DOMPurify import or sanitization
rg "DOMPurify|sanitize" components/Course/CoursePreview.tsx

# Check the full context of ArticleMenu's innerHTML usage
rg -B 5 -A 5 "innerHTML" components/ArticleMenu/ArticleMenu.tsx

Length of output: 758

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0ff28cb and 8c5e709.

📒 Files selected for processing (1)
  • app/(app)/articles/[slug]/page.tsx (2 hunks)
🧰 Additional context used
🪛 Biome
app/(app)/articles/[slug]/page.tsx

[error] 123-123: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (1)
app/(app)/articles/[slug]/page.tsx (1)

17-21: LGTM: Import changes successfully resolve the module resolution issue.

The change from @tiptap/html to @tiptap/core for generateHTML import addresses the original crash issue, while maintaining the required functionality.

Comment on lines +123 to +125
dangerouslySetInnerHTML={{
__html: renderedContent ?? <NotFound />,
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix NotFound component implementation.

The current implementation attempts to use JSX within dangerouslySetInnerHTML which won't work as expected. The NotFound component should be rendered conditionally.

-              dangerouslySetInnerHTML={{
-                __html: renderedContent ?? <NotFound />,
-              }}
+              {...(renderedContent
+                ? {
+                    dangerouslySetInnerHTML: {
+                      __html: renderedContent,
+                    },
+                  }
+                : {}
+              )}
+            >
+              {!renderedContent && <NotFound />}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dangerouslySetInnerHTML={{
__html: renderedContent ?? <NotFound />,
}}
{...(renderedContent
? {
dangerouslySetInnerHTML: {
__html: renderedContent,
},
}
: {}
)}
>
{!renderedContent && <NotFound />}
🧰 Tools
🪛 Biome

[error] 123-123: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

Copy link

vercel bot commented Oct 28, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
codu ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 28, 2024 11:27am

Copy link
Contributor

@NiallJoeMaher NiallJoeMaher left a comment

Choose a reason for hiding this comment

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

🌮 🦖 Nice one!

@NiallJoeMaher NiallJoeMaher merged commit e760be5 into codu-code:develop Oct 28, 2024
6 checks passed
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