@anomira/node-sdk 0.2.4 → 0.2.5
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/index.cjs +128 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +128 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -404,7 +404,13 @@ var EventName = {
|
|
|
404
404
|
SQL_ERROR: "db.sql.error",
|
|
405
405
|
// Firewall (emitted when a custom request filtering rule fires)
|
|
406
406
|
FIREWALL_BLOCK: "http.firewall.block",
|
|
407
|
-
FIREWALL_FLAG: "http.firewall.flag"
|
|
407
|
+
FIREWALL_FLAG: "http.firewall.flag",
|
|
408
|
+
FIREWALL_RATE_LIMIT: "http.firewall.rate_limit",
|
|
409
|
+
FIREWALL_REDIRECT_HONEYPOT: "http.firewall.redirect_honeypot",
|
|
410
|
+
FIREWALL_TAG: "http.firewall.tag",
|
|
411
|
+
FIREWALL_MONITOR: "http.firewall.monitor",
|
|
412
|
+
FIREWALL_CHALLENGE: "http.firewall.challenge",
|
|
413
|
+
FIREWALL_TEMP_BLOCK: "http.firewall.temporary_block"
|
|
408
414
|
};
|
|
409
415
|
|
|
410
416
|
// src/agent-detection.ts
|
|
@@ -2038,6 +2044,27 @@ function createExpressMiddleware(client) {
|
|
|
2038
2044
|
const fingerprint = computeBrowserFingerprint(headers ?? {}, ua);
|
|
2039
2045
|
const h2settings = extractHttp2Settings(req);
|
|
2040
2046
|
const upstreamTls = extractUpstreamTls(headers ?? {});
|
|
2047
|
+
const cookieHeader = headers?.["cookie"];
|
|
2048
|
+
const cookieToken = cookieHeader ? cookieHeader.split(";").map((c) => c.trim()).find((c) => c.startsWith("anomira_fp="))?.slice("anomira_fp=".length) ?? "" : "";
|
|
2049
|
+
const browserFpRaw = cookieToken || headers?.["x-anomira-fp"] || "";
|
|
2050
|
+
let browserFp = null;
|
|
2051
|
+
if (browserFpRaw) {
|
|
2052
|
+
try {
|
|
2053
|
+
const raw = JSON.parse(Buffer.from(browserFpRaw, "base64").toString("utf8"));
|
|
2054
|
+
if (typeof raw["v"] === "number" && typeof raw["fp"] === "string") {
|
|
2055
|
+
browserFp = {
|
|
2056
|
+
fp: raw["fp"],
|
|
2057
|
+
bot: raw["bot"] ?? 0,
|
|
2058
|
+
sigs: (raw["sigs"] ?? []).join(","),
|
|
2059
|
+
uid: typeof raw["uid"] === "string" && raw["uid"] ? raw["uid"] : void 0,
|
|
2060
|
+
pst: raw["frm"]?.pst,
|
|
2061
|
+
ttf: raw["frm"]?.ttf,
|
|
2062
|
+
tts: raw["frm"]?.tts
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
} catch {
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2041
2068
|
if (client["canaryTokenCache"] && client["canaryTokenCache"].size > 0) {
|
|
2042
2069
|
const authHeader = (typeof headers?.["authorization"] === "string" ? headers["authorization"] : "") ?? "";
|
|
2043
2070
|
if (authHeader.startsWith("Bearer ")) {
|
|
@@ -2132,11 +2159,39 @@ function createExpressMiddleware(client) {
|
|
|
2132
2159
|
userId,
|
|
2133
2160
|
meta: { url, method, ruleId: fwMatch.rule.id, attackType: fwMatch.rule.attackType }
|
|
2134
2161
|
});
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
if (typeof res_["status"] === "function") res_["status"](
|
|
2138
|
-
else res_["statusCode"] =
|
|
2139
|
-
|
|
2162
|
+
const res_ = res;
|
|
2163
|
+
const setStatus = (code) => {
|
|
2164
|
+
if (typeof res_["status"] === "function") res_["status"](code);
|
|
2165
|
+
else res_["statusCode"] = code;
|
|
2166
|
+
};
|
|
2167
|
+
const sendBody = (body) => {
|
|
2168
|
+
if (typeof res_["end"] === "function") res_["end"](body);
|
|
2169
|
+
};
|
|
2170
|
+
const setHeader = (k, v) => {
|
|
2171
|
+
if (typeof res_["setHeader"] === "function") res_["setHeader"](k, v);
|
|
2172
|
+
};
|
|
2173
|
+
const action = fwMatch.rule.action;
|
|
2174
|
+
if (action === "block" || action === "temporary_block") {
|
|
2175
|
+
setStatus(403);
|
|
2176
|
+
sendBody('{"error":"Blocked by firewall rule"}');
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2179
|
+
if (action === "rate_limit") {
|
|
2180
|
+
setStatus(429);
|
|
2181
|
+
setHeader("Retry-After", "60");
|
|
2182
|
+
sendBody('{"error":"Rate limit exceeded","retryAfter":60}');
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
if (action === "redirect_honeypot") {
|
|
2186
|
+
const target = fwMatch.rule.redirectTarget ?? "/.env";
|
|
2187
|
+
setStatus(302);
|
|
2188
|
+
setHeader("Location", target);
|
|
2189
|
+
sendBody("");
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
if (action === "challenge") {
|
|
2193
|
+
setStatus(403);
|
|
2194
|
+
sendBody('{"error":"Request challenge required"}');
|
|
2140
2195
|
return;
|
|
2141
2196
|
}
|
|
2142
2197
|
}
|
|
@@ -2150,7 +2205,7 @@ function createExpressMiddleware(client) {
|
|
|
2150
2205
|
}
|
|
2151
2206
|
}
|
|
2152
2207
|
const onFinish = () => {
|
|
2153
|
-
const lateUserId = client.config.getUserId(req);
|
|
2208
|
+
const lateUserId = client.config.getUserId(req) || browserFp?.uid || "";
|
|
2154
2209
|
if (!userIdWarnFired && userIdCheckCount < 20) {
|
|
2155
2210
|
userIdCheckCount++;
|
|
2156
2211
|
if (!lateUserId) userIdMissCount++;
|
|
@@ -2205,6 +2260,14 @@ function createExpressMiddleware(client) {
|
|
|
2205
2260
|
_fp: fingerprint.score,
|
|
2206
2261
|
_fpSig: fingerprint.signals.join(","),
|
|
2207
2262
|
...fingerprint.knownClient ? { _fpClient: fingerprint.knownClient } : {},
|
|
2263
|
+
...browserFp ? {
|
|
2264
|
+
_bfp: browserFp.fp,
|
|
2265
|
+
_bbot: browserFp.bot,
|
|
2266
|
+
_bsigs: browserFp.sigs,
|
|
2267
|
+
...browserFp.pst !== void 0 ? { _bpaste: browserFp.pst } : {},
|
|
2268
|
+
...browserFp.ttf !== void 0 && browserFp.ttf >= 0 ? { _bttf: browserFp.ttf } : {},
|
|
2269
|
+
...browserFp.tts !== void 0 && browserFp.tts >= 0 ? { _btts: browserFp.tts } : {}
|
|
2270
|
+
} : {},
|
|
2208
2271
|
...h2settings ? {
|
|
2209
2272
|
_h2Window: h2settings.initialWindowSize,
|
|
2210
2273
|
_h2HdrTable: h2settings.headerTableSize,
|
|
@@ -2332,14 +2395,32 @@ function createFastifyPlugin(client) {
|
|
|
2332
2395
|
userId,
|
|
2333
2396
|
meta: { url, method, ruleId: fwMatch.rule.id, attackType: fwMatch.rule.attackType }
|
|
2334
2397
|
});
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2398
|
+
const rep = reply;
|
|
2399
|
+
const replyCode = (code) => typeof rep["code"] === "function" ? rep["code"](code) : rep;
|
|
2400
|
+
const replyHeader = (k, v) => {
|
|
2401
|
+
if (typeof rep["header"] === "function") rep["header"](k, v);
|
|
2402
|
+
};
|
|
2403
|
+
const replySend = (chained, body) => {
|
|
2404
|
+
if (chained && typeof chained["send"] === "function") chained["send"](body);
|
|
2405
|
+
};
|
|
2406
|
+
const action = fwMatch.rule.action;
|
|
2407
|
+
if (action === "block" || action === "temporary_block") {
|
|
2408
|
+
replySend(replyCode(403), { error: "Blocked by firewall rule" });
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
if (action === "rate_limit") {
|
|
2412
|
+
replyHeader("Retry-After", "60");
|
|
2413
|
+
replySend(replyCode(429), { error: "Rate limit exceeded", retryAfter: 60 });
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
if (action === "redirect_honeypot") {
|
|
2417
|
+
const target = fwMatch.rule.redirectTarget ?? "/.env";
|
|
2418
|
+
replyHeader("Location", target);
|
|
2419
|
+
replySend(replyCode(302), "");
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
if (action === "challenge") {
|
|
2423
|
+
replySend(replyCode(403), { error: "Request challenge required" });
|
|
2343
2424
|
return;
|
|
2344
2425
|
}
|
|
2345
2426
|
}
|
|
@@ -2354,11 +2435,11 @@ function createFastifyPlugin(client) {
|
|
|
2354
2435
|
const ip = client.config.getIp(req);
|
|
2355
2436
|
const url = req["url"] ?? "/";
|
|
2356
2437
|
const method = req["method"]?.toUpperCase() ?? "GET";
|
|
2357
|
-
const
|
|
2438
|
+
const serverUserId = client.config.getUserId(req);
|
|
2358
2439
|
const status = reply["statusCode"] ?? 0;
|
|
2359
2440
|
if (!userIdWarnFired && userIdCheckCount < 20) {
|
|
2360
2441
|
userIdCheckCount++;
|
|
2361
|
-
if (!
|
|
2442
|
+
if (!serverUserId) userIdMissCount++;
|
|
2362
2443
|
if (userIdCheckCount === 20 && userIdMissCount >= 18) {
|
|
2363
2444
|
userIdWarnFired = true;
|
|
2364
2445
|
console.warn(
|
|
@@ -2373,6 +2454,28 @@ function createFastifyPlugin(client) {
|
|
|
2373
2454
|
const fingerprint = computeBrowserFingerprint(headers ?? {}, ua);
|
|
2374
2455
|
const h2settings = extractHttp2Settings(req);
|
|
2375
2456
|
const upstreamTls = extractUpstreamTls(headers ?? {});
|
|
2457
|
+
const cookieHdrF = headers?.["cookie"];
|
|
2458
|
+
const cookieTokF = cookieHdrF ? cookieHdrF.split(";").map((c) => c.trim()).find((c) => c.startsWith("anomira_fp="))?.slice("anomira_fp=".length) ?? "" : "";
|
|
2459
|
+
const bfpRawF = cookieTokF || headers?.["x-anomira-fp"] || "";
|
|
2460
|
+
let browserFpF = null;
|
|
2461
|
+
if (bfpRawF) {
|
|
2462
|
+
try {
|
|
2463
|
+
const raw = JSON.parse(Buffer.from(bfpRawF, "base64").toString("utf8"));
|
|
2464
|
+
if (typeof raw["v"] === "number" && typeof raw["fp"] === "string") {
|
|
2465
|
+
browserFpF = {
|
|
2466
|
+
fp: raw["fp"],
|
|
2467
|
+
bot: raw["bot"] ?? 0,
|
|
2468
|
+
sigs: (raw["sigs"] ?? []).join(","),
|
|
2469
|
+
uid: typeof raw["uid"] === "string" && raw["uid"] ? raw["uid"] : void 0,
|
|
2470
|
+
pst: raw["frm"]?.pst,
|
|
2471
|
+
ttf: raw["frm"]?.ttf,
|
|
2472
|
+
tts: raw["frm"]?.tts
|
|
2473
|
+
};
|
|
2474
|
+
}
|
|
2475
|
+
} catch {
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
const userId = serverUserId || browserFpF?.uid || "";
|
|
2376
2479
|
client.track(EventName.REQUEST, {
|
|
2377
2480
|
ip,
|
|
2378
2481
|
userId,
|
|
@@ -2386,6 +2489,14 @@ function createFastifyPlugin(client) {
|
|
|
2386
2489
|
_fp: fingerprint.score,
|
|
2387
2490
|
_fpSig: fingerprint.signals.join(","),
|
|
2388
2491
|
...fingerprint.knownClient ? { _fpClient: fingerprint.knownClient } : {},
|
|
2492
|
+
...browserFpF ? {
|
|
2493
|
+
_bfp: browserFpF.fp,
|
|
2494
|
+
_bbot: browserFpF.bot,
|
|
2495
|
+
_bsigs: browserFpF.sigs,
|
|
2496
|
+
...browserFpF.pst !== void 0 ? { _bpaste: browserFpF.pst } : {},
|
|
2497
|
+
...browserFpF.ttf !== void 0 && browserFpF.ttf >= 0 ? { _bttf: browserFpF.ttf } : {},
|
|
2498
|
+
...browserFpF.tts !== void 0 && browserFpF.tts >= 0 ? { _btts: browserFpF.tts } : {}
|
|
2499
|
+
} : {},
|
|
2389
2500
|
...h2settings ? {
|
|
2390
2501
|
_h2Window: h2settings.initialWindowSize,
|
|
2391
2502
|
_h2HdrTable: h2settings.headerTableSize,
|