--- title: Nuxt Security Hooks description: Use hooks to further customize Nuxt Security --- ## Available hooks Nuxt Security provides two custom hooks: 1. **The routeRules hook** (Nitro runtime hook): to modify the settings of Nuxt-Security at runtime. 2. **The prerenderedHeaders hook** (Nuxt buildtime hook): to create a headers configuration file for your static server. ## Route Rules Hook The `nuxt-security:routeRules` hook is convenient when you don't know the applicable security options at build time. This happens most frequently in the following cases: - Your Nuxt application is designed to be deployed on multiple websites, with a different configuration for each website. - Your security options are kept in a third-party vault system (e.g. Google Secret Manager), and your build system does not have access to the secrets. ::callout{icon="i-heroicons-light-bulb"} Your `nuxt-security:routeRules` hook will be invoked each time your server is restarted. :: ### How to use In order to use this hook, you will need to write a Nitro plugin ```ts{}[/server/plugins/my-plugin.ts] export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('nuxt-security:routeRules', (appSecurityOptions) => { // Your code here }) }) ``` - The `appSecurityOptions` variable contains all your application security options in the form of router definitions. These router definitions are provided in the form of h3's radix router rules. Please see [radix3](https://github.com/unjs/radix3) for further details. - The anonymous function `(appSecurityOptions) => {}` will be called asynchronously If you need to fetch your security data from an external secrets' manager API, you can use `async/await` in your code. - Your code can modify any security option inside this hook For each route, you can modify the rules exactly as you would do it with the `routeRules` option of `nuxt.config.ts`. ### Examples You can apply custom settings to your whole application by modifying the base `/**` route : ```ts export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('nuxt-security:routeRules', async(appSecurityOptions) => { const cspConnectSrc = await $fetch('https://secret-manager-api.com/api-route') // This example replaces only the connect-src CSP directive appSecurityOptions['/**'] = defuReplaceArray( { headers: { contentSecurityPolicy: { "connect-src": [cspConnectSrc] } } }, appSecurityOptions['/**'] ) }) }) ``` You can also apply your settings to selected sub-routes of your application : ```ts export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('nuxt-security:routeRules', async(appSecurityOptions) => { const cspConnectSrc = await $fetch('https://secret-manager-api.com/api-route') // This example modifies the CSP only for `/admin/**` routes appSecurityOptions['/admin/**'] = defuReplaceArray( { headers: { contentSecurityPolicy: { "connect-src": [cspConnectSrc] } } }, appSecurityOptions['/admin/**'] ) }) }) ``` You are not constrained to CSP options, you can modify any security option with this hook : ```ts export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('nuxt-security:routeRules', async(appSecurityOptions) => { const tokenLimit = await $fetch('https://secret-manager-api.com/api-route') // This example modifies the Rate Limiter only for API routes // It also modifies the X-Powered-By setting for these routes appSecurityOptions['/api/**'] = defuReplaceArray( { rateLimiter: { tokensPerInterval: tokenLimit }, hidePoweredBy: false }, appSecurityOptions['/api/**'] ) }) }) ``` ## Prerendered Headers Hook The `nuxt-security:prerenderedHeaders` hook is convenient when you want to know the security headers that should be delivered by your static server. This happens most frequently when you deploy your website statically on a CDN. In that case, your server has the HTML pages, but it doesn't know which security headers should be delivered. You may want to configure your hosting provider so that the correct headers are delivered for each static page. ::callout{icon="i-heroicons-light-bulb"} Your `nuxt-security:prerenderedHeaders` hook will be invoked each time your build your application. :: ### How to use In order to use this hook, you will need write your code in `defineNuxtConfig` ```ts{}[nuxt.config.ts] export default defineNuxtConfig({ hooks: { 'nuxt-security:prerenderedHeaders': (prerenderedHeaders) => { // Your code here } } }) ``` - The `prerenderedHeaders` variable contains all calculated headers for each page. ```js { '/page1': { header1: value1, header2: value2 }, '/page2': { header3: value3, ... } } ``` - The anonymous function `(prerenderedHeaders) => {}` will be called asynchronously If you need to write to files asynchronously in your code, you can use `async/await` in your code. ### Examples You can generate nginx-compatible header rules within your CI/CD pipeline and save them to a file on disk : ```ts{}[nuxt.config.ts] import { writeFile } from 'node:fs/promises' defineNuxtConfig({ hooks: { 'nuxt-security:prerenderedHeaders': async(prerenderedHeaders) => { // Don't take this snippet for granted, this is just provided as a basic example let nginxText = '' for (const path in prerenderedHeaders) { nginxText += 'location ' + path + ' {\n' const headersForPath = prerenderedHeaders[path] for (const headerName in headersForPath) { const headerValue = headersForPath[headerName] nginxText += ` add_header ${headerName} "${headerValue}";\n` } nginxText += '}\n\n' } await writeFile('./.nuxt/server.headers', nginxText) } } }) ```