DEV Community

Cover image for Low-Hanging Fruits of Web Security
Karma
Karma

Posted on • Edited on • Originally published at karmasakshi.Medium

Low-Hanging Fruits of Web Security

I talk about implementing common headers in your web app to increase its security.

Headers

  1. Access-Control-Allow-Origin: Defines domains that can access your content. MDN link.

  2. Permissions-Policy: Defines permissions your web app can request for. W3C link.

  3. Referrer-Policy: Defines how much information you share with link B about link A when you go from link A to link B. MDN link.

  4. Strict-Transport-Security: Defines whether or not https:// should be compulsory when accessing your web app. MDN link.

  5. X-Content-Type-Options: Mandates content to be of the type defined. MDN link.

  6. X-Frame-Options: Defines whether or not your web app can be loaded within an iframe or other embed elements. MDN link.

  7. X-XSS-Protection: Defines Cross-Site Scripting filter level. MDN link.

Examples

Say you have a web app hosted on https://example.com:

const HEADERS = [
  {
    key: 'Access-Control-Allow-Origin',
    value: 'https://example.com'
  },
  {
    key: 'Permissions-Policy',
    value: 'autoplay=(), camera=(), fullscreen=(), geolocation=(), microphone=()'
  },
  {
    key: 'Referrer-Policy',
    value: 'no-referrer'
  },
  {
    key: 'Strict-Transport-Security',
    value: 'max-age=63072000; includeSubDomains; preload'
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff'
  },
  {
    key: 'X-Frame-Options',
    value: 'DENY'
  },
  {
    key: 'X-XSS-protection',
    value: '1; mode=block'
  }
]
Enter fullscreen mode Exit fullscreen mode

On Next.js apps deployed on Vercel, you set the headers in next.config.js like so:

// next.config.js

const headers = async () => [
  {
    source: '/(.*)',
    headers: // Paste HEADERS here
  }
];
module.exports = {
  headers
};
Enter fullscreen mode Exit fullscreen mode

On SPAs deployed on Firebase Hosting, you set the headers in firebase.json like so:

// firebase.json

{
  "hosting": {
    "headers": [
      {
        "source": "**",
        "headers": // Paste HEADERS here
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

You may want to change the value of Access-Control-Allow-Origin header to allow CORS.

You may also want to change the value of Permissions-Policy header based on permissions you intend to ask for.

CSP: The King of Security Headers

Content-Security-Policy (MDN link) is an extremely powerful header since it combines various policies, allowing you to define the security policy of your web app in a fine-grained fashion. It is difficult to get right in the first attempt, so it behoves to not be included in the “low-hanging fruits” list above — but you shouldn’t skip it. It guarantees visitors have a safe time on your web app.

To build the tightest CSP for your web app, it is recommended to start with locked-down policies and open them up as you proceed. Chrome is very descriptive about CSP violations so it is easy to know which policy to open-up next. It is essential to test all features of your web app to ensure there are no violations. Use a new Incognito window every time you make changes to any policy to ensure you aren’t working with cached results.

It is common to disable CSP during development to allow tools to work properly. You can use an environment variable to disable CSP during development. Here’s an example of a CSP header configuration of a Next.js app that uses Google Fonts (note the usage of environment variable NEXT_PUBLIC_IS_PRODUCTION):

// next.config.js

const HEADERS = [
  ...,
  {
    key: 'Content-Security-Policy',
    value: process.env.NEXT_PUBLIC_IS_PRODUCTION === 'true' ? "connect-src 'self'; default-src 'self'; font-src https://fonts.gstatic.com; img-src 'self' data:; manifest-src 'self'; object-src 'none'; script-src 'self'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; upgrade-insecure-requests;" : ''
  },
  ...
]
Enter fullscreen mode Exit fullscreen mode

You can evaluate the strictness of your policy using Google’s CSP Evaluator.

Quantifying the Result

Mozilla Observatory is to Web Security, what Lighthouse is to Web Performance. It rates the security of your web app and provides suggestions to improve that rating. It also integrates 3rd party scanners like Security Headers so you can have multiple opinions.

Mozilla Observatory’s security score of Share By Cam


Was I able to help you increase your web app’s security score? Let me know on my Twitter. Cheers!

Top comments (2)

Collapse
 
edydeyemi profile image
Edydeyemi

Thanks for this. It is quite informative

Collapse
 
lowlifearcade profile image
Sonny Brown

Very nice article