There is no one best way to secure a web application. However, for any given framework there are common mistakes that can easily lead to security weaknesses. Nuxt is the same in this regard, and this guide aims to patch all of these common weakpoints to improve your security standpoint and reduce the risk of an incident.
I've ordered the sections from most important to least important.
Using the appropriate deployment mode significantly reduces the risk of a security incident. Development mode has had a history of serious vulnerabilities and still contains several serious issues, which are easiest to exploit if you expose them to the internet.
As well as this, production mode is optimized for performance using minification and other optimizations. You will see a significant performance boost using the production application.
Switching to a different environment such as Cloudflare Workers or Vercel Edge Functions can improve your security standpoint as they block potentially dangerous APIs on the server side. Functions like
new Function() are avoided in the Nuxt core, but poorly written modules or plugins may use this type of code.
These environments also lack filesystem APIs, which could be frustrating in certain cases, but makes persistence and further exploitation incredibly challenging.
While security issues can still arise in these envirionments, blocking these unsafe functions prevents the majority of injection attacks, allowing you to focus on other issues.
The easiest possible way to improve the security of your application is to update to the latest version. This will typically include the latest security patches.
Sometimes the Nuxt team do not publish which releases contain security fixes, so it's best to update whenever possible. You can read more about Nuxt Vulnerabilities here.
Storing your API keys or other secrets in Nuxt requires some care and consideration.
runtimeConfig feature is the officially supported way of storing sensitive data. You should ideally store your secrets in Environment variables in production, using the
NUXT_ prefix to map them into your
Storing secrets in development mode is challenging to do correctly. You should ideally avoid placing any important secrets here as it's historically much easier to attack.
Placing secrets haphazardly in
nuxt.config.ts, or not correctly following the documentation, will lead to easily leaked secrets.
Hardcoded Secrets can be leaked from Nuxt config.
You may think you're safe because Nuxt is only exposed on localhost. Unfortunately Vite allows requests from all origins by default. This means by visiting a malicious website an attacker could read your Nuxt configuration and steal your secrets!
Vite responding to a cross origin request.
Reconfiguring Vite isn't a solution either, as you can perform a similar attack using Nuxt Devtool's
getServerRuntimeConfig RPC method. This works over Websocket, which is not bound by the Same-Origin policy.
Using environment variables is a partial solution, but you must do it correctly.
This can't be exploited here.
Secret can be leaked in the bundled server.
.env file is a more robust method, but I would only recommend this in Nuxt 3.7.0+, due to several historical vulnerabilities.
Any secrets placed in
.ts files exposed to the client can be leaked, even if the user does not have access to that page, I'm planning on writing about this in my Nuxt Reconsisance guide which will be published soon.
Nuxt modules are a great way of reusing code to save time and development effort. However, they may not be written to the same high standard that the rest of the Nuxt Ecosystem is written in. This makes them an important part of your security.
While you don't need to code-review the entire module, it could be good to check a few basics, like which server routes are exposed in production.
Nuxt Content is a Nuxt Module that allows developers to write content in a variety of different formats including Markdown. While is this a very well written module, with fantastic tooling like Nuxt Studio, there are a number of potential weaknesses you can introduce inadvertently.
I've written a guide on exploiting Nuxt content, which you can read to understand more.