React is a popular front-end web library that had a great impact on the application development process. While React is considered to be quite secure, there are still some practices to take into account when applying it to applications.
It happens that developers conclude that React will unquestionably protect their code from all kinds of possible security problems. That’s not always right. As with all things in life, it’s not impossible to mess them up. React.js vulnerabilities can occur when you think that you are using the protective mechanisms of this library. It’s important to remember what React can and can’t handle for you. To avoid frequent security pitfalls it’s important to follow some practices. In this article, we are going to share with you some of the best React.js security practices that you can apply for your projects.
We’ll talk about typical React vulnerabilities, how to find them during a code review, and how to defend against them.
React.js popularity and why we choose it
The React library is known as a powerful tool for creating dynamic and interactive user interfaces. This library is used by many well-known companies, like Facebook, BBC, Instagram, WhatsApp, Netflix. Statistics show that React.js is one of the most popular frameworks in Google Search, which means the popularity of this technology is still growing. It is trusted by top leading companies and platforms. By UppLabs as well. The new version, React 16.8 will offer new features like using React without actually writing a separate class.
React.js development in UppLabs is used for building exceptional user interfaces and single-page applications for all kinds of web and mobile apps. React allows developers to create large web applications that use data that have the ability to change over time without reloading the page. Its purpose is to be fast, simple, scalable. React only processes the user interface in applications. This is consistent with the species in the Model View Controller (MVC) template and can be used in conjunction with other JavaScript libraries or in large MVC frameworks. As a React user interface library, it is most commonly used together with other libraries such as Redux.
Our developers use React.js in many projects. That allowed us to see the strong sides of this instrument. Those who use React.js ecosystem are offered a combination of the following benefits as:
- Reusable components
- Synchronization of application and interface status
- Routing and templating systems
Our developers rely heavily on React.js features while creating frontend tasks. The tool is very powerful, but at the same time is very easy to use.
Why is it important to follow React.js security
If the React.js is an important component of your tech stack, the risks and implications for your business in case of a security leak can be unavoidable. Building React applications for web platforms and SPAs (single page applications) connects your business with various kinds of information. It allows your business to become competitive in the market. The percentage of security flaws identified that appear in every two out of three applications usually show that sometimes developers ignore the importance of such issues and neglect the security practices.
Among the most common security issues in Web applications are:
- Cross-Site Scripting
This is a client vulnerability that can lead to serious problems. XSS attacks occur when an attacker is able to trick a website and force it to execute arbitrary JavaScript code in the browsers of its users.
– The reflected XSS attack can happen through the link containing text information, which is processed by the browser in the form of code. For example, this can be a form field that requires a special request on the client-side.
– A stored XSS attack happens when an attacker has access to the server, and when the code executed on the server can generate the information to the client’s web page. Typical vectors of such attacks are uploading comments and images to servers.
The example can be a Samy worm that exploited the MySpace XSS vulnerability. It was one of the fastest spreading viruses of all time.
import React, {useState} from 'react';
import createDOMPurify from ‘dompurify’;
function App(){
const [text, setText] = useState(‘’);
function updateText(e){
setText(e.target.value);
}
return (
<div>
<input onChange={updateText} type="text" value={text} />
<div dangerouslySetInnerHTML={{__html: createDOMPurify(text)}}/>
</div>
)
}
export default App;
- SQL Injection
SQL injection vulnerabilities allow attackers to execute arbitrary SQL code in the database, allowing them to receive, modify, or delete data regardless of user permissions. A successful injection attack can fake credentials, create new credentials with administrator privileges, gain access to all data on the server, or destroy/modify data to render it unusable. Types of SQL injection include error-based SQL injection, logical-error-based SQL injection, and time-based SQL injection.
- Insecure randomness and links
For web developers, this means that if the content of links is based on data entered by the user, an attacker can add malicious code starting with JavaScript. If the user clicks on this link, an attacker script will be launched in the browser. This happens not only to React projects and the solution depends on the application. In addition, you may need to make corrections on the server. It’s recommended to make the links use the whitelisted protocol (for example, http:) and screen the HTML entities. Links are not the only entities that can be used in this way. But they are the most likely attack target in React applications. Any element can be vulnerable to this attack if an attacker can control its URI (Uniform Resource Identifier) value.
- Server-Side Rendering Attacker-Controlled Initial State
This vulnerability can occur if you are server-side rendering an app. Any version of it can be dangerous for any part of the page. When a developer creates an initial state of the page, it can happen that he can generate a document variable from a JSON string. This vulnerability can look like:
<script>window.__STATE__ = ${JSON.stringify({ data })}</script>
This can be threatening as the JSON.stringify()
method can just convert any data provided to it into a string (as long as it is valid JSON data), and that’s what we’ll see on the page. This pattern is common when server-side React apps with Redux. You can find it in the official Redux documentation and many tutorials with examples on GitHub.
- Arbitrary Code Execution
The arbitrary code execution (ACE) usually refers to an attacker’s ability to execute arbitrary commands or code on a target process. Arbitrary code execution vulnerability is a security flaw in the software or hardware that allows arbitrary code execution. A program that is designed to exploit such a vulnerability is called arbitrary code execution exploit. This vulnerability is dangerous because if it appears in some public product (for example, Windows OS), then all users of this product will be exposed to it (WannaCry ransomware attack was spread because of this kind of vulnerability). - Zip Slip – Arbitrary File write via Archive
The root of the Zip Slip problem is overwriting arbitrary files used in conjunction with a directory traversal attack, which can be implemented while extracting files from the archives. It is possible to exploit Zip Slip through a special archive that contains the file names necessary to implement directory traversal. If such an archive is unpacked using any vulnerable library, the attacker will eventually be able to unzip the malicious files outside the designated directory. In this case, the attacker gets the opportunity to overwrite even an important system or executable files, configuration files, and so on. Ultimately, this will lead to the remote execution of arbitrary code.
Best practices of React.js security
By knowing the most common vulnerabilities of React it’s easier to find a solution and defense against the known enemy. For effective application security, you need to pay special attention to the development of the entire website: to your web application, web server configuration, creating and updating passwords, as well as client-side code. Taking into account the React pitfalls mentioned above and the React security resources, we’ll share with you some of the most common and simple steps you can take to protect your React.js application.
- As a defense against XSS vulnerabilities, remove or disable any markup that could potentially contain instructions for running the code. For HTML, this includes elements such as <script>, <object>, <embed>, and <link>.
- Protect React.js source code with Jscrambler.
- Use secure React Native applications. As React Native is the framework of choice for cross-platform mobile development, developers need to explore options to secure React Native applications.
- Implement Idle Timeout in React.
- Use snippet libraries like ES7 React, Redux, JS Snippets, etc. They’ll bring additional security and keep your code bug free.
- Install a visitor identification to block malicious traffic from getting to the internal program codes.
- Exploit script injection flaws in React.js apps.
- As a defense from insecure links, use the mechanism for opening custom links in new browser tabs.
- The code should behave as expected and should be testable easily. It’s recommended to name your test files as the source files with a .test suffix.
- To escape the rendered JSON, use the serialize-javascript NPM module.
- Scrub the entire React application during and after the development process to seize all the multi-type DDoS attacks.
- Test the functionality of every component using a React app, and tests your complete application once it renders in the browser.
These general React practices will help you to keep your code better organized:
- To organize all your React components, use tools like Bit. It helps code to become discoverable.
- Consolidate duplicate code – DRY (Don’t Repeat Yourself) your code. A common rule for all code is to keep it as brief and precise as possible.
- Attach comments to code only where necessary to avoid a potential conflict between comment and code.
- Mind the naming conventions like SubmitForm submitForm, submit_form, or submit_form. When working with React, you are using JavaScript Extension files and the components that you create for React should, therefore, be named in Pascal case or upper camel case. This translates to names without spaces and capitalizing the first letter. If you want to create a function that submits a form, you should name it in upper camel case or Pascal case.
- Keep the creation of new components to the minimum and create a Button component that can handle icons.
- Keep all files relating to any one component in a single folder. This will allow you to easily extract code to any other project or modify the code whenever you want.
- Name a component after the executed function so that it’s easily recognizable.
- Keep components small and function-specific. This makes testing and maintenance easier.
- Separate stateful aspects from rendering as it will lead to the reduction of components complexity.
The most important thing to keep in mind is that you should understand that while developing web applications you can’t trust any data from the web browser. All user data should be sanitized and tested before it is displayed, or used in SQL queries, and you should avoid resources downloaded through the insecure protocol.
It’s in your hands to protect your business and your application from security attacks, hacks, investment of cost in re-testing, re-development by following easy steps to keep React security vulnerabilities in check and fixing them at each stage.
But, also, it could be in the hands of dedicated React.js developers from UppLabs!
This material prepared in cooperation with UppLabs developers team. Special thanks to Larysa Babak, Yaroslav Ovdii and Pavlo Ihnatiev!