18

I created a sample react app using "create-react-app". I need to set the request headers with X-Frame-options and Content-Security-Policy. How do I do this? I just tried to update my index.html with the below code, but I'm not sure whether this it's right or not. Can anyone help with this?

   <meta http-equiv="Content-Security-Policy" content="frame-ancestors 'none'">
   <meta http-equiv="X-Frame-Options" content="SAMEORIGIN"> 
SOLO
  • 868
  • 9
  • 19
knbibin
  • 1,099
  • 7
  • 18
  • 36
  • update the index.html should be fine .. – user2473779 Apr 18 '18 at 09:57
  • Could you elaborate about what you are referring to? Are you referring to request headers as in the http headers when you are sending an HTTP request to an API endpoint? – Jackyef Apr 18 '18 at 10:47
  • @Jackyef: I want to send the http response headers with x-Frame-Options that instruct the browser to restrict framing where it is not allowed. – knbibin Apr 18 '18 at 11:58

5 Answers5

9

You have to override some webpack config that comes with create-react-app and add "X-Frame-Options": "SAMEORIGIN".

But in CRA, you can't do that directly with a webpack.config.js. You gotta use a package that rewires the way CRA start / build your app. Here are the rewiring packages you can use:

  • react-app-rewired (CRA v1)
  • customize-cra or rescript (CRA v2)
  • craco (CRA v3)

To know which CRA version you used, you can roughly follow the react-scripts version in your package.json.

craco

I succeeded with this craco config!!! In craco.config.js:

module.exports = {
    webpack: {
        headers: {
            'X-Frame-Options': 'Deny'
        }
    }
}

(I tested by scanning in Burpsuite; the Frameable Response issue was gone.)

Reference: How to set alias path via webpack in CRA (create-react-app) and craco?

react-app-rewired

I THINK you could try this, BUT I haven't tested it. In config-overrides.js:

module.exports = {
    devServer: function(configFunction) {
        return function(proxy, allowedHost) {
            const config = configFunction(proxy, allowedHost)
            config.headers = {
                'X-Frame-Options': 'Deny'
            }
            return config
        }
    }
}

Reference: Create React App adding CORS header

*I may have loosely gotten the versions wrongly, please correct if so.

hoohoo-b
  • 1,141
  • 11
  • 12
  • 1
    The sample for *react-app-rewired* works, I confirm. – Monsignor May 26 '21 at 05:10
  • 1
    THANK YOU! THIS WAS SO HELPFUL! Now if anyone can tell me why the headers work locally but now when deployed to Heroku (using react-app-rewired), I would be even more grateful :D – Pranav Pillai Sep 23 '21 at 16:32
  • With Craco 6.1 I had to set the `devServer` export instead: `module.exports = { devServer: (cfg) => { cfg.headers = { 'X-Frame-Options': 'Deny' }; return cfg }, ... ` – z0r Feb 07 '22 at 10:32
8

Simply modifying index.html as you have is not sufficient, at least for X-Frame-Options. Per OWASP:

Common Defense Mistakes

Meta-tags that attempt to apply the X-Frame-Options directive DO NOT WORK. For example, ) will not work. You must apply the X-FRAME-OPTIONS directive as HTTP Response Header...

MDC has a similar warning.

I spent some time looking, but didn't find a way to set X-Frame-Options in React itself. There are ways to do it at the server level or in other languages (e.g. for Tomact, or in Java, or with webpack, or configure it with Spring Security), which may or may not be helpful to you.

React doesn't seem to support Content-Security-Policy either... at least not as of 2013, and I searched but did not find any more recent change in position.

Community
  • 1
  • 1
SOLO
  • 868
  • 9
  • 19
  • 2
    With all that being said, I would love it if I just missed something and someone _could_ point to a way to do this in React. – SOLO Apr 24 '18 at 21:58
  • Yes, if somebody have any solution for how to do it in reactjs please reply – Amol Chaudhari May 21 '20 at 07:23
  • I used craco to inject a few headings for webpack's devServer, which is what npm start with CRA uses. worked first time. headers: { 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Embedder-Policy': 'require-corp', }, craco is a bit of a commitment, though. It helps if you've been driven crazy by the problem you're trying to solve. – OsamaBinLogin Mar 12 '23 at 04:35
5

If you are talking specifically for the dev server, you can configure the underlying express instance using the 'manually configure proxy' process.

You can set headers there:

// src/setupProxy.js

module.exports = function(app) {
  app.use((req, res, next) => {
    res.set({
        'foo': 'bar'
    });
      next();
  }); 
};
dwjohnston
  • 11,163
  • 32
  • 99
  • 194
3

For react-scripts start update your src/setupProxy.js:

module.exports = function (app) {
  app.use(function (req, res, next) {
    res.setHeader("X-Frame-Options", "DENY");
    next();
  });
};

If you in the Heroku and use buildpacks update static.json:

{
  "root": "build/",
  "https_only": true,
  "clean_urls": true,
  "routes": {
    "/**": "index.html"
  },
  "headers": {
    "/**": {
      "X-Frame-Options": "DENY"
    }
  }
}

If you host your app via Apache (production):

RequestHeader setIfEmpty X-Frame-Options "DENY"

or for older (pre-v2.4.7) with set:

<Location /app>
    RequestHeader set X-Frame-Options  "DENY"
</Location>
gavenkoa
  • 45,285
  • 19
  • 251
  • 303
0

x-frame-options and content-security-policy are response headers and not request headers. So you need to put it on server and not in react app (client)

pantech
  • 69
  • 2
  • 6