@ingram-tech/bot-protection 0.1.0 → 0.1.2
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/token.d.ts +5 -1
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +10 -2
- package/dist/token.js.map +1 -1
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +8 -3
- package/dist/verify.js.map +1 -1
- package/package.json +5 -1
package/dist/token.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Mint a token. Call server-side when rendering the form. If
|
|
3
|
+
* BOT_PROTECTION_SECRET isn't configured, returns "" (the timing layer is
|
|
4
|
+
* disabled) rather than throwing, so a misconfigured site still works.
|
|
5
|
+
*/
|
|
2
6
|
export declare const createFormToken: () => string;
|
|
3
7
|
export interface TokenCheck {
|
|
4
8
|
/** Reject submissions faster than this (default 2000ms — bots are instant). */
|
package/dist/token.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAYA
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAO,MASlC,CAAC;AAEF,MAAM,WAAW,UAAU;IAC1B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6EAA6E;AAC7E,eAAO,MAAM,eAAe,GAC3B,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI,EAChC,mBAA0C,UAAe,KACvD,WAqBF,CAAC"}
|
package/dist/token.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
-
import { getSecret } from "./keys";
|
|
2
|
+
import { getSecret, isConfigured } from "./keys";
|
|
3
3
|
/**
|
|
4
4
|
* Signed timing token: `<timestamp>.<hmac>`. The timestamp records when the
|
|
5
5
|
* form was rendered; the HMAC (keyed by BOT_PROTECTION_SECRET) prevents a bot
|
|
6
6
|
* from forging an older timestamp to defeat the "submitted too fast" check.
|
|
7
7
|
*/
|
|
8
8
|
const sign = (ts, secret) => createHmac("sha256", secret).update(ts).digest("hex");
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Mint a token. Call server-side when rendering the form. If
|
|
11
|
+
* BOT_PROTECTION_SECRET isn't configured, returns "" (the timing layer is
|
|
12
|
+
* disabled) rather than throwing, so a misconfigured site still works.
|
|
13
|
+
*/
|
|
10
14
|
export const createFormToken = () => {
|
|
15
|
+
if (!isConfigured()) {
|
|
16
|
+
console.warn("@ingram-tech/bot-protection: BOT_PROTECTION_SECRET not set — timing token disabled.");
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
11
19
|
const ts = Date.now().toString();
|
|
12
20
|
return `${ts}.${sign(ts, getSecret())}`;
|
|
13
21
|
};
|
package/dist/token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEjD;;;;GAIG;AAEH,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,MAAc,EAAU,EAAE,CACnD,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE;IAC3C,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CACX,qFAAqF,CACrF,CAAC;QACF,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IACjC,OAAO,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AACzC,CAAC,CAAC;AAcF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,KAAgC,EAChC,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,KAAiB,EAAE,EAC3C,EAAE;IAChB,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAE1D,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC9D,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC7E,IAAI,OAAO,GAAG,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC9D,IAAI,OAAO,GAAG,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAE7D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACrB,CAAC,CAAC"}
|
package/dist/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAmB,MAAM,SAAS,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC7B,0DAA0D;IAC1D,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAUD;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAAU,SAAS,aAAa,KAAG,OAAO,CAAC,YAAY,CAqB9E,CAAC"}
|
package/dist/verify.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { checkBot } from "./botid";
|
|
2
2
|
import { HONEYPOT_FIELD, TOKEN_FIELD } from "./fields";
|
|
3
|
+
import { isConfigured } from "./keys";
|
|
3
4
|
import { verifyFormToken } from "./token";
|
|
4
5
|
const getField = (formData, name) => {
|
|
5
6
|
const value = formData instanceof FormData
|
|
@@ -21,9 +22,13 @@ export const verifyHuman = async (options) => {
|
|
|
21
22
|
if (getField(options.formData, HONEYPOT_FIELD).trim() !== "") {
|
|
22
23
|
return { ok: false, reason: "honeypot" };
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// Timing layer only applies when a secret is configured; otherwise it's
|
|
26
|
+
// disabled (honeypot + BotID still run) so a misconfigured site keeps working.
|
|
27
|
+
if (isConfigured()) {
|
|
28
|
+
const token = verifyFormToken(getField(options.formData, TOKEN_FIELD), options.timing);
|
|
29
|
+
if (!token.ok)
|
|
30
|
+
return token;
|
|
31
|
+
}
|
|
27
32
|
if (options.botid !== false) {
|
|
28
33
|
const { isBot } = await checkBot();
|
|
29
34
|
if (isBot)
|
package/dist/verify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAmB,eAAe,EAAE,MAAM,SAAS,CAAC;AAiB3D,MAAM,QAAQ,GAAG,CAAC,QAAmC,EAAE,IAAY,EAAU,EAAE;IAC9E,MAAM,KAAK,GACV,QAAQ,YAAY,QAAQ;QAC3B,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QACpB,CAAC,CAAE,QAAoC,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAsB,EAAyB,EAAE;IAClF,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GAAG,eAAe,CAC5B,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,EACvC,OAAO,CAAC,MAAM,CACd,CAAC;
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAmB,eAAe,EAAE,MAAM,SAAS,CAAC;AAiB3D,MAAM,QAAQ,GAAG,CAAC,QAAmC,EAAE,IAAY,EAAU,EAAE;IAC9E,MAAM,KAAK,GACV,QAAQ,YAAY,QAAQ;QAC3B,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QACpB,CAAC,CAAE,QAAoC,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAsB,EAAyB,EAAE;IAClF,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC1C,CAAC;IAED,wEAAwE;IACxE,+EAA+E;IAC/E,IAAI,YAAY,EAAE,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,eAAe,CAC5B,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,EACvC,OAAO,CAAC,MAAM,CACd,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACnC,IAAI,KAAK;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACrB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingram-tech/bot-protection",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Invisible, layered bot protection for forms — honeypot + signed timing token + Vercel BotID.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"./honeypot": {
|
|
24
24
|
"types": "./dist/honeypot.d.ts",
|
|
25
25
|
"import": "./dist/honeypot.js"
|
|
26
|
+
},
|
|
27
|
+
"./fields": {
|
|
28
|
+
"types": "./dist/fields.d.ts",
|
|
29
|
+
"import": "./dist/fields.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
|
28
32
|
"scripts": {
|