@prosopo/provider 4.15.13 → 4.15.15
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/.turbo/turbo-build$colon$cjs.log +106 -106
- package/.turbo/turbo-build$colon$tsc.log +24 -24
- package/.turbo/turbo-build.log +107 -104
- package/CHANGELOG.md +78 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/api/admin/apiAdminRoutesProvider.js +27 -46
- package/dist/api/admin/apiClearAllCountersEndpoint.js +62 -57
- package/dist/api/admin/apiDnsEventEndpoint.js +79 -92
- package/dist/api/admin/apiGetAllDecisionMachinesEndpoint.js +43 -45
- package/dist/api/admin/apiGetDecisionMachineEndpoint.js +40 -40
- package/dist/api/admin/apiRegisterSiteKeyEndpoint.js +23 -22
- package/dist/api/admin/apiRegisterSiteKeysEndpoint.js +26 -30
- package/dist/api/admin/apiRemoveAllDecisionMachinesEndpoint.js +35 -37
- package/dist/api/admin/apiRemoveDecisionMachineEndpoint.js +40 -40
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.d.ts.map +1 -1
- package/dist/api/admin/apiRemoveDetectorKeyEndpoint.js +29 -31
- package/dist/api/admin/apiRemoveSiteKeyEndpoint.js +33 -29
- package/dist/api/admin/apiRemoveSiteKeysEndpoint.js +32 -31
- package/dist/api/admin/apiToggleMaintenanceModeEndpoint.js +43 -35
- package/dist/api/admin/apiUpdateDecisionMachineEndpoint.js +43 -63
- package/dist/api/admin/apiUpdateDetectorKeyEndpoint.js +36 -35
- package/dist/api/admin/createApiAdminRoutesProvider.js +6 -8
- package/dist/api/blacklistRequestInspector.js +285 -377
- package/dist/api/block.js +17 -30
- package/dist/api/captcha/checkSpamEmail.js +88 -98
- package/dist/api/captcha/contextAwareValidation.js +21 -15
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.js +126 -140
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/constants.js +11 -12
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js +236 -299
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.js +10 -13
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/handler.js +336 -462
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.js +17 -14
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.js +27 -27
- package/dist/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.js +42 -63
- package/dist/api/captcha/getFrictionlessCaptchaChallenge.js +2 -4
- package/dist/api/captcha/getImageCaptchaChallenge.js +136 -207
- package/dist/api/captcha/getPoWCaptchaChallenge.js +128 -198
- package/dist/api/captcha/getPuzzleCaptchaChallenge.js +132 -201
- package/dist/api/captcha/maintenanceModeResponses.js +38 -47
- package/dist/api/captcha/submitImageCaptchaSolution.js +75 -101
- package/dist/api/captcha/submitPoWCaptchaSolution.js +137 -207
- package/dist/api/captcha/submitPuzzleCaptchaSolution.js +73 -105
- package/dist/api/captcha.js +76 -58
- package/dist/api/dnsEventUrl.js +20 -22
- package/dist/api/domainMiddleware.js +104 -115
- package/dist/api/forwardVerify.js +62 -48
- package/dist/api/handshakeTimingMiddleware.js +43 -62
- package/dist/api/hardBlockVerdictCache.js +114 -117
- package/dist/api/headerCheckMiddleware.js +34 -34
- package/dist/api/ignoreMiddleware.js +13 -15
- package/dist/api/ipInfoMiddleware.js +17 -19
- package/dist/api/ja4.js +149 -188
- package/dist/api/ja4Middleware.js +39 -54
- package/dist/api/metrics.js +245 -257
- package/dist/api/public.js +52 -54
- package/dist/api/robotsMiddleware.js +10 -10
- package/dist/api/startProviderApi.js +205 -232
- package/dist/api/testSiteKey.js +16 -16
- package/dist/api/validateAddress.js +23 -21
- package/dist/api/verify.js +334 -377
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/api/admin/apiAdminRoutesProvider.cjs +40 -59
- package/dist/cjs/api/admin/apiClearAllCountersEndpoint.cjs +63 -58
- package/dist/cjs/api/admin/apiDnsEventEndpoint.cjs +82 -93
- package/dist/cjs/api/admin/apiGetAllDecisionMachinesEndpoint.cjs +46 -48
- package/dist/cjs/api/admin/apiGetDecisionMachineEndpoint.cjs +41 -41
- package/dist/cjs/api/admin/apiRegisterSiteKeyEndpoint.cjs +25 -24
- package/dist/cjs/api/admin/apiRegisterSiteKeysEndpoint.cjs +28 -32
- package/dist/cjs/api/admin/apiRemoveAllDecisionMachinesEndpoint.cjs +38 -40
- package/dist/cjs/api/admin/apiRemoveDecisionMachineEndpoint.cjs +41 -41
- package/dist/cjs/api/admin/apiRemoveDetectorKeyEndpoint.cjs +31 -33
- package/dist/cjs/api/admin/apiRemoveSiteKeyEndpoint.cjs +35 -31
- package/dist/cjs/api/admin/apiRemoveSiteKeysEndpoint.cjs +34 -33
- package/dist/cjs/api/admin/apiToggleMaintenanceModeEndpoint.cjs +45 -35
- package/dist/cjs/api/admin/apiUpdateDecisionMachineEndpoint.cjs +45 -65
- package/dist/cjs/api/admin/apiUpdateDetectorKeyEndpoint.cjs +38 -37
- package/dist/cjs/api/admin/createApiAdminRoutesProvider.cjs +7 -8
- package/dist/cjs/api/blacklistRequestInspector.cjs +288 -376
- package/dist/cjs/api/block.cjs +18 -30
- package/dist/cjs/api/captcha/checkSpamEmail.cjs +90 -100
- package/dist/cjs/api/captcha/contextAwareValidation.cjs +21 -14
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/accessPolicy.cjs +125 -140
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/constants.cjs +10 -10
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.cjs +238 -301
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/decryptSimdReadings.cjs +9 -12
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/handler.cjs +349 -473
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/honeypotResponse.cjs +18 -14
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/sessionDedup.cjs +26 -26
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge/shortCircuit.cjs +42 -63
- package/dist/cjs/api/captcha/getFrictionlessCaptchaChallenge.cjs +2 -3
- package/dist/cjs/api/captcha/getImageCaptchaChallenge.cjs +138 -208
- package/dist/cjs/api/captcha/getPoWCaptchaChallenge.cjs +131 -200
- package/dist/cjs/api/captcha/getPuzzleCaptchaChallenge.cjs +135 -203
- package/dist/cjs/api/captcha/maintenanceModeResponses.cjs +38 -44
- package/dist/cjs/api/captcha/submitImageCaptchaSolution.cjs +77 -102
- package/dist/cjs/api/captcha/submitPoWCaptchaSolution.cjs +140 -209
- package/dist/cjs/api/captcha/submitPuzzleCaptchaSolution.cjs +76 -107
- package/dist/cjs/api/captcha.cjs +79 -58
- package/dist/cjs/api/dnsEventUrl.cjs +20 -21
- package/dist/cjs/api/domainMiddleware.cjs +106 -117
- package/dist/cjs/api/forwardVerify.cjs +63 -49
- package/dist/cjs/api/handshakeTimingMiddleware.cjs +43 -61
- package/dist/cjs/api/hardBlockVerdictCache.cjs +114 -114
- package/dist/cjs/api/headerCheckMiddleware.cjs +34 -34
- package/dist/cjs/api/ignoreMiddleware.cjs +12 -14
- package/dist/cjs/api/ipInfoMiddleware.cjs +16 -18
- package/dist/cjs/api/ja4.cjs +149 -187
- package/dist/cjs/api/ja4Middleware.cjs +40 -53
- package/dist/cjs/api/metrics.cjs +229 -228
- package/dist/cjs/api/public.cjs +57 -57
- package/dist/cjs/api/robotsMiddleware.cjs +9 -9
- package/dist/cjs/api/startProviderApi.cjs +219 -237
- package/dist/cjs/api/testSiteKey.cjs +15 -14
- package/dist/cjs/api/validateAddress.cjs +24 -21
- package/dist/cjs/api/verify.cjs +338 -379
- package/dist/cjs/compositeIpAddress.cjs +40 -47
- package/dist/cjs/index.cjs +65 -71
- package/dist/cjs/pairs.cjs +31 -35
- package/dist/cjs/rules/lang.cjs +10 -14
- package/dist/cjs/schedulers/captchaScheduler.cjs +26 -32
- package/dist/cjs/schedulers/getClientList.cjs +35 -33
- package/dist/cjs/schedulers/setClientEntropy.cjs +35 -33
- package/dist/cjs/schedulers/updateSpamEmailDomains.cjs +39 -43
- package/dist/cjs/services/ipComparison.cjs +122 -119
- package/dist/cjs/tasks/captchaManager.cjs +407 -486
- package/dist/cjs/tasks/client/clientTasks.cjs +347 -470
- package/dist/cjs/tasks/dataset/datasetTasks.cjs +25 -29
- package/dist/cjs/tasks/dataset/datasetTasksUtils.cjs +16 -32
- package/dist/cjs/tasks/decisionMachine/decisionMachineRunner.cjs +220 -307
- package/dist/cjs/tasks/detection/decodeBehavior.cjs +408 -317
- package/dist/cjs/tasks/detection/decodePayload.cjs +686 -468
- package/dist/cjs/tasks/detection/decodeSimd.cjs +462 -304
- package/dist/cjs/tasks/detection/getBotScore.cjs +37 -43
- package/dist/cjs/tasks/dnsEvent/enrichDnsEvent.cjs +88 -71
- package/dist/cjs/tasks/frictionless/frictionlessTasks.cjs +348 -486
- package/dist/cjs/tasks/frictionless/frictionlessTasksUtils.cjs +13 -30
- package/dist/cjs/tasks/frictionless/routingMachine.cjs +71 -55
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs +555 -806
- package/dist/cjs/tasks/imgCaptcha/imgCaptchaTasksUtils.cjs +22 -23
- package/dist/cjs/tasks/index.cjs +2 -4
- package/dist/cjs/tasks/powCaptcha/powTasks.cjs +491 -687
- package/dist/cjs/tasks/powCaptcha/powTasksUtils.cjs +17 -29
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasks.cjs +422 -591
- package/dist/cjs/tasks/puzzleCaptcha/puzzleTasksUtils.cjs +8 -5
- package/dist/cjs/tasks/spam/checkSpamEmail.cjs +133 -141
- package/dist/cjs/tasks/spam/checkTrafficFilter.cjs +118 -76
- package/dist/cjs/tasks/spam/evaluateEmailSpamRules.cjs +75 -84
- package/dist/cjs/tasks/spam/updateSpamEmailDomains.cjs +40 -56
- package/dist/cjs/tasks/tasks.cjs +107 -158
- package/dist/cjs/util/usageCounters.cjs +220 -211
- package/dist/cjs/util.cjs +329 -359
- package/dist/cjs/utils/devicePlatform.cjs +14 -8
- package/dist/cjs/utils/dns.cjs +68 -93
- package/dist/cjs/utils/hashUserAgent.cjs +14 -7
- package/dist/cjs/utils/hashUserIp.cjs +14 -6
- package/dist/cjs/utils/honeypot/encoders.cjs +74 -80
- package/dist/cjs/utils/honeypot/phraseBank.cjs +51 -44
- package/dist/cjs/utils/normalizeRequestIp.cjs +33 -25
- package/dist/compositeIpAddress.js +38 -46
- package/dist/index.js +12 -56
- package/dist/pairs.js +31 -37
- package/dist/rules/lang.js +11 -15
- package/dist/schedulers/captchaScheduler.js +25 -31
- package/dist/schedulers/getClientList.js +34 -32
- package/dist/schedulers/setClientEntropy.js +34 -32
- package/dist/schedulers/updateSpamEmailDomains.js +38 -42
- package/dist/services/ipComparison.js +122 -119
- package/dist/tasks/captchaManager.js +403 -483
- package/dist/tasks/client/clientTasks.js +343 -467
- package/dist/tasks/dataset/datasetTasks.js +24 -28
- package/dist/tasks/dataset/datasetTasksUtils.js +15 -31
- package/dist/tasks/decisionMachine/decisionMachineRunner.js +217 -306
- package/dist/tasks/detection/getBotScore.js +37 -43
- package/dist/tasks/dnsEvent/enrichDnsEvent.d.ts.map +1 -1
- package/dist/tasks/dnsEvent/enrichDnsEvent.js +88 -74
- package/dist/tasks/dnsEvent/enrichDnsEvent.js.map +1 -1
- package/dist/tasks/frictionless/frictionlessTasks.js +342 -479
- package/dist/tasks/frictionless/frictionlessTasksUtils.js +14 -32
- package/dist/tasks/frictionless/routingMachine.js +72 -56
- package/dist/tasks/imgCaptcha/imgCaptchaTasks.js +550 -801
- package/dist/tasks/imgCaptcha/imgCaptchaTasksUtils.js +21 -22
- package/dist/tasks/index.js +1 -3
- package/dist/tasks/powCaptcha/powTasks.d.ts.map +1 -1
- package/dist/tasks/powCaptcha/powTasks.js +486 -682
- package/dist/tasks/powCaptcha/powTasks.js.map +1 -1
- package/dist/tasks/powCaptcha/powTasksUtils.js +15 -28
- package/dist/tasks/puzzleCaptcha/puzzleTasks.d.ts.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js +417 -586
- package/dist/tasks/puzzleCaptcha/puzzleTasks.js.map +1 -1
- package/dist/tasks/puzzleCaptcha/puzzleTasksUtils.js +9 -6
- package/dist/tasks/spam/checkSpamEmail.js +133 -141
- package/dist/tasks/spam/checkTrafficFilter.d.ts +1 -0
- package/dist/tasks/spam/checkTrafficFilter.d.ts.map +1 -1
- package/dist/tasks/spam/checkTrafficFilter.js +117 -77
- package/dist/tasks/spam/checkTrafficFilter.js.map +1 -1
- package/dist/tasks/spam/evaluateEmailSpamRules.js +75 -86
- package/dist/tasks/spam/updateSpamEmailDomains.js +36 -54
- package/dist/tasks/tasks.js +98 -150
- package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js +4 -1
- package/dist/tests/integration/api/blacklistRequestInspector.integration.test.js.map +1 -1
- package/dist/tests/unit/api/block.unit.test.js +8 -4
- package/dist/tests/unit/api/block.unit.test.js.map +1 -1
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js +8 -6
- package/dist/tests/unit/api/captcha/maintenanceModeShortCircuit.unit.test.js.map +1 -1
- package/dist/tests/unit/api/forwardVerify.unit.test.js +3 -1
- package/dist/tests/unit/api/forwardVerify.unit.test.js.map +1 -1
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js +15 -7
- package/dist/tests/unit/api/getFrictionlessCaptchaChallenge.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js +24 -18
- package/dist/tests/unit/schedulers/captchaScheduler.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/getClientList.unit.test.js +19 -13
- package/dist/tests/unit/schedulers/getClientList.unit.test.js.map +1 -1
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js +19 -13
- package/dist/tests/unit/schedulers/setClientEntropy.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/client/clientTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js +22 -16
- package/dist/tests/unit/tasks/imgCaptcha/imgCaptchaTasksUtils.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js +6 -0
- package/dist/tests/unit/tasks/powCaptcha/powTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js +60 -1
- package/dist/tests/unit/tasks/puzzleCaptcha/puzzleTasks.unit.test.js.map +1 -1
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js +140 -0
- package/dist/tests/unit/tasks/spam/checkTrafficFilter.unit.test.js.map +1 -1
- package/dist/tests/unit/testUtils/mockProviderEnv.d.ts +7 -7
- package/dist/util/usageCounters.js +220 -212
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +327 -364
- package/dist/util.js.map +1 -1
- package/dist/utils/devicePlatform.js +15 -9
- package/dist/utils/dns.js +64 -77
- package/dist/utils/hashUserAgent.js +14 -7
- package/dist/utils/hashUserIp.js +14 -6
- package/dist/utils/honeypot/encoders.js +74 -80
- package/dist/utils/honeypot/phraseBank.js +49 -44
- package/dist/utils/normalizeRequestIp.js +34 -26
- package/package.json +24 -24
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
//#region src/tasks/puzzleCaptcha/puzzleTasksUtils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Validate that the puzzle solution is within tolerance of the target.
|
|
4
|
+
* Uses Euclidean distance.
|
|
5
|
+
*/
|
|
6
|
+
var validatePuzzleSolution = (finalX, finalY, targetX, targetY, tolerance) => {
|
|
7
|
+
return Math.sqrt((finalX - targetX) ** 2 + (finalY - targetY) ** 2) <= tolerance;
|
|
6
8
|
};
|
|
9
|
+
//#endregion
|
|
7
10
|
exports.validatePuzzleSolution = validatePuzzleSolution;
|
|
@@ -1,146 +1,138 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const require_dns = require("../../utils/dns.cjs");
|
|
2
|
+
let _prosopo_util = require("@prosopo/util");
|
|
3
|
+
//#region src/tasks/spam/checkSpamEmail.ts
|
|
4
|
+
/**
|
|
5
|
+
* Extracts the domain from a URL or returns the input if it's already a domain
|
|
6
|
+
*/
|
|
5
7
|
function extractDomain(urlOrDomain) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} catch {
|
|
12
|
-
return urlOrDomain;
|
|
13
|
-
}
|
|
8
|
+
try {
|
|
9
|
+
return new URL(urlOrDomain.startsWith("http") ? urlOrDomain : `https://${urlOrDomain}`).hostname;
|
|
10
|
+
} catch {
|
|
11
|
+
return urlOrDomain;
|
|
12
|
+
}
|
|
14
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Checks if an email domain is spam by checking against a spam list,
|
|
16
|
+
* performing DNS/redirect/TLS-related checks.
|
|
17
|
+
*/
|
|
15
18
|
async function checkSpamEmail(email, db, config, logger) {
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
} catch (error) {
|
|
136
|
-
logger.warn(() => ({
|
|
137
|
-
msg: "Failed to check spam email domain for MX record",
|
|
138
|
-
error,
|
|
139
|
-
mxDomain
|
|
140
|
-
}));
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return false;
|
|
19
|
+
const normalizedDomain = (0, _prosopo_util.extractDomainFromEmail)(email);
|
|
20
|
+
if (!normalizedDomain) return true;
|
|
21
|
+
try {
|
|
22
|
+
const record = await db.getSpamEmailDomain(normalizedDomain);
|
|
23
|
+
if (record !== null && record !== void 0) return true;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
logger.warn(() => ({
|
|
26
|
+
msg: "Failed to check spam email domain",
|
|
27
|
+
error
|
|
28
|
+
}));
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const domainValidation = (0, _prosopo_util.validateDomainForOutboundRequest)(normalizedDomain);
|
|
32
|
+
if (!domainValidation.isValid) {
|
|
33
|
+
logger.warn(() => ({
|
|
34
|
+
msg: "Email domain failed SSRF validation, rejecting",
|
|
35
|
+
domain: normalizedDomain,
|
|
36
|
+
reason: domainValidation.reason
|
|
37
|
+
}));
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
let dnsCheckResult = null;
|
|
41
|
+
try {
|
|
42
|
+
dnsCheckResult = await require_dns.runDnsChecks(normalizedDomain, { dnsServers: config?.dnsServers });
|
|
43
|
+
} catch (error) {
|
|
44
|
+
logger.warn(() => ({
|
|
45
|
+
msg: "Failed to run DNS checks",
|
|
46
|
+
error,
|
|
47
|
+
domain: normalizedDomain
|
|
48
|
+
}));
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (dnsCheckResult.redirectResult.tlsError) logger.info(() => ({
|
|
52
|
+
msg: "Email domain apex has TLS error — observed, not treated as spam",
|
|
53
|
+
domain: normalizedDomain
|
|
54
|
+
}));
|
|
55
|
+
if (dnsCheckResult.redirectResult.redirectUrl) {
|
|
56
|
+
const redirectUrl = dnsCheckResult.redirectResult.redirectUrl;
|
|
57
|
+
const redirectDomain = extractDomain(redirectUrl).toLowerCase().trim();
|
|
58
|
+
logger.info(() => ({
|
|
59
|
+
msg: "Email domain has HTTP redirect",
|
|
60
|
+
domain: normalizedDomain,
|
|
61
|
+
redirectDomain
|
|
62
|
+
}));
|
|
63
|
+
try {
|
|
64
|
+
const record = await db.getSpamEmailDomain(redirectDomain);
|
|
65
|
+
if (record !== null && record !== void 0) return true;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
logger.warn(() => ({
|
|
68
|
+
msg: "Failed to check spam email domain for redirect",
|
|
69
|
+
error,
|
|
70
|
+
redirectDomain
|
|
71
|
+
}));
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
} else if (dnsCheckResult.cnameResult && dnsCheckResult.cnameResult.length > 0) {
|
|
75
|
+
const firstCname = dnsCheckResult.cnameResult[0];
|
|
76
|
+
if (!firstCname) {
|
|
77
|
+
logger.warn(() => ({
|
|
78
|
+
msg: "CNAME result array has undefined element",
|
|
79
|
+
domain: normalizedDomain
|
|
80
|
+
}));
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const cnameDomain = firstCname.replace(/\.$/, "").toLowerCase().trim();
|
|
84
|
+
logger.info(() => ({
|
|
85
|
+
msg: "Email domain has CNAME",
|
|
86
|
+
domain: normalizedDomain,
|
|
87
|
+
cnameDomain
|
|
88
|
+
}));
|
|
89
|
+
try {
|
|
90
|
+
const record = await db.getSpamEmailDomain(cnameDomain);
|
|
91
|
+
if (record !== null && record !== void 0) return true;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logger.warn(() => ({
|
|
94
|
+
msg: "Failed to check spam email domain for CNAME",
|
|
95
|
+
error,
|
|
96
|
+
cnameDomain
|
|
97
|
+
}));
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
} else if (dnsCheckResult.mxRecordResult && dnsCheckResult.mxRecordResult.length > 0) {
|
|
101
|
+
const firstMxRecord = dnsCheckResult.mxRecordResult[0];
|
|
102
|
+
if (!firstMxRecord || !firstMxRecord.exchange) {
|
|
103
|
+
logger.warn(() => ({
|
|
104
|
+
msg: "MX record result array has undefined element or exchange",
|
|
105
|
+
domain: normalizedDomain
|
|
106
|
+
}));
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const mxDomain = firstMxRecord.exchange.replace(/\.$/, "").toLowerCase().trim();
|
|
110
|
+
logger.info(() => ({
|
|
111
|
+
msg: "Email domain has MX record",
|
|
112
|
+
domain: normalizedDomain,
|
|
113
|
+
mxDomain,
|
|
114
|
+
priority: firstMxRecord.priority
|
|
115
|
+
}));
|
|
116
|
+
try {
|
|
117
|
+
const record = await db.getSpamEmailDomain(mxDomain);
|
|
118
|
+
if (record !== null && record !== void 0) {
|
|
119
|
+
logger.warn(() => ({
|
|
120
|
+
msg: "Email domain MX record points to spam domain",
|
|
121
|
+
domain: normalizedDomain,
|
|
122
|
+
mxDomain
|
|
123
|
+
}));
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
logger.warn(() => ({
|
|
128
|
+
msg: "Failed to check spam email domain for MX record",
|
|
129
|
+
error,
|
|
130
|
+
mxDomain
|
|
131
|
+
}));
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
145
136
|
}
|
|
137
|
+
//#endregion
|
|
146
138
|
exports.checkSpamEmail = checkSpamEmail;
|
|
@@ -1,81 +1,123 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (candidates.length === 0) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
const normalisedAllowlist = allowlist.map(
|
|
22
|
-
(entry) => entry.trim().toLowerCase()
|
|
23
|
-
);
|
|
24
|
-
return candidates.some((c) => normalisedAllowlist.includes(c));
|
|
1
|
+
let _prosopo_types = require("@prosopo/types");
|
|
2
|
+
//#region src/tasks/spam/checkTrafficFilter.ts
|
|
3
|
+
var matchesDatacenterNameList = (ipInfo, list) => {
|
|
4
|
+
if (!list || list.length === 0) return false;
|
|
5
|
+
const candidates = [];
|
|
6
|
+
for (const value of [
|
|
7
|
+
ipInfo.datacenterName,
|
|
8
|
+
ipInfo.providerName,
|
|
9
|
+
ipInfo.asnOrganization
|
|
10
|
+
]) {
|
|
11
|
+
if (typeof value !== "string") continue;
|
|
12
|
+
const trimmed = value.trim().toLowerCase();
|
|
13
|
+
if (trimmed) candidates.push(trimmed);
|
|
14
|
+
}
|
|
15
|
+
if (candidates.length === 0) return false;
|
|
16
|
+
const normalisedList = list.map((entry) => entry.trim().toLowerCase());
|
|
17
|
+
return candidates.some((c) => normalisedList.includes(c));
|
|
25
18
|
};
|
|
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
|
-
|
|
19
|
+
var isDatacenterAllowlisted = (ipInfo, allowlist) => matchesDatacenterNameList(ipInfo, allowlist);
|
|
20
|
+
var isDatacenterDenylisted = (ipInfo, denylist) => matchesDatacenterNameList(ipInfo, denylist);
|
|
21
|
+
var evaluateIpInfo = (ipInfo, trafficFilter, isDnsExtra = false) => {
|
|
22
|
+
if (!ipInfo || !ipInfo.isValid) return { isBlocked: false };
|
|
23
|
+
if (trafficFilter.blockVpn && ipInfo.isVPN) return {
|
|
24
|
+
isBlocked: true,
|
|
25
|
+
reason: _prosopo_types.ResultReason.VPN_BLOCKED
|
|
26
|
+
};
|
|
27
|
+
if (trafficFilter.blockProxy && ipInfo.isProxy) return {
|
|
28
|
+
isBlocked: true,
|
|
29
|
+
reason: _prosopo_types.ResultReason.PROXY_BLOCKED
|
|
30
|
+
};
|
|
31
|
+
if (trafficFilter.blockTor && ipInfo.isTor) return {
|
|
32
|
+
isBlocked: true,
|
|
33
|
+
reason: _prosopo_types.ResultReason.TOR_BLOCKED
|
|
34
|
+
};
|
|
35
|
+
if ((trafficFilter.blockAbuser ?? true) && ipInfo.isAbuser) {
|
|
36
|
+
const threshold = trafficFilter.abuserScoreThreshold ?? _prosopo_types.trafficFilterAbuserScoreThresholdDefault;
|
|
37
|
+
if (Math.max(ipInfo.abuserScore ?? 0, ipInfo.companyAbuserScore ?? 0) >= threshold) return {
|
|
38
|
+
isBlocked: true,
|
|
39
|
+
reason: _prosopo_types.ResultReason.ABUSER_BLOCKED
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const datacenterSuppressedByCategory = ipInfo.isVPN && !trafficFilter.blockVpn || ipInfo.isProxy && !trafficFilter.blockProxy || ipInfo.isTor && !trafficFilter.blockTor || ipInfo.isCrawler && !trafficFilter.blockCrawler;
|
|
43
|
+
if (trafficFilter.blockDatacenter && ipInfo.isDatacenter) {
|
|
44
|
+
if (isDatacenterDenylisted(ipInfo, trafficFilter.datacenterNameDenylist)) return {
|
|
45
|
+
isBlocked: true,
|
|
46
|
+
reason: _prosopo_types.ResultReason.DATACENTER_BLOCKED
|
|
47
|
+
};
|
|
48
|
+
if (ipInfo.providerType !== "isp" && !datacenterSuppressedByCategory && !isDatacenterAllowlisted(ipInfo, trafficFilter.datacenterNameAllowlist)) return {
|
|
49
|
+
isBlocked: true,
|
|
50
|
+
reason: _prosopo_types.ResultReason.DATACENTER_BLOCKED
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (trafficFilter.blockMobile && ipInfo.isMobile) return {
|
|
54
|
+
isBlocked: true,
|
|
55
|
+
reason: _prosopo_types.ResultReason.MOBILE_BLOCKED
|
|
56
|
+
};
|
|
57
|
+
if (trafficFilter.blockSatellite && ipInfo.isSatellite) return {
|
|
58
|
+
isBlocked: true,
|
|
59
|
+
reason: _prosopo_types.ResultReason.SATELLITE_BLOCKED
|
|
60
|
+
};
|
|
61
|
+
if (!isDnsExtra && trafficFilter.blockCrawler && ipInfo.isCrawler) return {
|
|
62
|
+
isBlocked: true,
|
|
63
|
+
reason: _prosopo_types.ResultReason.CRAWLER_BLOCKED
|
|
64
|
+
};
|
|
65
|
+
return { isBlocked: false };
|
|
63
66
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Checks whether a request should be blocked based on traffic filter
|
|
69
|
+
* settings and the request's already-resolved IP info (attached to
|
|
70
|
+
* `req.ipInfo` by `ipInfoMiddleware`). Each filter (VPN, proxy, Tor,
|
|
71
|
+
* abuser, etc.) is evaluated independently. A missing or invalid
|
|
72
|
+
* `ipInfo` falls back to "not blocked" so an outage in the upstream
|
|
73
|
+
* service can't block all traffic.
|
|
74
|
+
*
|
|
75
|
+
* Cross-filter rule: the datacenter rule is suppressed when the IP
|
|
76
|
+
* carries a more specific category the operator has left unblocked —
|
|
77
|
+
* VPN, proxy, Tor, or crawler. All four legitimately sit on datacenter
|
|
78
|
+
* infrastructure, so "block datacenters" (a scraping rule) shouldn't
|
|
79
|
+
* catch them out the back door. Applies to primary and DNS extras.
|
|
80
|
+
*
|
|
81
|
+
* Extras-only rule: the crawler check is skipped on DNS extras. Public
|
|
82
|
+
* DNS resolvers share IP space with search crawlers.
|
|
83
|
+
*
|
|
84
|
+
* The datacenter rule also honours `datacenterNameAllowlist`: consumer
|
|
85
|
+
* relays route through datacenter ranges and are reported as
|
|
86
|
+
* `is_datacenter=true` by upstream but the exiting users are real humans.
|
|
87
|
+
* Operators can list the datacenter, provider, or ASN organisation names
|
|
88
|
+
* they want to allow through — see `isDatacenterAllowlisted`.
|
|
89
|
+
*
|
|
90
|
+
* The datacenter rule also short-circuits when upstream classifies the
|
|
91
|
+
* provider as an ISP (`providerType === "isp"`). Consumer ISPs like
|
|
92
|
+
* Afrihost, Comcast, or BT are sometimes flagged `is_datacenter=true` by
|
|
93
|
+
* upstream heuristics — usually because part of the ASN hosts B2B or
|
|
94
|
+
* hosting services — but the eyeball ranges behind those ASNs carry
|
|
95
|
+
* ordinary end-users. The ISP categorisation is stronger evidence of
|
|
96
|
+
* consumer traffic than the datacenter boolean.
|
|
97
|
+
*
|
|
98
|
+
* The ISP short-circuit and the allowlist are both overridden by
|
|
99
|
+
* `datacenterNameDenylist`: if the IP's `datacenterName`, `providerName`,
|
|
100
|
+
* or `asnOrganization` matches a denylist entry, the block fires. This
|
|
101
|
+
* lets operators opt named providers (for example IP-leasing platforms
|
|
102
|
+
* whose ranges are announced from carrier ASNs but exit as proxy pools)
|
|
103
|
+
* back into the datacenter rule.
|
|
104
|
+
*
|
|
105
|
+
* When `trafficFilter.skipExtrasOnValidDnsPath` is on and the catcher
|
|
106
|
+
* confirmed the DNS path matched the connection path (`pathValid: true`),
|
|
107
|
+
* the extras evaluation is skipped. This stops public-DoH resolver IPs
|
|
108
|
+
* from tripping the datacenter rule for ordinary users.
|
|
109
|
+
*/
|
|
110
|
+
var checkTrafficFilter = (ipInfo, trafficFilter, extraIpInfos, dnsPathValid) => {
|
|
111
|
+
const primary = evaluateIpInfo(ipInfo, trafficFilter);
|
|
112
|
+
if (primary.isBlocked) return primary;
|
|
113
|
+
if (trafficFilter.skipExtrasOnValidDnsPath && dnsPathValid === true) return { isBlocked: false };
|
|
114
|
+
for (const extra of extraIpInfos ?? []) {
|
|
115
|
+
const result = evaluateIpInfo(extra, trafficFilter, true);
|
|
116
|
+
if (result.isBlocked) return result;
|
|
117
|
+
}
|
|
118
|
+
return { isBlocked: false };
|
|
79
119
|
};
|
|
120
|
+
//#endregion
|
|
80
121
|
exports.checkTrafficFilter = checkTrafficFilter;
|
|
81
122
|
exports.isDatacenterAllowlisted = isDatacenterAllowlisted;
|
|
123
|
+
exports.isDatacenterDenylisted = isDatacenterDenylisted;
|