@holo-js/security 0.3.19 → 0.3.20
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/dist/{chunk-G3HBF4Q5.mjs → chunk-5SCCUNBO.mjs} +0 -26
- package/dist/{chunk-5M3RHQIG.mjs → chunk-CTRTL4CO.mjs} +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.mjs +1 -1
- package/dist/next/server.mjs +37 -5
- package/dist/nuxt/server.mjs +9 -4
- package/dist/sveltekit/server.mjs +7 -4
- package/package.json +3 -3
|
@@ -293,28 +293,6 @@ function getHeaderToken(request) {
|
|
|
293
293
|
const { header } = getSecurityRuntime().config.csrf;
|
|
294
294
|
return request.headers.get(header)?.trim() || void 0;
|
|
295
295
|
}
|
|
296
|
-
function getRequestOrigin(request) {
|
|
297
|
-
const origin = request.headers.get("origin")?.trim();
|
|
298
|
-
if (origin) {
|
|
299
|
-
return origin;
|
|
300
|
-
}
|
|
301
|
-
const referer = request.headers.get("referer")?.trim();
|
|
302
|
-
if (!referer) {
|
|
303
|
-
return void 0;
|
|
304
|
-
}
|
|
305
|
-
try {
|
|
306
|
-
return new URL(referer).origin;
|
|
307
|
-
} catch {
|
|
308
|
-
return void 0;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
function isSameOriginRequest(request) {
|
|
312
|
-
const requestOrigin = getRequestOrigin(request);
|
|
313
|
-
if (!requestOrigin) {
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
return requestOrigin === new URL(request.url).origin;
|
|
317
|
-
}
|
|
318
296
|
async function readFormToken(request) {
|
|
319
297
|
const { field: field2 } = getSecurityRuntime().config.csrf;
|
|
320
298
|
try {
|
|
@@ -343,9 +321,6 @@ async function verifyRequest(request, options) {
|
|
|
343
321
|
}
|
|
344
322
|
return;
|
|
345
323
|
}
|
|
346
|
-
if (isSameOriginRequest(request)) {
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
324
|
const requestToken = await readFormToken(request);
|
|
350
325
|
if (requestToken !== cookieToken) {
|
|
351
326
|
throw new SecurityCsrfError();
|
|
@@ -432,7 +407,6 @@ var csrfInternals = {
|
|
|
432
407
|
getCookieToken,
|
|
433
408
|
getHeaderToken,
|
|
434
409
|
isSecureRequest,
|
|
435
|
-
isSameOriginRequest,
|
|
436
410
|
readFormToken,
|
|
437
411
|
isExcludedPath,
|
|
438
412
|
isSafeMethod,
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ declare function decodeCsrfToken(token: string): {
|
|
|
23
23
|
declare function isValidSignedCsrfToken(token: string): boolean;
|
|
24
24
|
declare function getCookieToken(request: Request): string | undefined;
|
|
25
25
|
declare function getHeaderToken(request: Request): string | undefined;
|
|
26
|
-
declare function isSameOriginRequest(request: Request): boolean;
|
|
27
26
|
declare function readFormToken(request: Request): Promise<string | undefined>;
|
|
28
27
|
declare function token(request: Request): Promise<string>;
|
|
29
28
|
declare function field(request: Request): Promise<SecurityCsrfField>;
|
|
@@ -45,7 +44,6 @@ declare const csrfInternals: {
|
|
|
45
44
|
getCookieToken: typeof getCookieToken;
|
|
46
45
|
getHeaderToken: typeof getHeaderToken;
|
|
47
46
|
isSecureRequest: typeof isSecureRequest;
|
|
48
|
-
isSameOriginRequest: typeof isSameOriginRequest;
|
|
49
47
|
readFormToken: typeof readFormToken;
|
|
50
48
|
isExcludedPath: typeof isExcludedPath;
|
|
51
49
|
isSafeMethod: typeof isSafeMethod;
|
package/dist/index.mjs
CHANGED
package/dist/next/server.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
prepareCsrfCookies
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-CTRTL4CO.mjs";
|
|
4
4
|
import {
|
|
5
|
+
cors,
|
|
6
|
+
getSecurityRuntime,
|
|
5
7
|
protect
|
|
6
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-5SCCUNBO.mjs";
|
|
7
9
|
import "../chunk-FUOZWKHK.mjs";
|
|
8
10
|
import {
|
|
9
11
|
SecurityCsrfError
|
|
@@ -38,8 +40,34 @@ async function issueCsrfCookie(request) {
|
|
|
38
40
|
}
|
|
39
41
|
return response;
|
|
40
42
|
}
|
|
43
|
+
async function actionRequest(request) {
|
|
44
|
+
const { field, header } = getSecurityRuntime().config.csrf;
|
|
45
|
+
if (!request.headers.has("next-action") || request.headers.get(header)?.trim() || !request.headers.get("content-type")?.startsWith("multipart/form-data")) return request;
|
|
46
|
+
try {
|
|
47
|
+
const data = await request.clone().formData();
|
|
48
|
+
const root = data.get("0");
|
|
49
|
+
if (typeof root !== "string") return request;
|
|
50
|
+
const args = JSON.parse(root);
|
|
51
|
+
if (!Array.isArray(args)) return request;
|
|
52
|
+
for (const argument of args) {
|
|
53
|
+
if (typeof argument !== "string") continue;
|
|
54
|
+
const part = /^\$K([0-9a-f]+)$/.exec(argument)?.[1];
|
|
55
|
+
if (!part) continue;
|
|
56
|
+
const token = data.get(`_${Number.parseInt(part, 16)}_${field}`);
|
|
57
|
+
if (typeof token !== "string") continue;
|
|
58
|
+
const headers = new Headers(request.headers);
|
|
59
|
+
headers.set(header, token);
|
|
60
|
+
return new Request(request.clone(), { headers });
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
return request;
|
|
64
|
+
}
|
|
65
|
+
return request;
|
|
66
|
+
}
|
|
41
67
|
function csrfProtection() {
|
|
42
68
|
return async (request) => {
|
|
69
|
+
const preflight = cors.preflight(request);
|
|
70
|
+
if (preflight) return preflight;
|
|
43
71
|
if (request.method.trim().toUpperCase() === "TRACE") {
|
|
44
72
|
return new Response("Method Not Allowed", {
|
|
45
73
|
status: 405,
|
|
@@ -47,14 +75,18 @@ function csrfProtection() {
|
|
|
47
75
|
});
|
|
48
76
|
}
|
|
49
77
|
try {
|
|
50
|
-
await protect(request);
|
|
78
|
+
await protect(await actionRequest(request));
|
|
51
79
|
} catch (error) {
|
|
52
80
|
if (error instanceof SecurityCsrfError) {
|
|
53
|
-
return createCsrfErrorResponse(error);
|
|
81
|
+
return cors.apply(request, createCsrfErrorResponse(error));
|
|
54
82
|
}
|
|
55
83
|
throw error;
|
|
56
84
|
}
|
|
57
|
-
|
|
85
|
+
const response = await issueCsrfCookie(request);
|
|
86
|
+
if (response) return cors.apply(request, response);
|
|
87
|
+
if ([...cors.headers(request)].length === 0) return void 0;
|
|
88
|
+
const { NextResponse } = await import("next/server.js");
|
|
89
|
+
return cors.apply(request, NextResponse.next());
|
|
58
90
|
};
|
|
59
91
|
}
|
|
60
92
|
var nextSecurityInternals = {
|
package/dist/nuxt/server.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
prepareCsrfCookies
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-CTRTL4CO.mjs";
|
|
4
4
|
import {
|
|
5
|
+
cors,
|
|
5
6
|
protect
|
|
6
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-5SCCUNBO.mjs";
|
|
7
8
|
import "../chunk-FUOZWKHK.mjs";
|
|
8
9
|
import {
|
|
9
10
|
SecurityCsrfError
|
|
@@ -19,11 +20,12 @@ import {
|
|
|
19
20
|
getRequestHeaders,
|
|
20
21
|
getRequestURL,
|
|
21
22
|
readRawBody,
|
|
22
|
-
setCookie
|
|
23
|
+
setCookie,
|
|
24
|
+
setResponseHeader
|
|
23
25
|
} from "h3";
|
|
24
26
|
function isSafeMethod(method) {
|
|
25
27
|
const normalized = method.trim().toUpperCase();
|
|
26
|
-
return normalized === "GET" || normalized === "HEAD";
|
|
28
|
+
return normalized === "GET" || normalized === "HEAD" || normalized === "OPTIONS";
|
|
27
29
|
}
|
|
28
30
|
function createHeaders(event) {
|
|
29
31
|
const headers = new Headers();
|
|
@@ -67,6 +69,9 @@ function csrfProtection() {
|
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
71
|
const request = await createRequest(event);
|
|
72
|
+
const preflight = cors.preflight(request);
|
|
73
|
+
if (preflight) return preflight;
|
|
74
|
+
cors.headers(request).forEach((value, name) => setResponseHeader(event, name, value));
|
|
70
75
|
try {
|
|
71
76
|
await protect(request);
|
|
72
77
|
} catch (error) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
prepareCsrfCookies
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-CTRTL4CO.mjs";
|
|
4
4
|
import {
|
|
5
|
+
cors,
|
|
5
6
|
protect
|
|
6
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-5SCCUNBO.mjs";
|
|
7
8
|
import "../chunk-FUOZWKHK.mjs";
|
|
8
9
|
import {
|
|
9
10
|
SecurityCsrfError
|
|
@@ -27,6 +28,8 @@ function createCsrfErrorResponse(error) {
|
|
|
27
28
|
}
|
|
28
29
|
function csrfProtection() {
|
|
29
30
|
return async ({ event, resolve }) => {
|
|
31
|
+
const preflight = cors.preflight(event.request);
|
|
32
|
+
if (preflight) return preflight;
|
|
30
33
|
if (event.request.method.trim().toUpperCase() === "TRACE") {
|
|
31
34
|
return new Response("Method Not Allowed", {
|
|
32
35
|
status: 405,
|
|
@@ -37,12 +40,12 @@ function csrfProtection() {
|
|
|
37
40
|
await protect(event.request);
|
|
38
41
|
} catch (error) {
|
|
39
42
|
if (error instanceof SecurityCsrfError) {
|
|
40
|
-
return createCsrfErrorResponse(error);
|
|
43
|
+
return cors.apply(event.request, createCsrfErrorResponse(error));
|
|
41
44
|
}
|
|
42
45
|
throw error;
|
|
43
46
|
}
|
|
44
47
|
await issueCsrfCookie(event);
|
|
45
|
-
return resolve(event);
|
|
48
|
+
return cors.apply(event.request, await resolve(event));
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
var svelteKitSecurityInternals = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/security",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"description": "Holo-JS Framework - CSRF and rate-limit contracts, config, and runtime seams",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"test": "vitest --run --coverage"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@holo-js/config": "^0.3.
|
|
62
|
-
"@holo-js/kernel": "^0.3.
|
|
61
|
+
"@holo-js/config": "^0.3.20",
|
|
62
|
+
"@holo-js/kernel": "^0.3.20"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"h3": "^1.15.11",
|