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

React inline styles blocked by CSP policy for 'style-src' #5878

Closed
subyraman opened this issue Jan 19, 2016 · 12 comments
Closed

React inline styles blocked by CSP policy for 'style-src' #5878

subyraman opened this issue Jan 19, 2016 · 12 comments

Comments

@subyraman
Copy link

I'm working on an application that has a strict CSP policy including style-src, which prevents the possibility of using inline styles. If I attempt to use React's builtin CSS templater with the following component, the styling is blocked with an error.


class SomeComponent extends React.Component {
    constructor() {
        super();

        this.styles = {
            backgroundColor: 'red',
            color: 'blue',
        };
    }

    render() {
        return <div ref="someDiv" style={this.styles}>Some Component</div>;
    }
}


DOM.render(<SomeComponent />, document.getElementById('main'));

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

I can get around this by manually manipulating the DOM's style object after every React render:


class SomeComponent extends React.Component {
    constructor() {
        super();

        this.styles = {
            backgroundColor: 'red',
            color: 'blue',
        };
    }

    componentDidMount() {
        _.extend(this.refs.someDiv.style, this.styles);
    }

    componentDidUpdate() {
        _.extend(this.refs.someDiv.style, this.styles);
    }

    render() {
        return <div ref="someDiv">Some Component</div>;
    }
}


DOM.render(<SomeComponent />, document.getElementById('main'));

I'm wondering if React's DOM engine can set the style object instead of serializing to a string and inserting a style attribute in the markup? This would make React adhere more tightly to CSP.

Would a pull request on this be welcomed?

@zpao
Copy link
Member

zpao commented Jan 19, 2016

In its current form (0.14) React generates a string of markup in a single pass and then inserts it. Ultimately this is a single dom operation and historically has been faster. This goes for the style as well. Updates are applied individually.

In the next version we'll be using createElement instead of innerHTML but I think we still set initial style all together - not sure if that matters for csp since the element is already created at that point. Can you try a build from master and see if it works (http://react.zpao.com/builds/master/latest)

Also cc @spicyj in case he knows if we actually do set each style property individually on initial render (and if we should if we don't currently)

@SlexAxton
Copy link

not sure if that matters for csp since the element is already created at that point.

Nah, the only way to bypass this stuff is to use the style props on the dom element directly elem.style.border = '1px solid blue'; (setStyle api also works).

My gut is that it'd definitely be slower by a usually insignificant amount. Perhaps it'd be a good thing to be able to configure (or just bypass with rawStyle="exact string we'll inject into style attr").

Thus far to get around this, I've been a fan of solutions that allow you to write the inline-looking css, but still end up generating a class name and pushing the styles into an external file. This works well unless you have dynamic variable values that you'd like to modify on the fly.

@sophiebits
Copy link
Contributor

We do set styles individually in master and it'll be in v15. Until then I suppose you'll need to add unsafe-inline to style-src.

@sophiebits
Copy link
Contributor

Note that server rendering will still generate style="..." markup by necessity.

lmorchard added a commit to lmorchard/testpilot that referenced this issue May 16, 2017
…ine React styles

- Also inject content-security-policy header in the local dev server

- See also: facebook/react#5878 (comment)

Issue mozilla#2434
lmorchard added a commit to lmorchard/testpilot that referenced this issue May 16, 2017
…ine React styles

- Also inject content-security-policy header in the local dev server

- See also: facebook/react#5878 (comment)

Issue mozilla#2434.
Fixes mozilla#2432.
@xkr47
Copy link

xkr47 commented Jan 29, 2018

As an interesting side note, HTML 5.2 supports <style> blocks in most elements inside and thus one could perhaps use <style nonce="..."> to create local styles instead of inline styles..

@xkr47
Copy link

xkr47 commented Jan 29, 2018

But maybe, for server-side rendering, the server could scan the generated html for style attributes and automatically add sha256 hashes for the attribute values in the CSP header in the response?

@xkr47
Copy link

xkr47 commented Feb 1, 2018

Yes! Scanning the server-side rendered html and adding sha256 for all <script>, <style> and 'style="..."things worked perfectly! No need for'unsafe-inline'or'nonce'` stuff. I will try to publish a npm module with my code. Will post about it here.

@elimisteve
Copy link

@sophiebits

Until then I suppose you'll need to add unsafe-inline to style-src.

Unfortunately that would make our React-powered sites vulnerable to clever attacks/injections, such as this CSS-only keylogger: https://no-csp-css-keylogger.badsite.io/

Do you believe that @xkr47's proposed solution above a good one, as it seems to be? Thanks.

@xkr47
Copy link

xkr47 commented Mar 21, 2018

The problem with my solution is it does not work in all browsers; probably need different CSP configs based on user agent.. But at least it worked great in Firefox :)

@mattferderer
Copy link

@elimisteve You could block that specific css-only keylogger example with a strict img-src policy.

@graingert
Copy link

But maybe, for server-side rendering, the server could scan the generated html for style attributes and automatically add sha256 hashes for the attribute values in the CSP header in the response

This defeats the point of CSP here, because if someone injected inline styles you'd mark them as acceptable in the header

@xkr47
Copy link

xkr47 commented Jun 30, 2018

[@graingert] This defeats the point of CSP here, because if someone injected inline styles you'd mark them as acceptable in the header

😳

Yes.. So some mechanism to register acceptable dynamic styles while rendering the actual components would perhaps be needed.. For example to render a component showing a web shop product with some product-specific url (which is unaffected by direct user input) in its inline styles, one could have some context object or similar where one could report trusted style snippets and after rendering they would be merged and a proper CSP header generated.. ?

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

8 participants