0

I'm building a block that shows a bunch of posts of a custom post type. This is the loop that prints them:

{ customposts.map( ( custompost, index ) => {
    return <div key={ index } className="custom-post">
        <h2 id={ custompost.id } className="custom-post-title">{ custompost.title.raw }</h2>
            <div className="custom-post-content">{ custompost.content.rendered }</div>
        </div>;
} ) }

But, using either custompost.content.raw or custompost.content.rendered shows uninterpreted HTML code. In the first case, it prints the blocks markup (with HTML comments), and in the second case, the HTML markup, but in both cases, the code is shown verbatim.

If I wrap this with a RawHTML component, the content is shown correctly, but according to the docs, this is discouraged as this is prone to cross-site scripting.

// This is discouraged
<div className="custom-post-content"><RawHTML>{ custompost.content.rendered }</RawHTML></div>

What is the best practice for displaying post content in the block editor?

1 Answer 1

2

It is true that using RawHTML (or dangerouslySetInnerHTML) is discouraged and indeed prone to XSS attacks like <img src=x onerror=alert(1)//> and <p>abc<iframe//src=jAva&Tab;script:alert(3)>def</p>.

But if you need to set HTML directly from React, then you'll have to use dangerouslySetInnerHTML, either directly (e.g. <div dangerouslySetInnerHTML={ ({ __html: 'foo <b>bar</b>' }) } />) or via RawHTML in Gutenberg (e.g. <RawHTML>{ 'foo <b>bar</b>' }</RawHTML>).

However, whether it's React, jQuery or even vanilla JS (direct access on innerHTML), the recommended practice has always been to sanitize the HTML, or ensuring it's safe, before passing it to the browser.

So despite WordPress does not (yet) have HTML sanitization functions in JS, there are actually libraries such as DOMPurify that we can use to ensure the HTML is safe.

And there are other libraries out there that you could choose from, but I thought DOMPurify is awesome, so here's an example assuming you've installed the package:

// At the top in your file:
import DOMPurify from 'dompurify';
// or you can use wp_enqueue_script() to "normally" load the src/purify.js or
// dist/purify.min.js file, and a global window variable named DOMPurify will
// be available on the page.

// Then somewhere in your code, use DOMPurify.sanitize() to sanitize the HTML:
<div className="custom-post-content">
    <RawHTML>{ DOMPurify.sanitize( custompost.content.rendered ) }</RawHTML>
</div>

So I hope that helps & Happy coding! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.