nuxt-security-module 4.1.1 → 4.2.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/package.json +4 -4
- package/dist/index.d.ts +0 -17
- package/dist/index.js +0 -105
- package/dist/models/AllowedMethodsRestricterOptions.d.ts +0 -5
- package/dist/models/BasicAuthOptions.d.ts +0 -9
- package/dist/models/ContentSecurityPolicy.d.ts +0 -3
- package/dist/models/CorsHandlerOptions.d.ts +0 -13
- package/dist/models/CrossOriginEmbedderPolicy.d.ts +0 -8
- package/dist/models/CrossOriginEmbedderPolicy.js +0 -8
- package/dist/models/CsrfOptions.d.ts +0 -6
- package/dist/models/ModuleOptions.d.ts +0 -27
- package/dist/models/PermissionsPolicy.d.ts +0 -3
- package/dist/models/RateLimitWindow.d.ts +0 -6
- package/dist/models/RateLimiterOptions.d.ts +0 -6
- package/dist/models/RateLimiterStore.d.ts +0 -6
- package/dist/models/RequestSizeLimiterOptions.d.ts +0 -6
- package/dist/models/SecurityHeaders.d.ts +0 -22
- package/dist/models/SecurityRouteRules.d.ts +0 -4
- package/dist/models/SecurityRules.d.ts +0 -4
- package/dist/models/SsgOptions.d.ts +0 -9
- package/dist/models/StrictTransportSecurity.d.ts +0 -7
- package/dist/models/XFrameOptions.d.ts +0 -7
- package/dist/models/XFrameOptions.js +0 -7
- package/dist/runtime/constants.d.ts +0 -24
- package/dist/runtime/constants.js +0 -52
- package/dist/runtime/nitro/plugins/hidePoweredBy.d.ts +0 -5
- package/dist/runtime/nitro/plugins/hidePoweredBy.js +0 -13
- package/dist/runtime/nitro/plugins/nonce.d.ts +0 -5
- package/dist/runtime/nitro/plugins/nonce.js +0 -27
- package/dist/runtime/nitro/plugins/routeRules.d.ts +0 -5
- package/dist/runtime/nitro/plugins/routeRules.js +0 -17
- package/dist/runtime/nitro/plugins/securityHeaders.d.ts +0 -5
- package/dist/runtime/nitro/plugins/securityHeaders.js +0 -25
- package/dist/runtime/nitro/plugins/ssgHashes.d.ts +0 -5
- package/dist/runtime/nitro/plugins/ssgHashes.js +0 -27
- package/dist/runtime/nitro/plugins/subresourceIntegrity.d.ts +0 -4
- package/dist/runtime/nitro/plugins/subresourceIntegrity.js +0 -19
- package/dist/runtime/server/middleware/allowedMethodsRestricter.d.ts +0 -5
- package/dist/runtime/server/middleware/allowedMethodsRestricter.js +0 -15
- package/dist/runtime/server/middleware/basicAuth.d.ts +0 -5
- package/dist/runtime/server/middleware/basicAuth.js +0 -23
- package/dist/runtime/server/middleware/corsHandler.d.ts +0 -5
- package/dist/runtime/server/middleware/corsHandler.js +0 -20
- package/dist/runtime/server/middleware/csrf.d.ts +0 -5
- package/dist/runtime/server/middleware/csrf.js +0 -28
- package/dist/runtime/server/middleware/rateLimiter.d.ts +0 -5
- package/dist/runtime/server/middleware/rateLimiter.js +0 -22
- package/dist/runtime/server/middleware/requestSizeLimiter.d.ts +0 -5
- package/dist/runtime/server/middleware/requestSizeLimiter.js +0 -17
- package/dist/runtime/services/checkIsBasicAuthorized.d.ts +0 -4
- package/dist/runtime/services/checkIsBasicAuthorized.js +0 -12
- package/dist/runtime/services/checkIsChallenged.d.ts +0 -4
- package/dist/runtime/services/checkIsChallenged.js +0 -8
- package/dist/runtime/services/checkIsCsrfTokenValid.d.ts +0 -3
- package/dist/runtime/services/checkIsCsrfTokenValid.js +0 -8
- package/dist/runtime/services/checkIsEqualInConstantTime.d.ts +0 -3
- package/dist/runtime/services/checkIsEqualInConstantTime.js +0 -11
- package/dist/runtime/services/checkIsMethodAllowed.d.ts +0 -3
- package/dist/runtime/services/checkIsMethodAllowed.js +0 -4
- package/dist/runtime/services/checkIsRecord.d.ts +0 -3
- package/dist/runtime/services/checkIsRecord.js +0 -4
- package/dist/runtime/services/checkIsRequestTooLarge.d.ts +0 -4
- package/dist/runtime/services/checkIsRequestTooLarge.js +0 -9
- package/dist/runtime/services/collectSsgHashes.d.ts +0 -5
- package/dist/runtime/services/collectSsgHashes.js +0 -41
- package/dist/runtime/services/createInMemoryRateLimiterStore.d.ts +0 -4
- package/dist/runtime/services/createInMemoryRateLimiterStore.js +0 -22
- package/dist/runtime/services/generateHash.d.ts +0 -3
- package/dist/runtime/services/generateHash.js +0 -9
- package/dist/runtime/services/generateNonce.d.ts +0 -3
- package/dist/runtime/services/generateNonce.js +0 -6
- package/dist/runtime/services/generateRandomToken.d.ts +0 -3
- package/dist/runtime/services/generateRandomToken.js +0 -8
- package/dist/runtime/services/getBasicAuthCredentials.d.ts +0 -6
- package/dist/runtime/services/getBasicAuthCredentials.js +0 -19
- package/dist/runtime/services/getBasicAuthOptions.d.ts +0 -4
- package/dist/runtime/services/getBasicAuthOptions.js +0 -17
- package/dist/runtime/services/getRetryAfterSeconds.d.ts +0 -5
- package/dist/runtime/services/getRetryAfterSeconds.js +0 -9
- package/dist/runtime/services/getSecurityRules.d.ts +0 -5
- package/dist/runtime/services/getSecurityRules.js +0 -15
- package/dist/runtime/services/getSecurityState.d.ts +0 -11
- package/dist/runtime/services/getSecurityState.js +0 -14
- package/dist/runtime/services/injectNonce.d.ts +0 -3
- package/dist/runtime/services/injectNonce.js +0 -7
- package/dist/runtime/services/injectSubresourceIntegrity.d.ts +0 -3
- package/dist/runtime/services/injectSubresourceIntegrity.js +0 -22
- package/dist/runtime/services/insertContentSecurityPolicyMeta.d.ts +0 -4
- package/dist/runtime/services/insertContentSecurityPolicyMeta.js +0 -17
- package/dist/runtime/services/mergeSecurityRules.d.ts +0 -4
- package/dist/runtime/services/mergeSecurityRules.js +0 -11
- package/dist/runtime/services/readHtmlTagAttribute.d.ts +0 -3
- package/dist/runtime/services/readHtmlTagAttribute.js +0 -8
- package/dist/runtime/services/rewriteHtmlTags.d.ts +0 -3
- package/dist/runtime/services/rewriteHtmlTags.js +0 -9
- package/dist/runtime/services/securityRouteMatcher.d.ts +0 -5
- package/dist/runtime/services/securityRouteMatcher.js +0 -11
- package/dist/runtime/services/serializeBasicAuthChallenge.d.ts +0 -3
- package/dist/runtime/services/serializeBasicAuthChallenge.js +0 -4
- package/dist/runtime/services/serializeContentSecurityPolicy.d.ts +0 -4
- package/dist/runtime/services/serializeContentSecurityPolicy.js +0 -7
- package/dist/runtime/services/serializePermissionsPolicy.d.ts +0 -4
- package/dist/runtime/services/serializePermissionsPolicy.js +0 -4
- package/dist/runtime/services/serializeSecurityHeaders.d.ts +0 -4
- package/dist/runtime/services/serializeSecurityHeaders.js +0 -19
- package/dist/runtime/services/serializeStrictTransportSecurity.d.ts +0 -4
- package/dist/runtime/services/serializeStrictTransportSecurity.js +0 -8
- package/dist/runtime/services/stripHtmlTagAttribute.d.ts +0 -3
- package/dist/runtime/services/stripHtmlTagAttribute.js +0 -5
- package/dist/runtime/services/updateContentSecurityPolicy.d.ts +0 -5
- package/dist/runtime/services/updateContentSecurityPolicy.js +0 -15
- package/dist/schemas/allowedMethodsRestricterOptionsSchema.js +0 -5
- package/dist/schemas/basicAuthOptionsSchema.js +0 -12
- package/dist/schemas/contentSecurityPolicySchema.js +0 -5
- package/dist/schemas/corsHandlerOptionsSchema.js +0 -14
- package/dist/schemas/csrfOptionsSchema.js +0 -9
- package/dist/schemas/moduleOptionsSchema.js +0 -29
- package/dist/schemas/permissionsPolicySchema.js +0 -5
- package/dist/schemas/rateLimiterOptionsSchema.js +0 -8
- package/dist/schemas/requestSizeLimiterOptionsSchema.js +0 -8
- package/dist/schemas/securityHeadersSchema.js +0 -25
- package/dist/schemas/ssgOptionsSchema.js +0 -11
- package/dist/schemas/strictTransportSecurityOptionsSchema.js +0 -9
- package/dist/services/computeSubresourceIntegrityHashes.js +0 -29
- package/dist/services/formatZodIssues.js +0 -16
- package/dist/services/getDefaultModuleOptions.js +0 -41
- package/dist/services/getDefaultSecurityHeaders.js +0 -85
- package/dist/services/getPluginTemplate.js +0 -10
- package/dist/services/getRemoveLoggersViteConfig.js +0 -4
- package/dist/services/getRouteRulesTemplate.js +0 -4
- package/dist/services/getRouteSecurityRules.js +0 -17
- package/dist/services/getStaticResourceHeaders.js +0 -12
- package/dist/services/getTypeTemplate.js +0 -25
- package/dist/services/mergeModuleOptions.js +0 -39
- package/dist/services/parseModuleOptions.js +0 -10
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import "../../constants.js";
|
|
2
|
-
import { checkIsBasicAuthorized } from "../../services/checkIsBasicAuthorized.js";
|
|
3
|
-
import { checkIsChallenged } from "../../services/checkIsChallenged.js";
|
|
4
|
-
import { getBasicAuthOptions } from "../../services/getBasicAuthOptions.js";
|
|
5
|
-
import { serializeBasicAuthChallenge } from "../../services/serializeBasicAuthChallenge.js";
|
|
6
|
-
import { defineMiddleware } from "nitro";
|
|
7
|
-
import { HTTPError } from "nitro/h3";
|
|
8
|
-
import { useRuntimeConfig } from "nuxt/server";
|
|
9
|
-
//#region src/runtime/server/middleware/basicAuth.ts
|
|
10
|
-
const basicAuthMiddleware = defineMiddleware((event) => {
|
|
11
|
-
const basicAuth = getBasicAuthOptions(useRuntimeConfig().private);
|
|
12
|
-
if (!basicAuth) return;
|
|
13
|
-
const { pathname } = event.url;
|
|
14
|
-
if (!checkIsChallenged(pathname, basicAuth)) return;
|
|
15
|
-
if (checkIsBasicAuthorized(event.req.headers.get("authorization"), basicAuth)) return;
|
|
16
|
-
event.res.headers.set("WWW-Authenticate", serializeBasicAuthChallenge(basicAuth.message || "Please enter username and password"));
|
|
17
|
-
throw new HTTPError({
|
|
18
|
-
status: 401,
|
|
19
|
-
statusText: "Access denied"
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
//#endregion
|
|
23
|
-
export { basicAuthMiddleware as default };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
2
|
-
import { defineMiddleware } from "nitro";
|
|
3
|
-
import { handleCors } from "nitro/h3";
|
|
4
|
-
//#region src/runtime/server/middleware/corsHandler.ts
|
|
5
|
-
const corsHandler = defineMiddleware((event) => {
|
|
6
|
-
const rules = getSecurityRules(event);
|
|
7
|
-
if (!rules?.enabled || !rules.corsHandler) return;
|
|
8
|
-
const { allowHeaders, credentials, exposeHeaders, maxAge, methods, origin, preflight } = rules.corsHandler;
|
|
9
|
-
handleCors(event, {
|
|
10
|
-
allowHeaders,
|
|
11
|
-
credentials,
|
|
12
|
-
exposeHeaders,
|
|
13
|
-
maxAge,
|
|
14
|
-
methods,
|
|
15
|
-
origin: [origin].flat(),
|
|
16
|
-
preflight
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
//#endregion
|
|
20
|
-
export { corsHandler as default };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { CSRF_UNSAFE_METHODS } from "../../constants.js";
|
|
2
|
-
import { checkIsCsrfTokenValid } from "../../services/checkIsCsrfTokenValid.js";
|
|
3
|
-
import { generateRandomToken } from "../../services/generateRandomToken.js";
|
|
4
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
5
|
-
import { defineMiddleware } from "nitro";
|
|
6
|
-
import { HTTPError, getCookie, setCookie } from "nitro/h3";
|
|
7
|
-
//#region src/runtime/server/middleware/csrf.ts
|
|
8
|
-
const csrf = defineMiddleware((event) => {
|
|
9
|
-
const rules = getSecurityRules(event);
|
|
10
|
-
if (!rules?.enabled || !rules.csrf) return;
|
|
11
|
-
const { cookieName, headerName } = rules.csrf;
|
|
12
|
-
const cookieToken = getCookie(event, cookieName);
|
|
13
|
-
if (!CSRF_UNSAFE_METHODS.includes(event.req.method)) {
|
|
14
|
-
if (cookieToken === void 0) setCookie(event, cookieName, generateRandomToken(32), {
|
|
15
|
-
httpOnly: false,
|
|
16
|
-
path: "/",
|
|
17
|
-
sameSite: "strict",
|
|
18
|
-
secure: event.url.protocol === "https:"
|
|
19
|
-
});
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (!checkIsCsrfTokenValid(cookieToken, event.req.headers.get(headerName))) throw new HTTPError({
|
|
23
|
-
status: 403,
|
|
24
|
-
statusText: "Forbidden"
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
//#endregion
|
|
28
|
-
export { csrf as default };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { MAX_RATE_LIMIT_ENTRIES } from "../../constants.js";
|
|
2
|
-
import { createInMemoryRateLimiterStore } from "../../services/createInMemoryRateLimiterStore.js";
|
|
3
|
-
import { getRetryAfterSeconds } from "../../services/getRetryAfterSeconds.js";
|
|
4
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
5
|
-
import { defineMiddleware } from "nitro";
|
|
6
|
-
import { HTTPError, getRequestIP } from "nitro/h3";
|
|
7
|
-
//#region src/runtime/server/middleware/rateLimiter.ts
|
|
8
|
-
const rateLimiterStore = createInMemoryRateLimiterStore(MAX_RATE_LIMIT_ENTRIES);
|
|
9
|
-
const rateLimiter = defineMiddleware(async (event) => {
|
|
10
|
-
const rules = getSecurityRules(event);
|
|
11
|
-
if (!rules?.enabled || !rules.rateLimiter) return;
|
|
12
|
-
const key = getRequestIP(event, { xForwardedFor: false }) ?? "unknown";
|
|
13
|
-
const retryAfterSeconds = await getRetryAfterSeconds(rateLimiterStore, key, rules.rateLimiter);
|
|
14
|
-
if (retryAfterSeconds === void 0) return;
|
|
15
|
-
event.res.headers.set("Retry-After", String(retryAfterSeconds));
|
|
16
|
-
throw new HTTPError({
|
|
17
|
-
status: 429,
|
|
18
|
-
statusText: "Too Many Requests"
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
//#endregion
|
|
22
|
-
export { rateLimiter as default };
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { checkIsRequestTooLarge } from "../../services/checkIsRequestTooLarge.js";
|
|
2
|
-
import { getSecurityRules } from "../../services/getSecurityRules.js";
|
|
3
|
-
import { defineMiddleware } from "nitro";
|
|
4
|
-
import { HTTPError } from "nitro/h3";
|
|
5
|
-
//#region src/runtime/server/middleware/requestSizeLimiter.ts
|
|
6
|
-
const requestSizeLimiter = defineMiddleware((event) => {
|
|
7
|
-
const rules = getSecurityRules(event);
|
|
8
|
-
if (!rules?.enabled || !rules.requestSizeLimiter) return;
|
|
9
|
-
const contentLength = event.req.headers.get("content-length");
|
|
10
|
-
const contentType = event.req.headers.get("content-type");
|
|
11
|
-
if (checkIsRequestTooLarge(event.req.method, contentLength, contentType, rules.requestSizeLimiter)) throw new HTTPError({
|
|
12
|
-
status: 413,
|
|
13
|
-
statusText: "Payload Too Large"
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
//#endregion
|
|
17
|
-
export { requestSizeLimiter as default };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { checkIsEqualInConstantTime } from "./checkIsEqualInConstantTime.js";
|
|
2
|
-
import { getBasicAuthCredentials } from "./getBasicAuthCredentials.js";
|
|
3
|
-
//#region src/runtime/services/checkIsBasicAuthorized.ts
|
|
4
|
-
const checkIsBasicAuthorized = (authorization, { name, pass }) => {
|
|
5
|
-
const credentials = getBasicAuthCredentials(authorization);
|
|
6
|
-
if (!credentials) return false;
|
|
7
|
-
const isNameEqual = checkIsEqualInConstantTime(credentials.name, name);
|
|
8
|
-
const isPassEqual = checkIsEqualInConstantTime(credentials.pass, pass);
|
|
9
|
-
return isNameEqual && isPassEqual;
|
|
10
|
-
};
|
|
11
|
-
//#endregion
|
|
12
|
-
export { checkIsBasicAuthorized };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/checkIsChallenged.ts
|
|
2
|
-
const checkIsChallenged = (path, { exclude = [], include = [] }) => {
|
|
3
|
-
const isIncluded = include.some((prefix) => path.startsWith(prefix));
|
|
4
|
-
const isExcluded = exclude.some((prefix) => path.startsWith(prefix));
|
|
5
|
-
return isIncluded || !isExcluded;
|
|
6
|
-
};
|
|
7
|
-
//#endregion
|
|
8
|
-
export { checkIsChallenged };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { checkIsEqualInConstantTime } from "./checkIsEqualInConstantTime.js";
|
|
2
|
-
//#region src/runtime/services/checkIsCsrfTokenValid.ts
|
|
3
|
-
const checkIsCsrfTokenValid = (cookieToken, headerToken) => {
|
|
4
|
-
if (!cookieToken || !headerToken) return false;
|
|
5
|
-
return checkIsEqualInConstantTime(cookieToken, headerToken);
|
|
6
|
-
};
|
|
7
|
-
//#endregion
|
|
8
|
-
export { checkIsCsrfTokenValid };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/checkIsEqualInConstantTime.ts
|
|
2
|
-
const checkIsEqualInConstantTime = (first, second) => {
|
|
3
|
-
const firstBytes = new TextEncoder().encode(first);
|
|
4
|
-
const secondBytes = new TextEncoder().encode(second);
|
|
5
|
-
if (firstBytes.length !== secondBytes.length) return false;
|
|
6
|
-
let difference = 0;
|
|
7
|
-
for (const [index, byte] of firstBytes.entries()) difference |= byte ^ (secondBytes[index] ?? 0);
|
|
8
|
-
return difference === 0;
|
|
9
|
-
};
|
|
10
|
-
//#endregion
|
|
11
|
-
export { checkIsEqualInConstantTime };
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { RequestSizeLimiterOptions } from "../../models/RequestSizeLimiterOptions.js";
|
|
2
|
-
//#region src/runtime/services/checkIsRequestTooLarge.d.ts
|
|
3
|
-
export declare const checkIsRequestTooLarge: (method: string, contentLength: null | string, contentType: null | string, { maxRequestSizeInBytes, maxUploadFileRequestInBytes }: RequestSizeLimiterOptions) => boolean;
|
|
4
|
-
//#endregion
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SIZE_LIMITED_METHODS } from "../constants.js";
|
|
2
|
-
//#region src/runtime/services/checkIsRequestTooLarge.ts
|
|
3
|
-
const checkIsRequestTooLarge = (method, contentLength, contentType, { maxRequestSizeInBytes, maxUploadFileRequestInBytes }) => {
|
|
4
|
-
if (!SIZE_LIMITED_METHODS.includes(method) || contentLength === null) return false;
|
|
5
|
-
const limit = contentType?.includes("multipart/form-data") ?? false ? maxUploadFileRequestInBytes : maxRequestSizeInBytes;
|
|
6
|
-
return Math.trunc(Number(contentLength)) >= limit;
|
|
7
|
-
};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { checkIsRequestTooLarge };
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { SsgOptions } from "../../models/SsgOptions.js";
|
|
2
|
-
import { SecurityState } from "./getSecurityState.js";
|
|
3
|
-
//#region src/runtime/services/collectSsgHashes.d.ts
|
|
4
|
-
export declare const collectSsgHashes: (html: string, options: SsgOptions) => Promise<SecurityState["hashes"]>;
|
|
5
|
-
//#endregion
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { CSP_HASH_ALGORITHM, HTML_TAG_REGEX } from "../constants.js";
|
|
2
|
-
import { generateHash } from "./generateHash.js";
|
|
3
|
-
import { readHtmlTagAttribute } from "./readHtmlTagAttribute.js";
|
|
4
|
-
//#region src/runtime/services/collectSsgHashes.ts
|
|
5
|
-
const SCRIPT_PRELOAD_TYPES = /* @__PURE__ */ new Set([
|
|
6
|
-
"audioworklet",
|
|
7
|
-
"paintworklet",
|
|
8
|
-
"script",
|
|
9
|
-
"xslt"
|
|
10
|
-
]);
|
|
11
|
-
const getSsgHashSource = async ([name, attributes, body], { hashScripts, hashStyles }) => {
|
|
12
|
-
const integrity = readHtmlTagAttribute(attributes, "integrity");
|
|
13
|
-
if (name === "script" && hashScripts) {
|
|
14
|
-
const source = readHtmlTagAttribute(attributes, "src");
|
|
15
|
-
if (source !== void 0 && integrity !== void 0) return ["script", `'${integrity}'`];
|
|
16
|
-
if (source === void 0 && body) return ["script", `'${await generateHash(body, CSP_HASH_ALGORITHM)}'`];
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (name === "style" && hashStyles && body) return ["style", `'${await generateHash(body, CSP_HASH_ALGORITHM)}'`];
|
|
20
|
-
if (name !== "link" || integrity === void 0) return void 0;
|
|
21
|
-
const rel = readHtmlTagAttribute(attributes, "rel");
|
|
22
|
-
const as = readHtmlTagAttribute(attributes, "as") ?? "";
|
|
23
|
-
if (rel === "stylesheet" && hashStyles) return ["style", `'${integrity}'`];
|
|
24
|
-
if (hashScripts && (rel === "modulepreload" || rel === "preload" && SCRIPT_PRELOAD_TYPES.has(as))) return ["script", `'${integrity}'`];
|
|
25
|
-
};
|
|
26
|
-
const collectSsgHashes = async (html, options) => {
|
|
27
|
-
const elements = Array.from(html.matchAll(HTML_TAG_REGEX), ([, elementName, elementAttributes, , body, tagName, tagAttributes]) => [
|
|
28
|
-
(elementName ?? tagName ?? "").toLowerCase(),
|
|
29
|
-
elementAttributes ?? tagAttributes ?? "",
|
|
30
|
-
body
|
|
31
|
-
]);
|
|
32
|
-
const hashSources = await Promise.all(elements.map((element) => getSsgHashSource(element, options)));
|
|
33
|
-
const hashes = {
|
|
34
|
-
script: [],
|
|
35
|
-
style: []
|
|
36
|
-
};
|
|
37
|
-
for (const hashSource of hashSources) if (hashSource) hashes[hashSource[0]].push(hashSource[1]);
|
|
38
|
-
return hashes;
|
|
39
|
-
};
|
|
40
|
-
//#endregion
|
|
41
|
-
export { collectSsgHashes };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/createInMemoryRateLimiterStore.ts
|
|
2
|
-
const createInMemoryRateLimiterStore = (maxEntries) => {
|
|
3
|
-
const windows = /* @__PURE__ */ new Map();
|
|
4
|
-
return { increment: (key, intervalInMilliseconds) => {
|
|
5
|
-
const now = Date.now();
|
|
6
|
-
const current = windows.get(key);
|
|
7
|
-
const window = current && current.resetAt > now ? {
|
|
8
|
-
count: current.count + 1,
|
|
9
|
-
resetAt: current.resetAt
|
|
10
|
-
} : {
|
|
11
|
-
count: 1,
|
|
12
|
-
resetAt: now + intervalInMilliseconds
|
|
13
|
-
};
|
|
14
|
-
windows.delete(key);
|
|
15
|
-
windows.set(key, window);
|
|
16
|
-
const [oldestKey] = windows.keys();
|
|
17
|
-
if (windows.size > maxEntries && oldestKey !== void 0) windows.delete(oldestKey);
|
|
18
|
-
return Promise.resolve(window);
|
|
19
|
-
} };
|
|
20
|
-
};
|
|
21
|
-
//#endregion
|
|
22
|
-
export { createInMemoryRateLimiterStore };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/generateHash.ts
|
|
2
|
-
const generateHash = async (content, hashAlgorithm) => {
|
|
3
|
-
const bytes = typeof content === "string" ? new TextEncoder().encode(content) : new Uint8Array(content);
|
|
4
|
-
const hashBuffer = await globalThis.crypto.subtle.digest(hashAlgorithm, bytes);
|
|
5
|
-
const base64 = btoa(String.fromCodePoint(...new Uint8Array(hashBuffer)));
|
|
6
|
-
return `${hashAlgorithm.replace("-", "").toLowerCase()}-${base64}`;
|
|
7
|
-
};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { generateHash };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/generateRandomToken.ts
|
|
2
|
-
const generateRandomToken = (byteLength) => {
|
|
3
|
-
const bytes = new Uint8Array(byteLength);
|
|
4
|
-
globalThis.crypto.getRandomValues(bytes);
|
|
5
|
-
return btoa(String.fromCodePoint(...bytes)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
|
|
6
|
-
};
|
|
7
|
-
//#endregion
|
|
8
|
-
export { generateRandomToken };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { BASIC_AUTHORIZATION_SCHEME } from "../constants.js";
|
|
2
|
-
//#region src/runtime/services/getBasicAuthCredentials.ts
|
|
3
|
-
const BASE64_REGEX = /^[\d+/A-Za-z]*={0,2}$/u;
|
|
4
|
-
const BASE64_QUANTUM_LENGTH = 4;
|
|
5
|
-
const checkIsBase64 = (value) => BASE64_REGEX.test(value) && (value.endsWith("=") ? value.length % BASE64_QUANTUM_LENGTH === 0 : value.length % BASE64_QUANTUM_LENGTH !== 1);
|
|
6
|
-
const getBasicAuthCredentials = (authorization) => {
|
|
7
|
-
if (!authorization?.startsWith(`Basic `)) return void 0;
|
|
8
|
-
const encoded = authorization.slice(BASIC_AUTHORIZATION_SCHEME.length + 1).trim();
|
|
9
|
-
if (!checkIsBase64(encoded)) return void 0;
|
|
10
|
-
const decoded = new TextDecoder().decode(Uint8Array.fromBase64(encoded));
|
|
11
|
-
const separatorIndex = decoded.indexOf(":");
|
|
12
|
-
if (separatorIndex === -1) return void 0;
|
|
13
|
-
return {
|
|
14
|
-
name: decoded.slice(0, separatorIndex),
|
|
15
|
-
pass: decoded.slice(separatorIndex + 1)
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
//#endregion
|
|
19
|
-
export { getBasicAuthCredentials };
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { checkIsRecord } from "./checkIsRecord.js";
|
|
2
|
-
//#region src/runtime/services/getBasicAuthOptions.ts
|
|
3
|
-
const checkIsStringList = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
4
|
-
const getBasicAuthOptions = (privateRuntimeConfig) => {
|
|
5
|
-
if (!checkIsRecord(privateRuntimeConfig) || !checkIsRecord(privateRuntimeConfig.basicAuth)) return void 0;
|
|
6
|
-
const { exclude, include, message, name, pass } = privateRuntimeConfig.basicAuth;
|
|
7
|
-
if (typeof name !== "string" || typeof pass !== "string") return void 0;
|
|
8
|
-
return {
|
|
9
|
-
...checkIsStringList(exclude) && { exclude },
|
|
10
|
-
...checkIsStringList(include) && { include },
|
|
11
|
-
...typeof message === "string" && { message },
|
|
12
|
-
name,
|
|
13
|
-
pass
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
//#endregion
|
|
17
|
-
export { getBasicAuthOptions };
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { RateLimiterOptions } from "../../models/RateLimiterOptions.js";
|
|
2
|
-
import { RateLimiterStore } from "../../models/RateLimiterStore.js";
|
|
3
|
-
//#region src/runtime/services/getRetryAfterSeconds.d.ts
|
|
4
|
-
export declare const getRetryAfterSeconds: (store: RateLimiterStore, key: string, { intervalInMilliseconds, tokensPerInterval }: RateLimiterOptions) => Promise<number | undefined>;
|
|
5
|
-
//#endregion
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/getRetryAfterSeconds.ts
|
|
2
|
-
const MILLISECONDS_PER_SECOND = 1e3;
|
|
3
|
-
const getRetryAfterSeconds = async (store, key, { intervalInMilliseconds, tokensPerInterval }) => {
|
|
4
|
-
const { count, resetAt } = await store.increment(key, intervalInMilliseconds);
|
|
5
|
-
if (count <= tokensPerInterval) return void 0;
|
|
6
|
-
return Math.max(1, Math.ceil((resetAt - Date.now()) / MILLISECONDS_PER_SECOND));
|
|
7
|
-
};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { getRetryAfterSeconds };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { mergeSecurityRules } from "./mergeSecurityRules.js";
|
|
2
|
-
import { findSecurityRules } from "./securityRouteMatcher.js";
|
|
3
|
-
//#region src/runtime/services/getSecurityRules.ts
|
|
4
|
-
const securityRulesByEvent = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
const getSecurityRules = (event) => {
|
|
6
|
-
const cachedRules = securityRulesByEvent.get(event);
|
|
7
|
-
if (cachedRules) return cachedRules;
|
|
8
|
-
const matchedRules = findSecurityRules(event.url.pathname);
|
|
9
|
-
if (!matchedRules) return void 0;
|
|
10
|
-
const rules = mergeSecurityRules(...matchedRules.toReversed());
|
|
11
|
-
securityRulesByEvent.set(event, rules);
|
|
12
|
-
return rules;
|
|
13
|
-
};
|
|
14
|
-
//#endregion
|
|
15
|
-
export { getSecurityRules };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { H3Event } from "nitro/h3";
|
|
2
|
-
//#region src/runtime/services/getSecurityState.d.ts
|
|
3
|
-
export interface SecurityState {
|
|
4
|
-
hashes: {
|
|
5
|
-
script: string[];
|
|
6
|
-
style: string[];
|
|
7
|
-
};
|
|
8
|
-
nonce?: string;
|
|
9
|
-
}
|
|
10
|
-
export declare const getSecurityState: (event: H3Event) => SecurityState;
|
|
11
|
-
//#endregion
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/services/getSecurityState.ts
|
|
2
|
-
const securityStateByEvent = /* @__PURE__ */ new WeakMap();
|
|
3
|
-
const getSecurityState = (event) => {
|
|
4
|
-
const cachedState = securityStateByEvent.get(event);
|
|
5
|
-
if (cachedState) return cachedState;
|
|
6
|
-
const state = { hashes: {
|
|
7
|
-
script: [],
|
|
8
|
-
style: []
|
|
9
|
-
} };
|
|
10
|
-
securityStateByEvent.set(event, state);
|
|
11
|
-
return state;
|
|
12
|
-
};
|
|
13
|
-
//#endregion
|
|
14
|
-
export { getSecurityState };
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { NONCE_TAG_NAMES } from "../constants.js";
|
|
2
|
-
import { rewriteHtmlTags } from "./rewriteHtmlTags.js";
|
|
3
|
-
import { stripHtmlTagAttribute } from "./stripHtmlTagAttribute.js";
|
|
4
|
-
//#region src/runtime/services/injectNonce.ts
|
|
5
|
-
const injectNonce = (html, nonce) => rewriteHtmlTags(html, (tagName, attributes) => NONCE_TAG_NAMES.includes(tagName.toLowerCase()) ? ` nonce="${nonce}"${stripHtmlTagAttribute(attributes, "nonce")}` : void 0);
|
|
6
|
-
//#endregion
|
|
7
|
-
export { injectNonce };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { readHtmlTagAttribute } from "./readHtmlTagAttribute.js";
|
|
2
|
-
import { rewriteHtmlTags } from "./rewriteHtmlTags.js";
|
|
3
|
-
//#region src/runtime/services/injectSubresourceIntegrity.ts
|
|
4
|
-
const RESOURCE_ATTRIBUTE_NAMES = {
|
|
5
|
-
link: "href",
|
|
6
|
-
script: "src"
|
|
7
|
-
};
|
|
8
|
-
const INTEGRITY_LINK_RELS = /* @__PURE__ */ new Set([
|
|
9
|
-
"modulepreload",
|
|
10
|
-
"preload",
|
|
11
|
-
"stylesheet"
|
|
12
|
-
]);
|
|
13
|
-
const injectSubresourceIntegrity = (html, hashes) => rewriteHtmlTags(html, (tagName, attributes) => {
|
|
14
|
-
const resourceAttributeName = RESOURCE_ATTRIBUTE_NAMES[tagName.toLowerCase()];
|
|
15
|
-
if (!resourceAttributeName || readHtmlTagAttribute(attributes, "integrity") !== void 0) return void 0;
|
|
16
|
-
const resource = readHtmlTagAttribute(attributes, resourceAttributeName);
|
|
17
|
-
if (resource === void 0 || hashes[resource] === void 0) return void 0;
|
|
18
|
-
if (tagName.toLowerCase() === "link" && !INTEGRITY_LINK_RELS.has(readHtmlTagAttribute(attributes, "rel") ?? "")) return void 0;
|
|
19
|
-
return ` integrity="${hashes[resource]}"${attributes}`;
|
|
20
|
-
});
|
|
21
|
-
//#endregion
|
|
22
|
-
export { injectSubresourceIntegrity };
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { ContentSecurityPolicy } from "../../models/ContentSecurityPolicy.js";
|
|
2
|
-
//#region src/runtime/services/insertContentSecurityPolicyMeta.d.ts
|
|
3
|
-
export declare const insertContentSecurityPolicyMeta: (html: string, policy: ContentSecurityPolicy) => string;
|
|
4
|
-
//#endregion
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { serializeContentSecurityPolicy } from "./serializeContentSecurityPolicy.js";
|
|
2
|
-
//#region src/runtime/services/insertContentSecurityPolicyMeta.ts
|
|
3
|
-
const META_CONTENT_SECURITY_POLICY_REGEX = /<meta\s+http-equiv=["']Content-Security-Policy["'][^>]*>/iu;
|
|
4
|
-
const HEAD_CHARSET_REGEX = /<meta\s+charset=["'][^"']*["'][^>]*>/iu;
|
|
5
|
-
const HEAD_OPEN_REGEX = /<head\b[^>]*>/iu;
|
|
6
|
-
const insertContentSecurityPolicyMeta = (html, policy) => {
|
|
7
|
-
const metaTag = `<meta http-equiv="Content-Security-Policy" content="${serializeContentSecurityPolicy({
|
|
8
|
-
...policy,
|
|
9
|
-
"frame-ancestors": false
|
|
10
|
-
})}">`;
|
|
11
|
-
if (META_CONTENT_SECURITY_POLICY_REGEX.test(html)) return html.replace(META_CONTENT_SECURITY_POLICY_REGEX, metaTag);
|
|
12
|
-
const insertion = HEAD_CHARSET_REGEX.exec(html) ?? HEAD_OPEN_REGEX.exec(html);
|
|
13
|
-
const insertAt = insertion ? insertion.index + insertion[0].length : 0;
|
|
14
|
-
return html.slice(0, insertAt) + metaTag + html.slice(insertAt);
|
|
15
|
-
};
|
|
16
|
-
//#endregion
|
|
17
|
-
export { insertContentSecurityPolicyMeta };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { createDefu } from "defu";
|
|
2
|
-
//#region src/runtime/services/mergeSecurityRules.ts
|
|
3
|
-
const mergeRulesWithReplacedArrays = createDefu((object, key, value) => {
|
|
4
|
-
if (Array.isArray(object[key]) || Array.isArray(value)) {
|
|
5
|
-
object[key] = value;
|
|
6
|
-
return true;
|
|
7
|
-
}
|
|
8
|
-
});
|
|
9
|
-
const mergeSecurityRules = (...rules) => mergeRulesWithReplacedArrays({}, ...rules);
|
|
10
|
-
//#endregion
|
|
11
|
-
export { mergeSecurityRules };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { HTML_ATTRIBUTE_REGEX } from "../constants.js";
|
|
2
|
-
//#region src/runtime/services/readHtmlTagAttribute.ts
|
|
3
|
-
const readHtmlTagAttribute = (attributes, attributeName) => {
|
|
4
|
-
for (const [, name, , value] of attributes.matchAll(HTML_ATTRIBUTE_REGEX)) if (name?.toLowerCase() === attributeName) return unquote(value ?? "");
|
|
5
|
-
};
|
|
6
|
-
const unquote = (value) => value.replace(/^(?<quote>["'])(?<inner>.*)\k<quote>$/su, "$<inner>");
|
|
7
|
-
//#endregion
|
|
8
|
-
export { readHtmlTagAttribute };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { HTML_TAG_REGEX } from "../constants.js";
|
|
2
|
-
//#region src/runtime/services/rewriteHtmlTags.ts
|
|
3
|
-
const rewriteHtmlTags = (html, rewriteAttributes) => html.replace(HTML_TAG_REGEX, (match, elementName, elementAttributes, elementTrailer, body, tagName, tagAttributes, tagTrailer) => {
|
|
4
|
-
if (elementName) return `<${elementName}${rewriteAttributes(elementName, elementAttributes ?? "") ?? elementAttributes}${elementTrailer}>${body}</${elementName}>`;
|
|
5
|
-
const attributes = rewriteAttributes(tagName ?? "", tagAttributes ?? "");
|
|
6
|
-
return attributes === void 0 ? match : `<${tagName}${attributes}${tagTrailer}>`;
|
|
7
|
-
});
|
|
8
|
-
//#endregion
|
|
9
|
-
export { rewriteHtmlTags };
|