Technology

Does Security Matter to Front End Developers and Tips To Not Get Hacked

Security is more important than ever before. Breaches can happen to anyone, whether it’s a large corporation or a small site. We need to be careful not to expose customer data, and we need to be aware of the many attacks that are possible and the errors that can happen when deploying a website or app.

A topic is often overlooked by frontend developers

Nothing in development happens in isolation — a front end does nothing without a back end, and a back end can’t be used without a front end into it, and on and on it goes. We all work together and washing your hands of things that “aren’t my job” is irresponsible and dangerous.

So yes, the responsibility for securing the user’s data is shared between both backend and frontend. And here’s the quick-n-dirty on the two most common ways we can protect our people:

1. Use a strong content security policy

Sound content security policy (CSP) is the cornerstone of safety in frontend applications. CSP is a standard that was introduced in browsers to detect and mitigate certain types of code injection attacks, including cross-site scripting (XSS) and clickjacking.

Strong CSP can disable potentially harmful inline code execution and restrict the domains from which external resources are loaded. You can enable CSP by setting Content-Security-Policy header to a list of semicolon-delimited directives. If your website doesn’t need access to any external resources, a good starting value for the header might look like this:

Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self'; connect-src 'self';

Here we set script-srcimg-srcstyle-src, and connect-src directives to self to indicate that all scripts, images, stylesheets, and fetch calls respectively should be limited to the same origin that the HTML document is served from. Any other CSP directive not mentioned explicitly will fallback to the value specified by default-src directive. We set it to none to indicate that the default behavior is to reject connections to any URL.

However, hardly any web application is self-contained nowadays, so you may want to adjust this header to allow for other trusted domains that you may use, like domains for Google Fonts or AWS S3 buckets for instance, but it’s always better to start with the strictest policy and loosen it later if needed.

2. Enable XSS protection mode and avoid typical mistakes

Enable XSS protection mode

If malicious code does get injected from user input, we can instruct the browser to block the response by supplying "X-XSS-Protection": "1; mode=block" header.

Although XSS protection mode is enabled by default in most modern browsers, and we can also use content security policy to disable the use of inline JavaScript, it is still recommended to include X-XSS-Protection header to ensure better security for older browsers that don’t support CSP headers.

Avoid typical XSS mistakes

While much less common when using modern JavaScript frameworks, it’s still possible to code in inadvertent XSS flaws into your front end. 

“Let’s say we wanted to address a user by their name by linking to them from a marketing email,” James Hall, director of digital innovation agency Parallax, suggests. “Adding ?name=James to the query string, and then simply adding that to the DOM, would be a quick way to do it.”

For example:

document.querySelector('.tagline').innerHTML = nameFromQueryString

James warns that using code like the above, however, means anyone can inject code into your site and take over. He cautions that just by changing the name to <script src="my.malicious.site">, an attacker could craft a URL that can make a fake payment page look like it’s serving from your SSL-encrypted website.

3. Use a modern framework that handles security automatically 

Modern UI frameworks like React, Vue, and Angular have a good level of security built into them, and can largely eliminate the risks of XSS attacks. They automatically encode HTML output, reduce the need for using XSS-susceptible DOM APIs, and give unambiguous and cautionary names to potentially dangerous methods, like dangerouslySetInnerHTML.

4. Be more selective with third-party scripts

What should be aware…

Third-party services like Google Analytics, Intercom, Mixpanel, and a hundred others can provide a “one line of code” solution to your business needs. At the same time, they can make your website more vulnerable, because if a third-party service gets compromised, then so will be your website. Especial care should be taken when using Google Tag Manager, Segment, or any other tools that allow anyone in your organization to integrate more third-party services.

For example: Using Google Tag Manager makes it very easy to add the latest tracking scripts, that chatbot the support team wanted, and Hotjar for user analytics. While it’s tempting to allow everyone in an organization (and sometimes outside) access to your Google Tag Manager, however, if a Google account gets hacked, it’s possible to add any arbitrary JavaScript to your website, and a sophisticated attack could take your users off to a fake payment page for them to complete their order, sending money to someone else.

Tips when integrating a third-party service

  • Make sure to set the strongest CSP policy that would still permit that service to work normally. Most of the popular services have documented what CSP directives they require, so make sure to follow their guidelines.
  • Be really mindful of the data you’re exposing to the front end in your code.  The less information you’re giving away, the less you’ll need to make people aware of in your privacy policy, which means there’s a lower chance of violating GDPR, the EU’s General Data Protection Regulation (GDPR)
  • Make sure to include integrity attribute when possible. Browsers have the Subresource Integrity feature that can validate the cryptographic hash of the script that you’re loading and make sure that it hasn’t been tampered with.

This how your script tag may look like:

<script src="https://example.com/example-framework.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>

5. Consider using textContent instead of innerHTML

To prevent XSS attacks, you can use a sanitization library like DOMPurify (see below, under 11), but front end consultant Zell Liew suggests that, if you’re changing text only, you can use textContent instead of innerHTML

“Let’s say you want to get a text value from an input field, and you want to output that text value into the DOM. Here’s the code to get the text value:

const value = input.value

But the user can try to enter something malicious, like this snippet:

<img src="x" onerror=alert("HACKED!")>

If you use innerHTML, you’ll create the <img> element and run the onerror handler. This is where XSS begins.” Using textContent instead, as it can only output text and doesn’t generate any HTML. 

“If you don’t generate HTML, there’s no way to insert JavaScript,” Zell explains. You’ll see <img src="x" onerror=alert("HACKED!")> in the DOM, but the JavaScript won’t run.

6. Keep your dependencies up to date

A quick look inside node_modules folder will confirm that our web applications are lego puzzles built out of hundreds (if not thousands) dependencies. Ensuring that these dependencies don’t contain any known security vulnerabilities is very important for the overall security of your website.

The best way to make sure that dependencies stay secure and up-to-date is to make vulnerability by checking a part of the development process. To do that, you can integrate tools like Dependabot and Snyk, which will create pull requests for out-of-date or potentially vulnerable dependencies and help you apply fixes sooner.

 7. Don’t leak referrer value

Finally, be really mindful of the data you’re exposing to the front end in your code. 

Limit access to browser features & APIs

Part of good security practice is restricting access to anything that is not needed for the proper use of our website. 

When you click on a link that navigates away from your website, the destination website will receive the URL of the last location on your website in a referrer header. That URL may contain sensitive and semi-sensitive data (like session tokens and user IDs), which should never be exposed.

To prevent leaking of referrer value, we set Referrer-Policy header to no-referrer:

"Referrer-Policy": "no-referrer"

This value should be good in most cases, but if your application logic requires you to preserve referrer in some cases, check out this article to know the way we should break down all possible header values and when to apply them.

Conclusion

There are many variations of UI-first attacks that malicious users can take advantage of, but you can greatly increase your chances of defending against them if you follow the recommendations given in this article.

Leave a comment