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

Consider not using dangerouslySetInnerHTML #16

Open
sebranly opened this issue Apr 21, 2020 · 6 comments
Open

Consider not using dangerouslySetInnerHTML #16

sebranly opened this issue Apr 21, 2020 · 6 comments

Comments

@sebranly
Copy link

sebranly commented Apr 21, 2020

Thank you for this package, I came across it following this issue: #9, as I'm still learning about dangerouslySetInnerHTML and XSS.

I noticed that this package uses dangerouslySetInnerHTML:

      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(this.props.item, safeJsonLdReplacer, this.props.space)
        }}
      />

In order to modify head on the website I'm working on, I use https://github.com/staylor/react-helmet-async which is an improved fork of https://github.com/nfl/react-helmet, for React 16+.

I noticed https://github.com/nfl/react-helmet readme has an example for JSON-LD which doesn't use dangerouslySetInnerHTML:

<Helmet>
    {/* inline script elements */}
    <script type="application/ld+json">{`
        {
            "@context": "http://schema.org"
        }
    `}</script>
</Helmet>

(please note that I added the first and last lines to make the example shorter)

I suppose in the case of https://github.com/google/react-schemaorg, such a syntax (not using dangerouslySetInnerHTML) wasn't followed because it has constraints:

I suppose https://github.com/google/react-schemaorg is aiming for simplicity and not using any Helmet package for this reason.


If within a project we have the choice then what would you recommend please?

Option a)

      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(this.props.item, safeJsonLdReplacer, this.props.space)
        }}

Option b)

    <Helmet>
      <script type="application/ld+json">{JSON.stringify(this.props.item, safeJsonLdReplacer, this.props.space)}</script>
    </Helmet>

Thank you in advance for your time!

@sebranly
Copy link
Author

Please note that I got some inspiration from this other issue: nfl/react-helmet#333 (comment)

@Eyas
Copy link
Collaborator

Eyas commented Apr 21, 2020

Yeah this package isn't particularly compatible with Helmet.

We need dangerouslySetInnerHtml for our use case because react by default parses the contents of <script> as text, meaning that characters like { and } will be escaped.

Helmet goes around that, which is why this works for them, but not for vanilla react.

It seems like part of your ask is to export safeJsonLdParser so that someone using Helmet can use it?

@Eyas
Copy link
Collaborator

Eyas commented Apr 21, 2020

For helmet, I often found that using its attributes section is easier, e.g.:

<Helmet
  htmlAttributes={{ lang: "en" }}  //Example,
  title="..."
  script={[
    {
      type: "application/ld+json",
      innerHTML: JSON.stringify(graph)
    },
   // ...
  ]}
/>

Only thing is that you'd need to use a safe JsonLD replacer in that JSON.stringify as well.

It might make sense to have a flavor of react-schemaorg that returns a JSX.IntrinsicElements["script"] here.

@sebranly
Copy link
Author

Thank you for the quick answers! I was writing this issue while trying to understand XSS vulnerabilities more in-depth in the context of LD-JSON script tags. I think part of my ask would become exporting safeJsonLdParser yes, unless this package you're maintaining offers a prop to customize either using the current solution (dangerouslySetInnerHTML) or the Helmet solution. But maybe this package has to stay vanilla react because of size of dependencies or other factors?

I'm also curious whether there was a reason for using safeJonLdParser rather than using a package such as https://github.com/cure53/DOMPurify which exposes a sanitize function please.

In your latest example, are you suggesting using a replacer as well because innerHTML is dangerous such as dangerouslySetInnerHTML? (https://zhenyong.github.io/react/tips/dangerously-set-inner-html.html)

@Eyas
Copy link
Collaborator

Eyas commented Apr 21, 2020 via email

@Eyas
Copy link
Collaborator

Eyas commented Jun 19, 2020

Check out the readme, out of 1.1.0 there's now native support for Helmet via the script={[...]} props.

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

No branches or pull requests

2 participants