nuxt-security-module 4.3.3 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -8
- package/package.json +9 -20
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -104
- package/dist/models/AllowedMethodsRestricterOptions.d.ts +0 -3
- package/dist/models/BasicAuthOptions.d.ts +0 -7
- package/dist/models/ContentSecurityPolicy.d.ts +0 -1
- package/dist/models/CorsHandlerOptions.d.ts +0 -11
- package/dist/models/CrossOriginEmbedderPolicy.d.ts +0 -6
- package/dist/models/CrossOriginEmbedderPolicy.js +0 -7
- package/dist/models/CsrfOptions.d.ts +0 -4
- package/dist/models/ModuleOptions.d.ts +0 -25
- package/dist/models/PermissionsPolicy.d.ts +0 -1
- package/dist/models/RateLimitWindow.d.ts +0 -4
- package/dist/models/RateLimiterOptions.d.ts +0 -4
- package/dist/models/RateLimiterStore.d.ts +0 -4
- package/dist/models/RequestSizeLimiterOptions.d.ts +0 -4
- package/dist/models/SecurityHeaders.d.ts +0 -20
- package/dist/models/SecurityRouteRules.d.ts +0 -2
- package/dist/models/SecurityRules.d.ts +0 -2
- package/dist/models/SsgOptions.d.ts +0 -7
- package/dist/models/StrictTransportSecurity.d.ts +0 -5
- package/dist/models/XFrameOptions.d.ts +0 -5
- package/dist/models/XFrameOptions.js +0 -6
- package/dist/runtime/constants.d.ts +0 -22
- package/dist/runtime/constants.js +0 -51
- package/dist/runtime/nitro/plugins/hidePoweredBy.d.ts +0 -3
- package/dist/runtime/nitro/plugins/hidePoweredBy.js +0 -12
- package/dist/runtime/nitro/plugins/nonce.d.ts +0 -3
- package/dist/runtime/nitro/plugins/nonce.js +0 -26
- package/dist/runtime/nitro/plugins/routeRules.d.ts +0 -3
- package/dist/runtime/nitro/plugins/routeRules.js +0 -16
- package/dist/runtime/nitro/plugins/securityHeaders.d.ts +0 -3
- package/dist/runtime/nitro/plugins/securityHeaders.js +0 -24
- package/dist/runtime/nitro/plugins/ssgHashes.d.ts +0 -3
- package/dist/runtime/nitro/plugins/ssgHashes.js +0 -26
- package/dist/runtime/nitro/plugins/subresourceIntegrity.d.ts +0 -2
- package/dist/runtime/nitro/plugins/subresourceIntegrity.js +0 -18
- package/dist/runtime/server/middleware/allowedMethodsRestricter.d.ts +0 -3
- package/dist/runtime/server/middleware/allowedMethodsRestricter.js +0 -14
- package/dist/runtime/server/middleware/basicAuth.d.ts +0 -3
- package/dist/runtime/server/middleware/basicAuth.js +0 -22
- package/dist/runtime/server/middleware/corsHandler.d.ts +0 -3
- package/dist/runtime/server/middleware/corsHandler.js +0 -19
- package/dist/runtime/server/middleware/csrf.d.ts +0 -3
- package/dist/runtime/server/middleware/csrf.js +0 -27
- package/dist/runtime/server/middleware/rateLimiter.d.ts +0 -3
- package/dist/runtime/server/middleware/rateLimiter.js +0 -21
- package/dist/runtime/server/middleware/requestSizeLimiter.d.ts +0 -3
- package/dist/runtime/server/middleware/requestSizeLimiter.js +0 -16
- package/dist/runtime/services/checkIsBasicAuthorized.d.ts +0 -2
- package/dist/runtime/services/checkIsBasicAuthorized.js +0 -11
- package/dist/runtime/services/checkIsChallenged.d.ts +0 -2
- package/dist/runtime/services/checkIsChallenged.js +0 -7
- package/dist/runtime/services/checkIsCsrfTokenValid.d.ts +0 -1
- package/dist/runtime/services/checkIsCsrfTokenValid.js +0 -7
- package/dist/runtime/services/checkIsEqualInConstantTime.d.ts +0 -1
- package/dist/runtime/services/checkIsEqualInConstantTime.js +0 -10
- package/dist/runtime/services/checkIsMethodAllowed.d.ts +0 -1
- package/dist/runtime/services/checkIsMethodAllowed.js +0 -3
- package/dist/runtime/services/checkIsRecord.d.ts +0 -1
- package/dist/runtime/services/checkIsRecord.js +0 -3
- package/dist/runtime/services/checkIsRequestTooLarge.d.ts +0 -2
- package/dist/runtime/services/checkIsRequestTooLarge.js +0 -8
- package/dist/runtime/services/collectSsgHashes.d.ts +0 -3
- package/dist/runtime/services/collectSsgHashes.js +0 -40
- package/dist/runtime/services/createInMemoryRateLimiterStore.d.ts +0 -2
- package/dist/runtime/services/createInMemoryRateLimiterStore.js +0 -21
- package/dist/runtime/services/generateHash.d.ts +0 -1
- package/dist/runtime/services/generateHash.js +0 -8
- package/dist/runtime/services/generateNonce.d.ts +0 -1
- package/dist/runtime/services/generateNonce.js +0 -5
- package/dist/runtime/services/generateRandomToken.d.ts +0 -1
- package/dist/runtime/services/generateRandomToken.js +0 -7
- package/dist/runtime/services/getBasicAuthCredentials.d.ts +0 -4
- package/dist/runtime/services/getBasicAuthCredentials.js +0 -18
- package/dist/runtime/services/getBasicAuthOptions.d.ts +0 -2
- package/dist/runtime/services/getBasicAuthOptions.js +0 -16
- package/dist/runtime/services/getRetryAfterSeconds.d.ts +0 -3
- package/dist/runtime/services/getRetryAfterSeconds.js +0 -8
- package/dist/runtime/services/getSecurityRules.d.ts +0 -3
- package/dist/runtime/services/getSecurityRules.js +0 -14
- package/dist/runtime/services/getSecurityState.d.ts +0 -9
- package/dist/runtime/services/getSecurityState.js +0 -13
- package/dist/runtime/services/injectNonce.d.ts +0 -1
- package/dist/runtime/services/injectNonce.js +0 -6
- package/dist/runtime/services/injectSubresourceIntegrity.d.ts +0 -1
- package/dist/runtime/services/injectSubresourceIntegrity.js +0 -21
- package/dist/runtime/services/insertContentSecurityPolicyMeta.d.ts +0 -2
- package/dist/runtime/services/insertContentSecurityPolicyMeta.js +0 -16
- package/dist/runtime/services/mergeSecurityRules.d.ts +0 -2
- package/dist/runtime/services/mergeSecurityRules.js +0 -10
- package/dist/runtime/services/readHtmlTagAttribute.d.ts +0 -1
- package/dist/runtime/services/readHtmlTagAttribute.js +0 -7
- package/dist/runtime/services/rewriteHtmlTags.d.ts +0 -1
- package/dist/runtime/services/rewriteHtmlTags.js +0 -8
- package/dist/runtime/services/securityRouteMatcher.d.ts +0 -3
- package/dist/runtime/services/securityRouteMatcher.js +0 -10
- package/dist/runtime/services/serializeBasicAuthChallenge.d.ts +0 -1
- package/dist/runtime/services/serializeBasicAuthChallenge.js +0 -3
- package/dist/runtime/services/serializeContentSecurityPolicy.d.ts +0 -2
- package/dist/runtime/services/serializeContentSecurityPolicy.js +0 -6
- package/dist/runtime/services/serializePermissionsPolicy.d.ts +0 -2
- package/dist/runtime/services/serializePermissionsPolicy.js +0 -3
- package/dist/runtime/services/serializeSecurityHeaders.d.ts +0 -2
- package/dist/runtime/services/serializeSecurityHeaders.js +0 -18
- package/dist/runtime/services/serializeStrictTransportSecurity.d.ts +0 -2
- package/dist/runtime/services/serializeStrictTransportSecurity.js +0 -7
- package/dist/runtime/services/stripHtmlTagAttribute.d.ts +0 -1
- package/dist/runtime/services/stripHtmlTagAttribute.js +0 -4
- package/dist/runtime/services/updateContentSecurityPolicy.d.ts +0 -3
- package/dist/runtime/services/updateContentSecurityPolicy.js +0 -14
- package/dist/schemas/allowedMethodsRestricterOptionsSchema.js +0 -4
- package/dist/schemas/basicAuthOptionsSchema.js +0 -11
- package/dist/schemas/contentSecurityPolicySchema.js +0 -4
- package/dist/schemas/corsHandlerOptionsSchema.js +0 -13
- package/dist/schemas/csrfOptionsSchema.js +0 -8
- package/dist/schemas/moduleOptionsSchema.js +0 -28
- package/dist/schemas/permissionsPolicySchema.js +0 -4
- package/dist/schemas/rateLimiterOptionsSchema.js +0 -7
- package/dist/schemas/requestSizeLimiterOptionsSchema.js +0 -7
- package/dist/schemas/securityHeadersSchema.js +0 -24
- package/dist/schemas/ssgOptionsSchema.js +0 -10
- package/dist/schemas/strictTransportSecurityOptionsSchema.js +0 -8
- package/dist/services/computeSubresourceIntegrityHashes.js +0 -28
- package/dist/services/formatZodIssues.js +0 -15
- package/dist/services/getDefaultModuleOptions.js +0 -40
- package/dist/services/getDefaultSecurityHeaders.js +0 -84
- package/dist/services/getPluginTemplate.js +0 -9
- package/dist/services/getRemoveLoggersViteConfig.js +0 -3
- package/dist/services/getRouteRulesTemplate.js +0 -3
- package/dist/services/getRouteSecurityRules.js +0 -16
- package/dist/services/getStaticResourceHeaders.js +0 -11
- package/dist/services/getTypeTemplate.js +0 -24
- package/dist/services/mergeModuleOptions.js +0 -38
- package/dist/services/parseModuleOptions.js +0 -9
package/README.md
CHANGED
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
[![NPM downloads][badge-npm-downloads]][url-npm]
|
|
6
6
|
[![NPM Unpacked Size (with version)][badge-npm-unpacked-size]][url-npm]
|
|
7
7
|
|
|
8
|
-
Nuxt security module for [Nitro 3](https://nitro.build) and h3 2
|
|
8
|
+
A Nuxt security module for [Nitro 3](https://nitro.build) and h3 2 that sets security headers on rendered pages, a per-request nonce Content Security Policy, subresource integrity, CORS, allowed methods, basic auth and a request size limit.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Design notes live in [the specs](https://github.com/Esposter/Esposter/tree/main/openspec/specs/nuxt-security-module).
|
|
11
11
|
|
|
12
12
|
## Table of Contents
|
|
13
13
|
|
|
14
14
|
- 🚀 [Getting Started](#getting-started)
|
|
15
|
-
-
|
|
15
|
+
- 🧩 [Key Exports](#key-exports)
|
|
16
|
+
- 📝 [Usage](#usage)
|
|
16
17
|
- ⚖️ [License](#license)
|
|
17
18
|
|
|
18
19
|
---
|
|
@@ -28,17 +29,31 @@ pnpm i nuxt-security-module
|
|
|
28
29
|
export default defineNuxtConfig({ modules: ["nuxt-security-module"] });
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
## <a name="
|
|
32
|
+
## <a name="key-exports">🧩 Key Exports</a>
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
| Export | Kind | Purpose |
|
|
35
|
+
| :----------------------- | :-------- | :----------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| `createRouteRulesPlugin` | function | Exported from `./runtime/nitro/plugins/routeRules`: the plugin that matches each request against the build's route rules |
|
|
37
|
+
| `default` | const | The Nuxt module, set up from the `security` config key; each feature registers only when its option is on |
|
|
38
|
+
| `ModuleOptions` | interface | The module's options, one key per feature, each on or off; the `security` config key takes a partial of them |
|
|
39
|
+
| `rateLimiter` | const | Default export of `./runtime/server/middleware/rateLimiter`: refuses a request with `429` once its key's window is spent |
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
## <a name="usage">📝 Usage</a>
|
|
36
42
|
|
|
37
|
-
|
|
43
|
+
```ts
|
|
44
|
+
// nuxt.config.ts
|
|
45
|
+
export default defineNuxtConfig({
|
|
46
|
+
modules: ["nuxt-security-module"],
|
|
47
|
+
security: {
|
|
48
|
+
// Refuses a client with 429 after 100 requests in each minute-long window
|
|
49
|
+
rateLimiter: { intervalInMilliseconds: 60000, tokensPerInterval: 100 },
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
```
|
|
38
53
|
|
|
39
54
|
## <a name="license">⚖️ License</a>
|
|
40
55
|
|
|
41
|
-
Apache-2.0
|
|
56
|
+
Licensed under [Apache-2.0][url-license].
|
|
42
57
|
|
|
43
58
|
[badge-license]: https://img.shields.io/github/license/Esposter/Esposter.svg?color=blue
|
|
44
59
|
[url-license]: https://github.com/Esposter/Esposter/blob/main/LICENSE
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-security-module",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Nuxt security module for Nitro 3 and h3 2 — security headers, a per-request nonce Content Security Policy, subresource integrity, CORS, allowed methods, basic auth and a request size limit.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Jimmy Chen",
|
|
@@ -19,19 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./dist/index.js",
|
|
22
|
-
"./runtime/constants": "./dist/runtime/constants.js",
|
|
23
|
-
"./runtime/nitro/plugins/hidePoweredBy": "./dist/runtime/nitro/plugins/hidePoweredBy.js",
|
|
24
|
-
"./runtime/nitro/plugins/nonce": "./dist/runtime/nitro/plugins/nonce.js",
|
|
25
22
|
"./runtime/nitro/plugins/routeRules": "./dist/runtime/nitro/plugins/routeRules.js",
|
|
26
|
-
"./runtime/nitro/plugins/securityHeaders": "./dist/runtime/nitro/plugins/securityHeaders.js",
|
|
27
|
-
"./runtime/nitro/plugins/ssgHashes": "./dist/runtime/nitro/plugins/ssgHashes.js",
|
|
28
|
-
"./runtime/nitro/plugins/subresourceIntegrity": "./dist/runtime/nitro/plugins/subresourceIntegrity.js",
|
|
29
|
-
"./runtime/server/middleware/allowedMethodsRestricter": "./dist/runtime/server/middleware/allowedMethodsRestricter.js",
|
|
30
|
-
"./runtime/server/middleware/basicAuth": "./dist/runtime/server/middleware/basicAuth.js",
|
|
31
|
-
"./runtime/server/middleware/corsHandler": "./dist/runtime/server/middleware/corsHandler.js",
|
|
32
|
-
"./runtime/server/middleware/csrf": "./dist/runtime/server/middleware/csrf.js",
|
|
33
23
|
"./runtime/server/middleware/rateLimiter": "./dist/runtime/server/middleware/rateLimiter.js",
|
|
34
|
-
"./runtime/server/middleware/requestSizeLimiter": "./dist/runtime/server/middleware/requestSizeLimiter.js",
|
|
35
24
|
"./package.json": "./package.json"
|
|
36
25
|
},
|
|
37
26
|
"scripts": {
|
|
@@ -40,7 +29,7 @@
|
|
|
40
29
|
"lint": "eslint .",
|
|
41
30
|
"lint:fix": "eslint --fix .",
|
|
42
31
|
"test": "vitest",
|
|
43
|
-
"typecheck": "
|
|
32
|
+
"typecheck": "tsrs --fast"
|
|
44
33
|
},
|
|
45
34
|
"dependencies": {
|
|
46
35
|
"@nuxt/kit": "npm:@nuxt/kit-nightly@5x",
|
|
@@ -50,16 +39,16 @@
|
|
|
50
39
|
"zod": "^4.6.7"
|
|
51
40
|
},
|
|
52
41
|
"devDependencies": {
|
|
53
|
-
"@esposter/configuration": "4.
|
|
54
|
-
"@esposter/shared-node": "4.
|
|
42
|
+
"@esposter/configuration": "4.4.0",
|
|
43
|
+
"@esposter/shared-node": "4.4.0",
|
|
55
44
|
"@nuxt/nitro-server": "npm:@nuxt/nitro-server-nightly@5x",
|
|
56
|
-
"@types/node": "^26.6.
|
|
57
|
-
"h3": "^2.0.
|
|
58
|
-
"tsdown": "
|
|
45
|
+
"@types/node": "^26.6.6",
|
|
46
|
+
"h3": "^2.0.8",
|
|
47
|
+
"tsdown": "0.23.2"
|
|
59
48
|
},
|
|
60
49
|
"peerDependencies": {
|
|
61
|
-
"nitro": "npm:nitro-nightly@
|
|
50
|
+
"nitro": "npm:nitro-nightly@latest",
|
|
62
51
|
"nuxt": "npm:nuxt-nightly@5x"
|
|
63
52
|
},
|
|
64
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "e1a416c4b91da69cc2aa259b50a4d656f204d272"
|
|
65
54
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ModuleOptions } from "./models/ModuleOptions.js";
|
|
2
|
-
import { SecurityRouteRules } from "./models/SecurityRouteRules.js";
|
|
3
|
-
import { NuxtModule } from "@nuxt/schema";
|
|
4
|
-
declare module "@nuxt/schema" {
|
|
5
|
-
interface NuxtConfig {
|
|
6
|
-
security?: Partial<ModuleOptions>;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
declare module "h3/rules" {
|
|
10
|
-
interface RouteRuleConfig {
|
|
11
|
-
security?: SecurityRouteRules;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
declare const securityModule: NuxtModule<Partial<ModuleOptions>>;
|
|
15
|
-
export { type ModuleOptions, securityModule as default };
|
package/dist/index.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { MODULE_NAME } from "./runtime/constants.js";
|
|
2
|
-
import { checkIsRecord } from "./runtime/services/checkIsRecord.js";
|
|
3
|
-
import { computeSubresourceIntegrityHashes } from "./services/computeSubresourceIntegrityHashes.js";
|
|
4
|
-
import { getDefaultModuleOptions } from "./services/getDefaultModuleOptions.js";
|
|
5
|
-
import { getPluginTemplate } from "./services/getPluginTemplate.js";
|
|
6
|
-
import { getRemoveLoggersViteConfig } from "./services/getRemoveLoggersViteConfig.js";
|
|
7
|
-
import { getRouteRulesTemplate } from "./services/getRouteRulesTemplate.js";
|
|
8
|
-
import { mergeModuleOptions } from "./services/mergeModuleOptions.js";
|
|
9
|
-
import { getRouteSecurityRules } from "./services/getRouteSecurityRules.js";
|
|
10
|
-
import { getStaticResourceHeaders } from "./services/getStaticResourceHeaders.js";
|
|
11
|
-
import { getTypeTemplate } from "./services/getTypeTemplate.js";
|
|
12
|
-
import { parseModuleOptions } from "./services/parseModuleOptions.js";
|
|
13
|
-
import { defu } from "defu";
|
|
14
|
-
import { addNitroPlugin, addServerHandler, addServerTemplate, addTypeTemplate, createResolver, defineNuxtModule } from "@nuxt/kit";
|
|
15
|
-
// src/module.ts
|
|
16
|
-
const ROUTE_RULES_TEMPLATE_FILENAME = `#${MODULE_NAME}/route-rules.mjs`;
|
|
17
|
-
const SRI_HASHES_TEMPLATE_FILENAME = `#${MODULE_NAME}/sri-hashes.mjs`;
|
|
18
|
-
const ROUTE_RULES_PLUGIN_FILENAME = `#${MODULE_NAME}/route-rules-plugin.mjs`;
|
|
19
|
-
const SRI_PLUGIN_FILENAME = `#${MODULE_NAME}/sri-plugin.mjs`;
|
|
20
|
-
const securityModule = defineNuxtModule({
|
|
21
|
-
meta: {
|
|
22
|
-
compatibility: { nuxt: ">=5.0.0-0" },
|
|
23
|
-
configKey: "security",
|
|
24
|
-
name: MODULE_NAME
|
|
25
|
-
},
|
|
26
|
-
setup(userOptions, nuxt) {
|
|
27
|
-
const options = parseModuleOptions(mergeModuleOptions(getDefaultModuleOptions(nuxt.options.dev, nuxt.options.devServer.url, userOptions.strict === true), userOptions));
|
|
28
|
-
if (!options.enabled) return;
|
|
29
|
-
const resolver = createResolver(import.meta.url);
|
|
30
|
-
const { basicAuth, ...publicOptions } = options;
|
|
31
|
-
if (basicAuth) {
|
|
32
|
-
const { private: privateRuntimeConfig } = nuxt.options.runtimeConfig;
|
|
33
|
-
nuxt.options.runtimeConfig.private = defu(checkIsRecord(privateRuntimeConfig) ? privateRuntimeConfig : {}, { basicAuth });
|
|
34
|
-
}
|
|
35
|
-
const routeSecurityRules = getRouteSecurityRules(nuxt.options.routeRules ?? {}, options);
|
|
36
|
-
addServerTemplate({
|
|
37
|
-
filename: ROUTE_RULES_TEMPLATE_FILENAME,
|
|
38
|
-
getContents: () => getRouteRulesTemplate({
|
|
39
|
-
"/**": publicOptions,
|
|
40
|
-
...routeSecurityRules
|
|
41
|
-
})
|
|
42
|
-
});
|
|
43
|
-
addServerTemplate({
|
|
44
|
-
filename: ROUTE_RULES_PLUGIN_FILENAME,
|
|
45
|
-
getContents: () => getPluginTemplate(resolver.resolve("./runtime/nitro/plugins/routeRules"), "createRouteRulesPlugin", ROUTE_RULES_TEMPLATE_FILENAME)
|
|
46
|
-
});
|
|
47
|
-
addNitroPlugin(ROUTE_RULES_PLUGIN_FILENAME);
|
|
48
|
-
if (options.removeLoggers) nuxt.options.vite = defu(getRemoveLoggersViteConfig(), nuxt.options.vite);
|
|
49
|
-
if (options.headers) nuxt.options.routeRules = defu({ "/**": { headers: getStaticResourceHeaders(options.headers) } }, nuxt.options.routeRules);
|
|
50
|
-
if (options.nonce) addNitroPlugin(resolver.resolve("./runtime/nitro/plugins/nonce"));
|
|
51
|
-
if (options.sri) {
|
|
52
|
-
addServerTemplate({
|
|
53
|
-
filename: SRI_PLUGIN_FILENAME,
|
|
54
|
-
getContents: () => getPluginTemplate(resolver.resolve("./runtime/nitro/plugins/subresourceIntegrity"), "createSubresourceIntegrityPlugin", SRI_HASHES_TEMPLATE_FILENAME)
|
|
55
|
-
});
|
|
56
|
-
addNitroPlugin(SRI_PLUGIN_FILENAME);
|
|
57
|
-
}
|
|
58
|
-
if (options.ssg) addNitroPlugin(resolver.resolve("./runtime/nitro/plugins/ssgHashes"));
|
|
59
|
-
if (options.headers) addNitroPlugin(resolver.resolve("./runtime/nitro/plugins/securityHeaders"));
|
|
60
|
-
if (options.hidePoweredBy) addNitroPlugin(resolver.resolve("./runtime/nitro/plugins/hidePoweredBy"));
|
|
61
|
-
if (options.csrf) addServerHandler({
|
|
62
|
-
handler: resolver.resolve("./runtime/server/middleware/csrf"),
|
|
63
|
-
middleware: true
|
|
64
|
-
});
|
|
65
|
-
if (options.rateLimiter) addServerHandler({
|
|
66
|
-
handler: resolver.resolve("./runtime/server/middleware/rateLimiter"),
|
|
67
|
-
middleware: true
|
|
68
|
-
});
|
|
69
|
-
if (options.requestSizeLimiter) addServerHandler({
|
|
70
|
-
handler: resolver.resolve("./runtime/server/middleware/requestSizeLimiter"),
|
|
71
|
-
middleware: true
|
|
72
|
-
});
|
|
73
|
-
if (options.corsHandler) addServerHandler({
|
|
74
|
-
handler: resolver.resolve("./runtime/server/middleware/corsHandler"),
|
|
75
|
-
middleware: true
|
|
76
|
-
});
|
|
77
|
-
if (options.allowedMethodsRestricter) addServerHandler({
|
|
78
|
-
handler: resolver.resolve("./runtime/server/middleware/allowedMethodsRestricter"),
|
|
79
|
-
middleware: true
|
|
80
|
-
});
|
|
81
|
-
if (basicAuth) addServerHandler({
|
|
82
|
-
handler: resolver.resolve("./runtime/server/middleware/basicAuth"),
|
|
83
|
-
middleware: true
|
|
84
|
-
});
|
|
85
|
-
let sriHashes = {};
|
|
86
|
-
if (options.sri) {
|
|
87
|
-
addServerTemplate({
|
|
88
|
-
filename: SRI_HASHES_TEMPLATE_FILENAME,
|
|
89
|
-
getContents: () => `export default ${JSON.stringify(sriHashes)}\n`
|
|
90
|
-
});
|
|
91
|
-
nuxt.hook("nitro:build:before", async (nitro) => {
|
|
92
|
-
sriHashes = await computeSubresourceIntegrityHashes(nitro);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
addTypeTemplate({
|
|
96
|
-
filename: `types/${MODULE_NAME}.d.ts`,
|
|
97
|
-
getContents: getTypeTemplate
|
|
98
|
-
}, {
|
|
99
|
-
nitro: true,
|
|
100
|
-
nuxt: true
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
export { securityModule as default };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type ContentSecurityPolicy = Record<string, boolean | string[] | undefined>;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const CrossOriginEmbedderPolicy: {
|
|
2
|
-
readonly Credentialless: "credentialless";
|
|
3
|
-
readonly RequireCorp: "require-corp";
|
|
4
|
-
readonly UnsafeNone: "unsafe-none";
|
|
5
|
-
};
|
|
6
|
-
export type CrossOriginEmbedderPolicy = (typeof CrossOriginEmbedderPolicy)[keyof typeof CrossOriginEmbedderPolicy];
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { AllowedMethodsRestricterOptions } from "./AllowedMethodsRestricterOptions.js";
|
|
2
|
-
import { BasicAuthOptions } from "./BasicAuthOptions.js";
|
|
3
|
-
import { CorsHandlerOptions } from "./CorsHandlerOptions.js";
|
|
4
|
-
import { CsrfOptions } from "./CsrfOptions.js";
|
|
5
|
-
import { RateLimiterOptions } from "./RateLimiterOptions.js";
|
|
6
|
-
import { RequestSizeLimiterOptions } from "./RequestSizeLimiterOptions.js";
|
|
7
|
-
import { SecurityHeaders } from "./SecurityHeaders.js";
|
|
8
|
-
import { SsgOptions } from "./SsgOptions.js";
|
|
9
|
-
export interface ModuleOptions {
|
|
10
|
-
allowedMethodsRestricter: AllowedMethodsRestricterOptions | false;
|
|
11
|
-
basicAuth: BasicAuthOptions | false;
|
|
12
|
-
contentSecurityPolicyReportOnly: boolean;
|
|
13
|
-
corsHandler: CorsHandlerOptions | false;
|
|
14
|
-
csrf: CsrfOptions | false;
|
|
15
|
-
enabled: boolean;
|
|
16
|
-
headers: false | SecurityHeaders;
|
|
17
|
-
hidePoweredBy: boolean;
|
|
18
|
-
nonce: boolean;
|
|
19
|
-
rateLimiter: false | RateLimiterOptions;
|
|
20
|
-
removeLoggers: boolean;
|
|
21
|
-
requestSizeLimiter: false | RequestSizeLimiterOptions;
|
|
22
|
-
sri: boolean;
|
|
23
|
-
ssg: false | SsgOptions;
|
|
24
|
-
strict: boolean;
|
|
25
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type PermissionsPolicy = Record<string, false | string[] | undefined>;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ContentSecurityPolicy } from "./ContentSecurityPolicy.js";
|
|
2
|
-
import { CrossOriginEmbedderPolicy } from "./CrossOriginEmbedderPolicy.js";
|
|
3
|
-
import { PermissionsPolicy } from "./PermissionsPolicy.js";
|
|
4
|
-
import { StrictTransportSecurity } from "./StrictTransportSecurity.js";
|
|
5
|
-
import { XFrameOptions } from "./XFrameOptions.js";
|
|
6
|
-
export interface SecurityHeaders {
|
|
7
|
-
contentSecurityPolicy?: ContentSecurityPolicy | false;
|
|
8
|
-
crossOriginEmbedderPolicy?: CrossOriginEmbedderPolicy | false;
|
|
9
|
-
crossOriginOpenerPolicy?: false | string;
|
|
10
|
-
crossOriginResourcePolicy?: false | string;
|
|
11
|
-
originAgentCluster?: false | string;
|
|
12
|
-
permissionsPolicy?: false | PermissionsPolicy;
|
|
13
|
-
referrerPolicy?: false | string;
|
|
14
|
-
strictTransportSecurity?: false | StrictTransportSecurity;
|
|
15
|
-
xContentTypeOptions?: false | string;
|
|
16
|
-
xDNSPrefetchControl?: false | string;
|
|
17
|
-
xDownloadOptions?: false | string;
|
|
18
|
-
xFrameOptions?: false | XFrameOptions;
|
|
19
|
-
xPermittedCrossDomainPolicies?: false | string;
|
|
20
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { SecurityHeaders } from "../models/SecurityHeaders.js";
|
|
2
|
-
export declare const MODULE_NAME = "nuxt-security-module";
|
|
3
|
-
export declare const ROUTE_RULES_HOOK: `${typeof MODULE_NAME}:routeRules`;
|
|
4
|
-
export declare const SECURITY_HEADER_NAMES: Readonly<Record<keyof SecurityHeaders, string>>;
|
|
5
|
-
export declare const CONTENT_SECURITY_POLICY_REPORT_ONLY_HEADER_NAME = "Content-Security-Policy-Report-Only";
|
|
6
|
-
export declare const MAX_RATE_LIMIT_ENTRIES = 1e4;
|
|
7
|
-
export declare const UNKNOWN_CLIENT_KEY = "unknown";
|
|
8
|
-
export declare const CSRF_UNSAFE_METHODS: readonly string[];
|
|
9
|
-
export declare const CSRF_TOKEN_BYTE_LENGTH = 32;
|
|
10
|
-
export declare const NONCE_BYTE_LENGTH = 18;
|
|
11
|
-
export declare const NONCE_PLACEHOLDER = "'nonce-{{nonce}}'";
|
|
12
|
-
export declare const SRI_HASH_ALGORITHM = "SHA-384";
|
|
13
|
-
export declare const CSP_HASH_ALGORITHM = "SHA-256";
|
|
14
|
-
export declare const PRERENDERED_HEADERS_DIRECTORY_NAME = "nuxt-security";
|
|
15
|
-
export declare const PRERENDERED_HEADERS_FILE_NAME = "headers.json";
|
|
16
|
-
export declare const HTML_ATTRIBUTE_REGEX: RegExp;
|
|
17
|
-
export declare const HTML_TAG_REGEX: RegExp;
|
|
18
|
-
export declare const NONCE_TAG_NAMES: readonly string[];
|
|
19
|
-
export declare const FILE_UPLOAD_CONTENT_TYPE = "multipart/form-data";
|
|
20
|
-
export declare const SIZE_LIMITED_METHODS: readonly string[];
|
|
21
|
-
export declare const DEFAULT_BASIC_AUTH_REALM = "Please enter username and password";
|
|
22
|
-
export declare const BASIC_AUTHORIZATION_SCHEME = "Basic";
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// src/runtime/constants.ts
|
|
2
|
-
const MODULE_NAME = "nuxt-security-module";
|
|
3
|
-
const ROUTE_RULES_HOOK = `${MODULE_NAME}:routeRules`;
|
|
4
|
-
const SECURITY_HEADER_NAMES = {
|
|
5
|
-
contentSecurityPolicy: "Content-Security-Policy",
|
|
6
|
-
crossOriginEmbedderPolicy: "Cross-Origin-Embedder-Policy",
|
|
7
|
-
crossOriginOpenerPolicy: "Cross-Origin-Opener-Policy",
|
|
8
|
-
crossOriginResourcePolicy: "Cross-Origin-Resource-Policy",
|
|
9
|
-
originAgentCluster: "Origin-Agent-Cluster",
|
|
10
|
-
permissionsPolicy: "Permissions-Policy",
|
|
11
|
-
referrerPolicy: "Referrer-Policy",
|
|
12
|
-
strictTransportSecurity: "Strict-Transport-Security",
|
|
13
|
-
xContentTypeOptions: "X-Content-Type-Options",
|
|
14
|
-
xDNSPrefetchControl: "X-DNS-Prefetch-Control",
|
|
15
|
-
xDownloadOptions: "X-Download-Options",
|
|
16
|
-
xFrameOptions: "X-Frame-Options",
|
|
17
|
-
xPermittedCrossDomainPolicies: "X-Permitted-Cross-Domain-Policies"
|
|
18
|
-
};
|
|
19
|
-
const CONTENT_SECURITY_POLICY_REPORT_ONLY_HEADER_NAME = "Content-Security-Policy-Report-Only";
|
|
20
|
-
const MAX_RATE_LIMIT_ENTRIES = 1e4;
|
|
21
|
-
const UNKNOWN_CLIENT_KEY = "unknown";
|
|
22
|
-
const CSRF_UNSAFE_METHODS = [
|
|
23
|
-
"DELETE",
|
|
24
|
-
"PATCH",
|
|
25
|
-
"POST",
|
|
26
|
-
"PUT"
|
|
27
|
-
];
|
|
28
|
-
const CSRF_TOKEN_BYTE_LENGTH = 32;
|
|
29
|
-
const NONCE_BYTE_LENGTH = 18;
|
|
30
|
-
const NONCE_PLACEHOLDER = "'nonce-{{nonce}}'";
|
|
31
|
-
const SRI_HASH_ALGORITHM = "SHA-384";
|
|
32
|
-
const CSP_HASH_ALGORITHM = "SHA-256";
|
|
33
|
-
const PRERENDERED_HEADERS_DIRECTORY_NAME = "nuxt-security";
|
|
34
|
-
const PRERENDERED_HEADERS_FILE_NAME = "headers.json";
|
|
35
|
-
const HTML_ATTRIBUTE_PATTERN = String.raw`\s+[^\s"'<>/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'<>=]+))?`;
|
|
36
|
-
const HTML_ATTRIBUTE_REGEX = /\s+(?<name>[^\s"'<>/=]+)(?<assignment>\s*=\s*(?<value>"[^"]*"|'[^']*'|[^\s"'<>=]+))?/gu;
|
|
37
|
-
const HTML_TAG_REGEX = new RegExp(String.raw`<(script|style)\b((?:${HTML_ATTRIBUTE_PATTERN})*)(\s*\/?)>([\s\S]*?)<\/\1\s*>|<([a-z][\w:-]*)((?:${HTML_ATTRIBUTE_PATTERN})*)(\s*\/?)>`, "giu");
|
|
38
|
-
const NONCE_TAG_NAMES = [
|
|
39
|
-
"link",
|
|
40
|
-
"script",
|
|
41
|
-
"style"
|
|
42
|
-
];
|
|
43
|
-
const FILE_UPLOAD_CONTENT_TYPE = "multipart/form-data";
|
|
44
|
-
const SIZE_LIMITED_METHODS = [
|
|
45
|
-
"DELETE",
|
|
46
|
-
"POST",
|
|
47
|
-
"PUT"
|
|
48
|
-
];
|
|
49
|
-
const DEFAULT_BASIC_AUTH_REALM = "Please enter username and password";
|
|
50
|
-
const BASIC_AUTHORIZATION_SCHEME = "Basic";
|
|
51
|
-
export { BASIC_AUTHORIZATION_SCHEME, CONTENT_SECURITY_POLICY_REPORT_ONLY_HEADER_NAME, CSP_HASH_ALGORITHM, CSRF_TOKEN_BYTE_LENGTH, CSRF_UNSAFE_METHODS, DEFAULT_BASIC_AUTH_REALM, FILE_UPLOAD_CONTENT_TYPE, HTML_ATTRIBUTE_REGEX, HTML_TAG_REGEX, MAX_RATE_LIMIT_ENTRIES, MODULE_NAME, NONCE_BYTE_LENGTH, NONCE_PLACEHOLDER, NONCE_TAG_NAMES, PRERENDERED_HEADERS_DIRECTORY_NAME, PRERENDERED_HEADERS_FILE_NAME, ROUTE_RULES_HOOK, SECURITY_HEADER_NAMES, SIZE_LIMITED_METHODS, SRI_HASH_ALGORITHM, UNKNOWN_CLIENT_KEY };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
2
|
-
import { definePlugin } from "nitro";
|
|
3
|
-
import { isEvent } from "nitro/h3";
|
|
4
|
-
// src/runtime/nitro/plugins/hidePoweredBy.ts
|
|
5
|
-
const hidePoweredBy = definePlugin((nitroApp) => {
|
|
6
|
-
nitroApp.hooks.hook("response", (_response, event) => {
|
|
7
|
-
if (!isEvent(event)) return;
|
|
8
|
-
const rules = getSecurityRules(event);
|
|
9
|
-
if (rules?.enabled && rules.hidePoweredBy) event.res.headers.delete("x-powered-by");
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
export { hidePoweredBy as default };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { generateNonce } from "../../services/generateNonce.js";
|
|
2
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
3
|
-
import { getSecurityState } from "../../services/getSecurityState.js";
|
|
4
|
-
import { injectNonce } from "../../services/injectNonce.js";
|
|
5
|
-
import { definePlugin } from "nitro";
|
|
6
|
-
// src/runtime/nitro/plugins/nonce.ts
|
|
7
|
-
const HTML_SECTIONS = [
|
|
8
|
-
"body",
|
|
9
|
-
"bodyAppend",
|
|
10
|
-
"bodyPrepend",
|
|
11
|
-
"head"
|
|
12
|
-
];
|
|
13
|
-
const noncePlugin = definePlugin((nitroApp) => {
|
|
14
|
-
if (import.meta.prerender) return;
|
|
15
|
-
nitroApp.hooks.hook("render:route", (_context, { event }) => {
|
|
16
|
-
const rules = getSecurityRules(event);
|
|
17
|
-
if (rules?.enabled && rules.nonce) getSecurityState(event).nonce = generateNonce();
|
|
18
|
-
});
|
|
19
|
-
nitroApp.hooks.hook("render:html", (html, { event }) => {
|
|
20
|
-
const rules = getSecurityRules(event);
|
|
21
|
-
const nonce = getSecurityState(event).nonce;
|
|
22
|
-
if (!rules?.enabled || !rules.nonce || !rules.headers || !rules.headers.contentSecurityPolicy || !nonce) return;
|
|
23
|
-
for (const section of HTML_SECTIONS) html[section] = html[section].map((element) => injectNonce(element, nonce));
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
export { noncePlugin as default };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ROUTE_RULES_HOOK } from "../../constants.js";
|
|
2
|
-
import { setSecurityRouteMatcher } from "../../services/securityRouteMatcher.js";
|
|
3
|
-
import { definePlugin } from "nitro";
|
|
4
|
-
// src/runtime/nitro/plugins/routeRules.ts
|
|
5
|
-
const createRouteRulesPlugin = (routeRules) => definePlugin((nitroApp) => {
|
|
6
|
-
let routesResolved;
|
|
7
|
-
nitroApp.hooks.hook("request", () => {
|
|
8
|
-
routesResolved ??= (async () => {
|
|
9
|
-
const routes = structuredClone(routeRules);
|
|
10
|
-
await nitroApp.hooks.callHook(ROUTE_RULES_HOOK, routes);
|
|
11
|
-
setSecurityRouteMatcher(routes);
|
|
12
|
-
})();
|
|
13
|
-
return routesResolved;
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
export { createRouteRulesPlugin };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { CONTENT_SECURITY_POLICY_REPORT_ONLY_HEADER_NAME, SECURITY_HEADER_NAMES } from "../../constants.js";
|
|
2
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
3
|
-
import { getSecurityState } from "../../services/getSecurityState.js";
|
|
4
|
-
import { serializeSecurityHeaders } from "../../services/serializeSecurityHeaders.js";
|
|
5
|
-
import { updateContentSecurityPolicy } from "../../services/updateContentSecurityPolicy.js";
|
|
6
|
-
import { definePlugin } from "nitro";
|
|
7
|
-
// src/runtime/nitro/plugins/securityHeaders.ts
|
|
8
|
-
const CONTENT_SECURITY_POLICY_HEADER_NAME = SECURITY_HEADER_NAMES.contentSecurityPolicy;
|
|
9
|
-
const securityHeaders = definePlugin((nitroApp) => {
|
|
10
|
-
nitroApp.hooks.hook("render:route", (_context, { event }) => {
|
|
11
|
-
const rules = getSecurityRules(event);
|
|
12
|
-
if (!rules?.enabled || !rules.headers) return;
|
|
13
|
-
const { contentSecurityPolicy } = rules.headers;
|
|
14
|
-
const serializedHeaders = serializeSecurityHeaders({
|
|
15
|
-
...rules.headers,
|
|
16
|
-
contentSecurityPolicy: contentSecurityPolicy ? updateContentSecurityPolicy(contentSecurityPolicy, getSecurityState(event)) : false
|
|
17
|
-
});
|
|
18
|
-
for (const [name, value] of Object.entries(serializedHeaders)) {
|
|
19
|
-
const isPolicy = name === CONTENT_SECURITY_POLICY_HEADER_NAME;
|
|
20
|
-
event.res.headers.set(isPolicy && rules.contentSecurityPolicyReportOnly ? CONTENT_SECURITY_POLICY_REPORT_ONLY_HEADER_NAME : name, value);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
export { securityHeaders as default };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { collectSsgHashes } from "../../services/collectSsgHashes.js";
|
|
2
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
3
|
-
import { getSecurityState } from "../../services/getSecurityState.js";
|
|
4
|
-
import { insertContentSecurityPolicyMeta } from "../../services/insertContentSecurityPolicyMeta.js";
|
|
5
|
-
import { updateContentSecurityPolicy } from "../../services/updateContentSecurityPolicy.js";
|
|
6
|
-
import { definePlugin } from "nitro";
|
|
7
|
-
// src/runtime/nitro/plugins/ssgHashes.ts
|
|
8
|
-
const HTML_SECTIONS = [
|
|
9
|
-
"head",
|
|
10
|
-
"bodyPrepend",
|
|
11
|
-
"body",
|
|
12
|
-
"bodyAppend"
|
|
13
|
-
];
|
|
14
|
-
const ssgHashes = definePlugin((nitroApp) => {
|
|
15
|
-
if (!import.meta.prerender) return;
|
|
16
|
-
nitroApp.hooks.hook("render:html", async (html, { event }) => {
|
|
17
|
-
const rules = getSecurityRules(event);
|
|
18
|
-
if (!rules?.enabled || !rules.ssg || !rules.headers || !rules.headers.contentSecurityPolicy) return;
|
|
19
|
-
const state = getSecurityState(event);
|
|
20
|
-
state.hashes = await collectSsgHashes(HTML_SECTIONS.map((section) => html[section].join("")).join(""), rules.ssg);
|
|
21
|
-
if (!rules.ssg.meta) return;
|
|
22
|
-
const policy = updateContentSecurityPolicy(rules.headers.contentSecurityPolicy, state);
|
|
23
|
-
html.head = [insertContentSecurityPolicyMeta(html.head.join(""), policy)];
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
export { ssgHashes as default };
|