File size: 3,642 Bytes
c592d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// micromatch is only available at node runtime, so it cannot be used here since the code path that calls this function
// can be run from edge. This is a simple implementation that safely achieves the required functionality.
// the goal is to match the functionality for remotePatterns as defined here -
// https://nextjs.org/docs/app/api-reference/components/image#remotepatterns
// TODO - retrofit micromatch to work in edge and use that instead
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "isCsrfOriginAllowed", {
    enumerable: true,
    get: function() {
        return isCsrfOriginAllowed;
    }
});
function matchWildcardDomain(domain, pattern) {
    // DNS names are case-insensitive per RFC 1035
    // Use ASCII-only toLowerCase to avoid unicode issues
    const normalizedDomain = domain.replace(/[A-Z]/g, (c)=>c.toLowerCase());
    const normalizedPattern = pattern.replace(/[A-Z]/g, (c)=>c.toLowerCase());
    const domainParts = normalizedDomain.split('.');
    const patternParts = normalizedPattern.split('.');
    if (patternParts.length < 1) {
        // pattern is empty and therefore invalid to match against
        return false;
    }
    if (domainParts.length < patternParts.length) {
        // domain has too few segments and thus cannot match
        return false;
    }
    // Prevent wildcards from matching entire domains (e.g. '**' or '*.com')
    // This ensures wildcards can only match subdomains, not the main domain
    if (patternParts.length === 1 && (patternParts[0] === '*' || patternParts[0] === '**')) {
        return false;
    }
    while(patternParts.length){
        const patternPart = patternParts.pop();
        const domainPart = domainParts.pop();
        switch(patternPart){
            case '':
                {
                    // invalid pattern. pattern segments must be non empty
                    return false;
                }
            case '*':
                {
                    // wildcard matches anything so we continue if the domain part is non-empty
                    if (domainPart) {
                        continue;
                    } else {
                        return false;
                    }
                }
            case '**':
                {
                    // if this is not the last item in the pattern the pattern is invalid
                    if (patternParts.length > 0) {
                        return false;
                    }
                    // recursive wildcard matches anything so we terminate here if the domain part is non empty
                    return domainPart !== undefined;
                }
            case undefined:
            default:
                {
                    if (domainPart !== patternPart) {
                        return false;
                    }
                }
        }
    }
    // We exhausted the pattern. If we also exhausted the domain we have a match
    return domainParts.length === 0;
}
const isCsrfOriginAllowed = (originDomain, allowedOrigins = [])=>{
    // DNS names are case-insensitive per RFC 1035
    // Use ASCII-only toLowerCase to avoid unicode issues
    const normalizedOrigin = originDomain.replace(/[A-Z]/g, (c)=>c.toLowerCase());
    return allowedOrigins.some((allowedOrigin)=>{
        if (!allowedOrigin) return false;
        const normalizedAllowed = allowedOrigin.replace(/[A-Z]/g, (c)=>c.toLowerCase());
        return normalizedAllowed === normalizedOrigin || matchWildcardDomain(originDomain, allowedOrigin);
    });
};

//# sourceMappingURL=csrf-protection.js.map