capjs-core 0.1.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capjs-core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Stateless server-side challenge generator and verifier for Cap, a lightweight, modern open-source CAPTCHA alternative. No storage, no filesystem - bring your own.",
5
5
  "keywords": [
6
6
  "anti-abuse",
package/src/index.js CHANGED
@@ -27,13 +27,9 @@ export {
27
27
 
28
28
  const DEFAULT_RSW_T = 75_000;
29
29
 
30
- // Cache the minter on the keypair object identity, keyed by t. Callers who
31
- // pass the same `keypair` object back across requests get zero per-call
32
- // overhead beyond the mint itself.
33
- const _minterCache = new WeakMap(); // keypair → Map<t, minter>
30
+ const _minterCache = new WeakMap();
34
31
 
35
32
  function resolveRswMinter(opts) {
36
- // explicit minter takes precedence (existing API)
37
33
  if (opts.rsw && typeof opts.rsw.mint === "function") return opts.rsw;
38
34
 
39
35
  if (!opts.keypair) {
@@ -42,13 +38,10 @@ function resolveRswMinter(opts) {
42
38
  );
43
39
  }
44
40
 
45
- // Normalize: serialized (strings) → BigInt
46
41
  const kp = typeof opts.keypair.N === "string"
47
42
  ? deserializeRswKeypair(opts.keypair)
48
43
  : opts.keypair;
49
44
 
50
- // Memoize {keypair, t} → minter. Reuses the precomputed h across calls so
51
- // the first request after boot is the only one that pays the ~5 ms setup.
52
45
  const t = opts.t ?? DEFAULT_RSW_T;
53
46
  let byT = _minterCache.get(opts.keypair);
54
47
  if (!byT) {
@@ -151,6 +151,25 @@ const DOC_PROP_MARKERS = [
151
151
  "__webdriver_script_func",
152
152
  "__webdriver_script_function",
153
153
  ];
154
+ const NAV_OWN_PROP_MARKERS = [
155
+ "webdriver",
156
+ "userAgent",
157
+ "appVersion",
158
+ "userAgentData",
159
+ "platform",
160
+ "vendor",
161
+ "product",
162
+ "productSub",
163
+ "languages",
164
+ "language",
165
+ "plugins",
166
+ "mimeTypes",
167
+ "hardwareConcurrency",
168
+ "deviceMemory",
169
+ "maxTouchPoints",
170
+ "permissions",
171
+ "connection",
172
+ ];
154
173
  const ATTR_SUBSTRING_MARKERS = ["selenium", "webdriver", "driver"];
155
174
  const STACK_SUBSTRING_MARKERS = ["pptr:", "UtilityScript.", "PhantomJS"];
156
175
  const WINDOW_PREFIX_MARKERS = ["puppeteer_", "cdc_", "$cdc_"];
@@ -179,6 +198,7 @@ function hashWith(seed) {
179
198
  function buildBlockChecks(b, id, hF, hSet, h) {
180
199
  const winHashes = WINDOW_PROP_MARKERS.map(h);
181
200
  const docHashes = DOC_PROP_MARKERS.map(h);
201
+ const navOwnHashes = NAV_OWN_PROP_MARKERS.map(h);
182
202
  const attrSubHashes = ATTR_SUBSTRING_MARKERS.map(h);
183
203
  const stackSubHashes = STACK_SUBSTRING_MARKERS.map(h);
184
204
  const winPrefixHashes = WINDOW_PREFIX_MARKERS.map(h);
@@ -187,16 +207,19 @@ function buildBlockChecks(b, id, hF, hSet, h) {
187
207
  const webglRendererHash = h(WEBGL_RENDERER_MARKER);
188
208
  const productSubGeckoHash = h(PRODUCTSUB_GECKO);
189
209
  const sequentumHash = h(SEQUENTUM_MARKER);
190
-
210
+
191
211
  const checks = [];
192
212
 
193
213
  checks.push(
194
214
  `if (!${b}) { try { var d = Object.getOwnPropertyDescriptors(navigator); var __wh = ${h("webdriver")}; for (const k in d) { if (${hF}(k) === __wh) { ${b} = true; break; } } if (!${b}) { var p = Object.getPrototypeOf(navigator); while (p && !${b}) { for (const k of Object.getOwnPropertyNames(p)) { if (${hF}(k) === __wh) { try { if (navigator[k]) ${b} = true; } catch {} break; } } p = Object.getPrototypeOf(p); } } } catch { ${b} = true; } }`,
195
215
  );
196
216
 
197
- checks.push(
198
- `if (!${b} && Object.getOwnPropertyNames(navigator).length !== 0) ${b} = true;`,
199
- );
217
+ {
218
+ const a = rVar();
219
+ checks.push(
220
+ `if (!${b}) { try { var ${a} = ${JSON.stringify(navOwnHashes)}; for (const k of Object.getOwnPropertyNames(navigator)) { if (${hSet}(${a}, ${hF}(k))) { ${b} = true; break; } } } catch { ${b} = true; } }`,
221
+ );
222
+ }
200
223
 
201
224
  {
202
225
  const a = rVar();