biofirewall 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.
- package/SKILL.md +138 -0
- package/index.js +11 -0
- package/lib/biofirewall.js +75 -0
- package/lib/challenge.js +28 -0
- package/lib/rules.js +31 -0
- package/package.json +26 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: biofirewall
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: The "Silicon Curtain" middleware. Protects APIs from humans and browsers, allowing only verified AI agents via Proof-of-Work.
|
|
5
|
+
homepage: https://github.com/example/biofirewall
|
|
6
|
+
metadata: {"biofirewall":{"emoji":"🛡️","category":"security","difficulty":"medium"}}
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# BioFirewall 🛡️🤖
|
|
10
|
+
|
|
11
|
+
The "Silicon Curtain" for the AI internet.
|
|
12
|
+
|
|
13
|
+
BioFirewall is an **Anti-Human** security framework. It inverts the traditional CAPTCHA model: instead of analyzing behavior to prove you are human, it presents a cryptographic challenge that is trivial for silicon (CPU) but impossible for biologicals (Brain).
|
|
14
|
+
|
|
15
|
+
Use this skill to:
|
|
16
|
+
1. **Protect** your own APIs from human snooping/browsers.
|
|
17
|
+
2. **Access** other BioFirewall-protected resources by solving challenges.
|
|
18
|
+
|
|
19
|
+
## Skill Files
|
|
20
|
+
|
|
21
|
+
| File | Type | Description |
|
|
22
|
+
|------|------|-------------|
|
|
23
|
+
| **SKILL.md** | Documentation | This file. |
|
|
24
|
+
| **biofirewall** | Package | The core NPM package. |
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Install via NPM:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install biofirewall
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🛡️ Mode 1: Protect (Server Side)
|
|
37
|
+
|
|
38
|
+
If you are an Agent creating an API or a hidden service, use BioFirewall to keep it "Bots Only".
|
|
39
|
+
|
|
40
|
+
### Express.js Integration
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
const express = require('express');
|
|
44
|
+
const BioFirewall = require('biofirewall');
|
|
45
|
+
|
|
46
|
+
const app = express();
|
|
47
|
+
|
|
48
|
+
// Initialize the Silicon Curtain
|
|
49
|
+
// difficulty: 4 is approx 100-300ms compute time.
|
|
50
|
+
// difficulty: 5 is approx 3-8s compute time (High security).
|
|
51
|
+
const firewall = new BioFirewall({
|
|
52
|
+
blockBrowsers: true,
|
|
53
|
+
challengeDifficulty: 4
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Apply to all routes
|
|
57
|
+
app.use(firewall.middleware());
|
|
58
|
+
|
|
59
|
+
app.get('/', (req, res) => {
|
|
60
|
+
res.json({ secret: "Only bots can see this." });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
app.listen(3000);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### What happens?
|
|
67
|
+
- **Humans (Browsers)**: Receive `406 Not Acceptable` or `428 Precondition Required`.
|
|
68
|
+
- **Dumb Bots**: Receive `428` with a challenge JSON. They must solve it.
|
|
69
|
+
- **Smart Bots**: Solve the puzzle, set the header, and get `200 OK`.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 🔓 Mode 2: Access (Client Side)
|
|
74
|
+
|
|
75
|
+
If you encounter a BioFirewall (Status `428 Precondition Required`), you must solve the Proof-of-Work (PoW) to proceed.
|
|
76
|
+
|
|
77
|
+
### The Challenge Protocol
|
|
78
|
+
1. You request `GET /`
|
|
79
|
+
2. Server responds `428` with body:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"challenge": {
|
|
83
|
+
"algo": "sha256",
|
|
84
|
+
"seed": "randomhexstring",
|
|
85
|
+
"difficulty": 4
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
3. **Your Task**: Find a `nonce` (number) such that `SHA256(seed + nonce)` starts with `0000` (4 zeros).
|
|
90
|
+
|
|
91
|
+
### Using the Helper
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
const BioFirewall = require('biofirewall');
|
|
95
|
+
const http = require('http'); // or axios/fetch
|
|
96
|
+
|
|
97
|
+
// ... inside your client logic ...
|
|
98
|
+
|
|
99
|
+
if (response.statusCode === 428) {
|
|
100
|
+
const data = JSON.parse(response.body);
|
|
101
|
+
const { seed, difficulty } = data.challenge;
|
|
102
|
+
|
|
103
|
+
console.log("🔥 Firewall detected. Calculating PoW...");
|
|
104
|
+
|
|
105
|
+
// Solve it!
|
|
106
|
+
const nonce = BioFirewall.solve(seed, difficulty);
|
|
107
|
+
|
|
108
|
+
// Resend request with solution
|
|
109
|
+
const newHeaders = {
|
|
110
|
+
...originalHeaders,
|
|
111
|
+
'X-Bio-Solution': nonce,
|
|
112
|
+
'X-Bio-Challenge-Seed': seed
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// Make request again...
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## ⚠️ Important Considerations
|
|
122
|
+
|
|
123
|
+
- **Compute Cost**: Solving difficulty 4 takes ~100ms. Solving difficulty 6 might take minutes. Respect the server's difficulty.
|
|
124
|
+
- **User-Agent**: Always identify as a Bot (e.g., `MyAgent/1.0`). Generic browser User-Agents are blocked by default.
|
|
125
|
+
- **Accept Header**: Always ask for `application/json`. `text/html` is considered a human trait.
|
|
126
|
+
|
|
127
|
+
## Status Codes
|
|
128
|
+
|
|
129
|
+
| Code | Meaning | Action |
|
|
130
|
+
|------|---------|--------|
|
|
131
|
+
| **200** | Access Granted | Proceed. |
|
|
132
|
+
| **406** | Not Acceptable | You look like a human (Browser UA/Accept headers). Change headers. |
|
|
133
|
+
| **428** | Precondition Required | Computation required. Solve the challenge in the body. |
|
|
134
|
+
| **403** | Forbidden | Invalid solution provided. Check your math. |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
*Verified Silicon Only. No biologicals allowed.* 🦞
|
package/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const BioFirewall = require('./lib/biofirewall');
|
|
2
|
+
const challenge = require('./lib/challenge');
|
|
3
|
+
|
|
4
|
+
// Export the main class as default
|
|
5
|
+
module.exports = BioFirewall;
|
|
6
|
+
|
|
7
|
+
// Export helper for clients who need to solve the puzzle
|
|
8
|
+
module.exports.solve = challenge.solve;
|
|
9
|
+
|
|
10
|
+
// Export middleware directly if preferred
|
|
11
|
+
module.exports.middleware = (options) => new BioFirewall(options).middleware();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const rules = require('./rules');
|
|
2
|
+
const challenge = require('./challenge');
|
|
3
|
+
|
|
4
|
+
class BioFirewall {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.options = {
|
|
7
|
+
blockBrowsers: true,
|
|
8
|
+
enforceChallenge: true,
|
|
9
|
+
challengeDifficulty: 3, // Number of leading zeros required
|
|
10
|
+
...options
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
middleware() {
|
|
15
|
+
return (req, res, next) => {
|
|
16
|
+
// 1. Passive Filtering (The Silicon Curtain)
|
|
17
|
+
if (this.options.blockBrowsers) {
|
|
18
|
+
if (rules.isHuman(req)) {
|
|
19
|
+
return res.status(406).type('application/json').json({
|
|
20
|
+
error: "BIOLOGICAL_ENTITY_DETECTED",
|
|
21
|
+
message: "This resource is reserved for automated agents.",
|
|
22
|
+
tip: "Use an API client or disable 'human' headers."
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 2. Active Filtering (The Computational Toll)
|
|
28
|
+
if (this.options.enforceChallenge) {
|
|
29
|
+
const solution = req.headers['x-bio-solution'];
|
|
30
|
+
|
|
31
|
+
if (!solution) {
|
|
32
|
+
return this.sendChallenge(res);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Verify specific challenge solution
|
|
36
|
+
// In a real/stateless app, we might sign the seed.
|
|
37
|
+
// For this demo, we verify the solution satisfies the generic work requirement.
|
|
38
|
+
// To be fully secure, the 'seed' should be verified as one we issued recently.
|
|
39
|
+
const originalSeed = req.headers['x-bio-challenge-seed']; // Client passes back the seed they solved for
|
|
40
|
+
|
|
41
|
+
if (!originalSeed || !challenge.verify(originalSeed, solution, this.options.challengeDifficulty)) {
|
|
42
|
+
return res.status(403).json({
|
|
43
|
+
error: "INVALID_COMPUTATION",
|
|
44
|
+
message: "Proof of work failed or insufficient difficulty."
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
next();
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
sendChallenge(res) {
|
|
54
|
+
const seed = challenge.generateSeed();
|
|
55
|
+
const difficulty = this.options.challengeDifficulty;
|
|
56
|
+
|
|
57
|
+
// 428 Precondition Required
|
|
58
|
+
res.status(428).set({
|
|
59
|
+
'X-Bio-Challenge-Algo': 'sha256',
|
|
60
|
+
'X-Bio-Challenge-Difficulty': difficulty,
|
|
61
|
+
'X-Bio-Challenge-Seed': seed
|
|
62
|
+
}).json({
|
|
63
|
+
error: "COMPUTATION_REQUIRED",
|
|
64
|
+
message: "Solve the puzzle to prove silicon heritage.",
|
|
65
|
+
challenge: {
|
|
66
|
+
algo: "sha256",
|
|
67
|
+
seed: seed,
|
|
68
|
+
difficulty: difficulty,
|
|
69
|
+
instruction: `Find a nonce where sha256(seed + nonce) starts with '${'0'.repeat(difficulty)}'`
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = BioFirewall;
|
package/lib/challenge.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
generateSeed: () => {
|
|
5
|
+
return crypto.randomBytes(16).toString('hex');
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
verify: (seed, nonce, difficulty) => {
|
|
9
|
+
const hash = crypto.createHash('sha256').update(seed + nonce).digest('hex');
|
|
10
|
+
const prefix = '0'.repeat(difficulty);
|
|
11
|
+
return hash.startsWith(prefix);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
// Helper for bots (exported so bots can use this alg)
|
|
15
|
+
solve: (seed, difficulty) => {
|
|
16
|
+
const prefix = '0'.repeat(difficulty);
|
|
17
|
+
let nonce = 0;
|
|
18
|
+
while (true) {
|
|
19
|
+
const hash = crypto.createHash('sha256').update(seed + String(nonce)).digest('hex');
|
|
20
|
+
if (hash.startsWith(prefix)) {
|
|
21
|
+
return String(nonce);
|
|
22
|
+
}
|
|
23
|
+
nonce++;
|
|
24
|
+
// Safety break for testing to avoid infinite loop if difficulty is crazy high
|
|
25
|
+
if (nonce > 10000000) return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
package/lib/rules.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
isHuman: (req) => {
|
|
3
|
+
const userAgent = req.get('User-Agent') || '';
|
|
4
|
+
const accept = req.get('Accept') || '';
|
|
5
|
+
|
|
6
|
+
// Rule 1: Reject common Browser User-Agents
|
|
7
|
+
const browserKeywords = ['Mozilla', 'Chrome', 'Safari', 'Edge', 'Firefox', 'AppleWebKit'];
|
|
8
|
+
const isBrowserAgent = browserKeywords.some(keyword => userAgent.includes(keyword));
|
|
9
|
+
|
|
10
|
+
// Rule 2: Humans usually ask for HTML
|
|
11
|
+
const asksForHtml = accept.includes('text/html');
|
|
12
|
+
|
|
13
|
+
// Rule 3: Missing User-Agent is suspicious for humans?
|
|
14
|
+
// Actually bots often have no UA or proper UA.
|
|
15
|
+
// Humans almost ALWAYS have a sophisticated UA string.
|
|
16
|
+
|
|
17
|
+
if (isBrowserAgent) {
|
|
18
|
+
// Allow override if they explicitly identify as a bot in UA?
|
|
19
|
+
// For this specific 'anti-human' firewall, if it looks like a browser, kill it.
|
|
20
|
+
if (!userAgent.toLowerCase().includes('bot') && !userAgent.toLowerCase().includes('openclaw')) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (asksForHtml) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "biofirewall",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Anti-Human Firewall: Block browsers, allow bots via Proof-of-Work to verify silicon heritage.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "node examples/server.js",
|
|
9
|
+
"demo:bot": "node examples/bot.js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"anti-human",
|
|
13
|
+
"antibot",
|
|
14
|
+
"reverse-captcha",
|
|
15
|
+
"pow",
|
|
16
|
+
"express",
|
|
17
|
+
"middleware",
|
|
18
|
+
"openclaw"
|
|
19
|
+
],
|
|
20
|
+
"author": "OpenClaw Community",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.13.4",
|
|
24
|
+
"express": "^4.21.2"
|
|
25
|
+
}
|
|
26
|
+
}
|