UNPKG

2.04 kB JavaScript View Raw
1/**
2 * react-router v8.3.1
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11//#region lib/actions.ts
12function throwIfPotentialCSRFAttack(request, allowedActionOrigins) {
13 let originHeader = request.headers.get("origin");
14 let originDomain = null;
15 let originUrl = null;
16 try {
17 if (typeof originHeader === "string" && originHeader !== "null") {
18 originUrl = new URL(originHeader);
19 originDomain = originUrl.host;
20 } else originDomain = originHeader;
21 } catch {
22 throw new Error(`\`origin\` header is not a valid URL. Aborting the action.`);
23 }
24 let requestUrl = new URL(request.url);
25 let originMatchesRequest = originUrl ? originUrl.origin === requestUrl.origin : originDomain === requestUrl.host;
26 if (originDomain && !originMatchesRequest) {
27 if (!isAllowedOrigin(originDomain, allowedActionOrigins)) throw new Error("The `request.url` origin does not match `origin` header from a forwarded action request. Aborting the action.");
28 }
29}
30function matchWildcardDomain(domain, pattern) {
31 const domainParts = domain.split(".");
32 const patternParts = pattern.split(".");
33 if (patternParts.length < 1) return false;
34 if (domainParts.length < patternParts.length) return false;
35 while (patternParts.length) {
36 const patternPart = patternParts.pop();
37 const domainPart = domainParts.pop();
38 switch (patternPart) {
39 case "": return false;
40 case "*": if (domainPart) continue;
41 else return false;
42 case "**":
43 if (patternParts.length > 0) return false;
44 return domainPart !== void 0;
45 case void 0:
46 default: if (domainPart !== patternPart) return false;
47 }
48 }
49 return domainParts.length === 0;
50}
51function isAllowedOrigin(originDomain, allowedActionOrigins = []) {
52 return allowedActionOrigins.some((allowedOrigin) => allowedOrigin && (allowedOrigin === originDomain || matchWildcardDomain(originDomain, allowedOrigin)));
53}
54//#endregion
55export { throwIfPotentialCSRFAttack };