Good Practices

Learn how you can make your app even more secure.


Only return what is necessary

If you just need a certain field of an object, you should only return the specific fields required. In other words, if you only need to list names of the users available, you are not returning their email addresses or credit card numbers in addition to their full names.

You can read more about this recommendation here

Fortunately, in Nuxt 3, you can utilize pick or use interceptors concepts for both useAsyncData and useFetch to sanitize what you get from the server without leaking confidential data.

ℹ Read more about it here.
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
    pick: ['title']
})

Handling State with Care in Nuxt SSR

When developing applications with Nuxt.js in SSR mode, it's crucial to handle reactive state with care to avoid Cross-Request State Pollution. This issue arises when state is shared unintentionally between requests, leading to potential data leaks and inconsistent application behavior. Nuxt's documentation here provides best practices for state management in such scenarios.

Consider the issue with global ref in a composable.

const unsafeGlobal = ref<number>(1);

export function useSafeRef() {
    const safeRef = ref<number>(2);

    return {
        unsafeGlobal,
        safeRef
    }
}

For enhanced safety and to adhere to Nuxt's best practices, it's recommended to manage state using abstractions with useState. This utility function is specifically designed for Nuxt applications to ensure state is isolated per request, effectively preventing cross-request state pollution:

const safeGlobal = useState<number>('safeGlobal', () => 5);

export function useSafeRef() {
    const safeRef = useState<number>('safeRef', () => 2);

    return {
        safeGlobal,
        safeRef
    }
}

Note: useState is global across components. Use a unique key if you want to keep them separate.

ℹ Read more about Cross-Request State Pollution here

Use access control lists

Authorization prevents users from acting outside of their intended permissions. In order to do so, users and their roles should be determined with consideration of the principle of least privilege. Each user role should only have access to the resources they must use.

You can use the acl module to provide ACL (access control list) implementation. With this module, you can create roles and assign users to these roles.

ℹ Read more about it here.

Install the module:

npm install acl # or yarn

Add use it in your code:

var acl = require('acl');

acl = new acl(new acl.memoryBackend())

// guest is allowed to view blogs
acl.allow('guest', 'blogs', 'view')

Perform Application Activity Logging

Logging application activity is an encouraged good practice. It makes it easier to debug any errors encountered during application runtime. It is also useful for security concerns, since it can be used during incident response. In addition, these logs can be used to feed Intrusion Detection/Prevention Systems (IDS/IPS).

ℹ Read more about it here.

Install the module:

npm i winston # or yarn

Add then use it in your application like this:

const logger = new (Winston.Logger) ({
  transports: [
      new (winston.transports.Console)(),
      new (winston.transports.File)({ filename: 'application.log' })
  ],
  level: 'verbose'
});

Use eslint security plugins

eslint-plugin-security-node

ESLint plugin containing Node.js security rules. This plugin will help to identify potential threats and prevent attacks.

ℹ Read more about it here.

Install the module:

npm install --save-dev eslint-plugin-security-node # or yarn

Add the following configuration to .eslintrc:

"plugins": [
    "security-node"
],
"extends": [
    "plugin:security-node/recommended"
]

eslint-plugin-anti-trojan-source

ESLint plugin to detect and stop Trojan Source attacks from entering your codebase.

ℹ Read more about it here.

Install the module:

npm install --save-dev eslint-plugin-anti-trojan-source # or yarn

Add the following configuration to .eslintrc:

"plugins": [
    "anti-trojan-source"
],
"extends": [
    "plugin:anti-trojan-source/recommended"
]

Use Snyk

Snyk allows you to find and automatically fix vulnerabilities in your code, open source dependencies, containers, and infrastructure as code — all powered by Snyk’s industry-leading security intelligence.

ℹ Read more about it here.

Snyk Homepage

For development, especially useful are two Snyk products; Snyk Code and Snyk Open Source. The first is responsible for securing the code you write, while the second helps avoid vulnerable dependencies. Apart from that, Snyk CLI finds hardcoded secrets so that you won't push them to your repository.

Lint Lockfile

Lockfiles are used as trusted whitelist of resources manifest to fetch packages from. However, keeping track of the changes introduced to lockfiles is not an easy task as they are designed to be consumed by machines 🤖.

ℹ Read more about it here.

Usage:

npx lockfile-lint --path yarn.lock --allowed-hosts npm yarn --validate-https

Lockfile Linter use

Check Awesome Node Security

There are many ways that you can make you app more secure and apart from OWASP and Helmet, there are sources like Awesome Node.js Security by Liran Tal.

Check it out to learn about other tools that you can use.

Use Security Checklists

There are few useful checklists that tackle the topic of security in web applications that you can check out to develop more secure applications: