bot-shield 1.0.0

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.
Files changed (3) hide show
  1. package/README.md +53 -0
  2. package/index.js +94 -0
  3. package/package.json +20 -0
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # BotShield Middleware
2
+
3
+ An Economic Deterrence Bot Mitigation Middleware for Express/Node.js based on V8 Javascript cryptographic token challenges.
4
+
5
+ This package protects your valuable API endpoints by filtering out automated scrapers and bots trying to steal data, while allowing legitimate human browsers to seamlessly access the content.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install bot-shield-mca
11
+ ```
12
+
13
+ ## Basic Usage
14
+
15
+ ```javascript
16
+ const express = require('express');
17
+ const BotShield = require('bot-shield-mca');
18
+
19
+ const app = express();
20
+ const botShield = new BotShield({
21
+ riskThreshold: 70, // Blocking threshold (default 70)
22
+ maxRequestsPerWindow: 50, // Rate limiting volume
23
+ minTimeBetweenRequestsMs: 200 // Velocity tracking
24
+ });
25
+
26
+ // 1. Expose the challenge token endpoint
27
+ app.get('/api/bot-challenge', botShield.challengeEndpoint);
28
+
29
+ // 2. Protect your valuable data API with the middleware
30
+ app.get('/api/data', botShield.protectApi, (req, res) => {
31
+ res.json({ message: "Protected data payload!" });
32
+ });
33
+
34
+ app.listen(3000);
35
+ ```
36
+
37
+ ## Frontend Integration (The X-BOT-SIGNAL)
38
+
39
+ Legitimate browsers must solve the execution challenge to retrieve the token and present it in the headers (`X-shield-token`) to access the protected JSON payload.
40
+
41
+ ```javascript
42
+ // Step 1: Challenge
43
+ const challenge = await fetch('http://localhost:3000/api/bot-challenge');
44
+ const { token } = await challenge.json();
45
+
46
+ // Step 2: Retrieve protected data
47
+ const response = await fetch('http://localhost:3000/api/data', {
48
+ headers: {
49
+ 'x-shield-token': token
50
+ }
51
+ });
52
+ const data = await response.json();
53
+ ```
package/index.js ADDED
@@ -0,0 +1,94 @@
1
+ const crypto = require('crypto');
2
+
3
+ class BotShield {
4
+ constructor(options = {}) {
5
+ this.riskThreshold = options.riskThreshold || 70;
6
+ this.timeWindowMs = options.timeWindowMs || 60000;
7
+ this.maxRequestsPerWindow = options.maxRequestsPerWindow || 50;
8
+ this.minTimeBetweenRequestsMs = options.minTimeBetweenRequestsMs || 200;
9
+
10
+ this.clients = new Map();
11
+ this.validTokens = new Set();
12
+ }
13
+
14
+ challengeEndpoint = (req, res) => {
15
+ const token = crypto.randomBytes(16).toString('hex');
16
+ this.validTokens.add(token);
17
+ setTimeout(() => this.validTokens.delete(token), 5 * 60 * 1000);
18
+ res.json({ token });
19
+ };
20
+
21
+ _getClientData(ip) {
22
+ if (!this.clients.has(ip)) {
23
+ this.clients.set(ip, {
24
+ requestCount: 0,
25
+ lastRequestTime: Date.now(),
26
+ firstRequestTime: Date.now()
27
+ });
28
+ }
29
+ return this.clients.get(ip);
30
+ }
31
+
32
+ _calculateRiskScore(clientData, hasValidToken, timeSinceLastRequest) {
33
+ let score = 0;
34
+ const signals = {};
35
+
36
+ if (!hasValidToken) {
37
+ score += 75;
38
+ signals.jsExecuted = false;
39
+ } else {
40
+ signals.jsExecuted = true;
41
+ }
42
+
43
+ if (timeSinceLastRequest < this.minTimeBetweenRequestsMs) {
44
+ score += 30;
45
+ signals.suspiciousTiming = true;
46
+ }
47
+
48
+ if (clientData.requestCount > this.maxRequestsPerWindow) {
49
+ score += 40;
50
+ signals.highVolume = true;
51
+ }
52
+
53
+ return { score, signals };
54
+ }
55
+
56
+ protectApi = (req, res, next) => {
57
+ const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
58
+ const clientToken = req.headers['x-shield-token'];
59
+ const now = Date.now();
60
+
61
+ const clientData = this._getClientData(ip);
62
+ const timeSinceLastRequest = now - clientData.lastRequestTime;
63
+ const hasValidToken = this.validTokens.has(clientToken);
64
+
65
+ if (now - clientData.firstRequestTime > this.timeWindowMs) {
66
+ clientData.requestCount = 0;
67
+ clientData.firstRequestTime = now;
68
+ }
69
+
70
+ clientData.requestCount += 1;
71
+ clientData.lastRequestTime = now;
72
+
73
+ const { score, signals } = this._calculateRiskScore(clientData, hasValidToken, timeSinceLastRequest);
74
+
75
+ if (score >= this.riskThreshold) {
76
+ console.log("\n" + "X".repeat(60));
77
+ console.log("🚨 [THREAT INTERCEPTED] 🚨");
78
+ console.log(`[!] Target: ${req.originalUrl} | IP: ${ip} | Risk Score: ${score}/100`);
79
+ console.log(`[!] Primary Reason: X-BOT-SIGNAL Missing`);
80
+ console.log("X".repeat(60));
81
+
82
+ return res.status(403).json({
83
+ error: "Access Denied",
84
+ code: "SHIELD_ERR",
85
+ message: "Verification Required. Unverified client behavior detected."
86
+ });
87
+ }
88
+
89
+ this.clients.set(ip, clientData);
90
+ next();
91
+ };
92
+ }
93
+
94
+ module.exports = BotShield;
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "bot-shield",
3
+ "version": "1.0.0",
4
+ "description": "An Economic Deterrence Bot Mitigation Middleware for Express",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [
10
+ "bot-protection",
11
+ "middleware",
12
+ "express",
13
+ "security",
14
+ "bot-shield",
15
+ "rate-limiting",
16
+ "economic-deterrence"
17
+ ],
18
+ "author": "Your Name",
19
+ "license": "ISC"
20
+ }