-
Notifications
You must be signed in to change notification settings - Fork 56
/
module.ts
87 lines (76 loc) · 4.92 KB
/
module.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { resolve, normalize } from 'pathe'
import { fileURLToPath } from 'node:url'
import { defineNuxtModule, addServerHandler } from '@nuxt/kit'
import defu from 'defu'
import { AllowedHTTPMethods, MiddlewareConfiguration, ModuleOptions, RateLimiter, RequestSizeLimiter, SecurityHeader, SecurityHeaders, XssValidator } from './types'
import { defaultSecurityConfig } from './defaultConfig'
import { SECURITY_HEADER_NAMES } from './headers'
import { RuntimeConfig } from '@nuxt/schema'
import { CorsOptions } from '@nozomuikuta/h3-cors'
declare module '@nuxt/schema' {
interface NuxtOptions {
security: ModuleOptions
}
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'nuxt-security',
configKey: 'security'
},
defaults: defaultSecurityConfig,
setup (options, nuxt) {
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
nuxt.options.security = defu(nuxt.options.security, {
...options
})
// Register nitro plugin to replace default 'X-Powered-By' header with custom one that does not indicate what is the framework underneath the app.
if (nuxt.options.security.hidePoweredBy) {
nuxt.hook('nitro:config', (config) => {
config.plugins = config.plugins || []
config.plugins.push(normalize(fileURLToPath(new URL('./runtime/nitro', import.meta.url))))
})
}
nuxt.options.runtimeConfig.security = defu(nuxt.options.runtimeConfig.security, {
...nuxt.options.security as RuntimeConfig['security']
})
// Register enabled middlewares to automatically set default values for security response headers.
if (nuxt.options.security.headers) {
for (const header in nuxt.options.security.headers as SecurityHeaders) {
if ((nuxt.options.security.headers as SecurityHeader)[header]) {
// Have to create this manually, otherwise the build will fail. Also, have to create empty object first or use the previous headers if they are for the same route
nuxt.options.nitro.routeRules!![(nuxt.options.security.headers as SecurityHeader)[header].route] = { headers: nuxt.options.nitro.routeRules!![(nuxt.options.security.headers as SecurityHeader)[header].route] ? { ...nuxt.options.nitro.routeRules!![(nuxt.options.security.headers as SecurityHeader)[header].route].headers } : {} }
nuxt.options.nitro.routeRules!![(nuxt.options.security.headers as SecurityHeader)[header].route].headers!![SECURITY_HEADER_NAMES[header]] = (nuxt.options.security.headers as SecurityHeader)[header].value
}
}
}
// Register requestSizeLimiter middleware with default values that will throw an error when the payload will be too big for methods like POST/PUT/DELETE.
const requestSizeLimiterConfig = nuxt.options.security.requestSizeLimiter
if(requestSizeLimiterConfig) {
addServerHandler({ route: (requestSizeLimiterConfig as MiddlewareConfiguration<RequestSizeLimiter>).route, handler: normalize(resolve(runtimeDir, 'server/middleware/requestSizeLimiter')) })
}
// Register rateLimiter middleware with default values that will throw an error when there will be too many requests from the same IP during certain interval.
// Based on 'limiter' package and stored in 'unstorage' for each ip address.
const rateLimiterConfig = nuxt.options.security.rateLimiter
if (rateLimiterConfig) {
addServerHandler({ route: (rateLimiterConfig as MiddlewareConfiguration<RateLimiter>).route, handler: normalize(resolve(runtimeDir, 'server/middleware/rateLimiter')) })
}
// Register xssValidator middleware with default config that will return 400 Bad Request when either query or body will include unwanted characteds like <script>
// Based on 'xss' package and works for both GET and POST requests
const xssValidatorConfig = nuxt.options.security.xssValidator
if (xssValidatorConfig) {
addServerHandler({ route: (xssValidatorConfig as MiddlewareConfiguration<XssValidator>).route, handler: normalize(resolve(runtimeDir, 'server/middleware/xssValidator')) })
}
// Register corsHandler middleware with default config that will add CORS setup
// Based on '@nozomuikuta/h3-cors' package
const corsHandlerConfig = nuxt.options.security.corsHandler
if (corsHandlerConfig) {
addServerHandler({ route: (corsHandlerConfig as MiddlewareConfiguration<CorsOptions>).route, handler: normalize(resolve(runtimeDir, 'server/middleware/corsHandler')) })
}
// Register allowedMethodsRestricter middleware with that will by default allow all methods
const allowedMethodsRestricterConfig = nuxt.options.security.allowedMethodsRestricter as MiddlewareConfiguration<AllowedHTTPMethods>
if (allowedMethodsRestricterConfig && allowedMethodsRestricterConfig.value !== '*') {
addServerHandler({ route: allowedMethodsRestricterConfig.route, handler: normalize(resolve(runtimeDir, 'server/middleware/allowedMethodsRestricter')) })
}
}
})