React SSR using Express JS and resolving XSS Cross site vulnerability

John Panugaling
AIA Singapore Technology Blog
4 min readMay 19, 2023

Nowadays, we have lots of tools and libraries to use like Next.js, that supports Server-side rendering for a lot of frontend frameworks out there.

Right now, I am going to share to you my experience on how I managed to do it using only Express.js that also allowed me to achieve the requirements given by the client, plus resolving the XSS Cross site vulnerability.

Given:

  • an existing React project with full integration and deployment functionalities using Webpack
  • this application is a like a base template for multiple products. Meaning, the components shown are dynamic depending on the what the product is. (name, description, price, banner images, logo, etc…)

Requirement:

  • we need to add dynamic Open Graph meta tags to have a good look when people share our URLs to social media and messaging applications.

Initial solution:

One solution I had in mind was react-helmet, but when I used it, it doesn’t seem to work as what I expected. It actually has the OG META TAGs with correct values, but it was set right after when you load the page. So in that case, it won’t suffice the requirement, mainly because what we need is to directly show the values even without loading the page. This means that our index.html should already have the OG meta tags before rendering to the browser. (Maybe there is a way using react-helmet, but I just don’t know)

Normally, when we deploy to production, we will use our dist folder and host it statically. But this time, I thought of creating a node server of my own, so that it will go to a controller first before rendering static data.

So I created a new file called “./server/index.js”

(Check the Final Solution part)

Below is the existing output of webpack. The default content values will be explained further below:

./dist/index.html

How I got the XSS Cross site Vulnerability

Previously I used these ways below, but I always got vulnerability issue.

  1. read file from “./dist/index.html”
  2. replace the default OG meta tags with the correct values
  3. send it back to browser

But these examples above give me the XSS Cross site vulnerability.

Final Solution:

Since the application is dependent of the config, where it calls an API first before rendering things, then I decided not to host it statically by creating my own node server. This means that I will lookup on the static folder “dist”, take the “index.html” and send it to browser. But of course before sending it, I need to call the API and get the necessary data for my OG meta tags first.

If you noticed, I am using a view engine called EJS. This allows me to use a template instead of plainly reading a file and replacing some static wordings and sending back to browser. By using an EJS template, you can put variables in your static files and the view engine will replace it according based on the value set.

How did I put variables in my “dist/index.html”

Normally, we can just do like this right?

./src/index.html

But this one still doesn’t work, because we are using Webpack. During compilation, webpack will treat these as “compile-time variables”, which means, webpack will replace it with the values you set in the HtmlWebpackPlugin while building. And the thing is, we don’t have any! And its not even the correct way of setting webpack compile-time variables.

So here is my solution. I added these in the webpack configuration,

webpack.config.js

and changed the variable names to these:

./src/index.html

Now, when I build my application by running “npm run build” the output will be like this:

./dist/index.html

Finally, we can now use “./dist/index.html” as the template, with the EJS variables set.

How to run?

Since we are not hosting it directly as static data, we will now run it via our node server. You can use containerization tools like Docker.

node server/index.js

I hope you have learned also from my experience. If you have another solution, I am happy to learn it.

--

--