yakmesh 2.8.2 → 3.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/CHANGELOG.md +637 -0
- package/CONTRIBUTING.md +42 -0
- package/Caddyfile +77 -0
- package/README.md +119 -29
- package/adapters/adapter-mlv-bible/README.md +124 -0
- package/adapters/adapter-mlv-bible/index.js +400 -0
- package/adapters/chat-mod-adapter.js +532 -0
- package/adapters/content-adapter.js +273 -0
- package/content/api.js +50 -41
- package/content/index.js +2 -2
- package/content/store.js +355 -173
- package/dashboard/index.html +19 -3
- package/database/replication.js +117 -37
- package/docs/CRYPTO-AGILITY.md +204 -0
- package/docs/MTLS-RESEARCH.md +367 -0
- package/docs/NAMCHE-SPEC.md +681 -0
- package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
- package/docs/PRECISION-DISCLOSURE.md +96 -0
- package/docs/README.md +76 -0
- package/docs/ROADMAP-2.4.0.md +447 -0
- package/docs/ROADMAP-2.5.0.md +244 -0
- package/docs/SECURITY-AUDIT-REPORT.md +306 -0
- package/docs/SST-INTEGRATION.md +712 -0
- package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
- package/docs/TERNARY-AUDIT-REPORT.md +247 -0
- package/docs/TME-FAQ.md +221 -0
- package/docs/WHITEPAPER.md +623 -0
- package/docs/adapters.html +1001 -0
- package/docs/advanced-systems.html +1045 -0
- package/docs/annex.html +1046 -0
- package/docs/api.html +970 -0
- package/docs/business/response-templates.md +160 -0
- package/docs/c2c.html +1225 -0
- package/docs/cli.html +1332 -0
- package/docs/configuration.html +1248 -0
- package/docs/darshan.html +1085 -0
- package/docs/dharma.html +966 -0
- package/docs/docs-bundle.html +1075 -0
- package/docs/docs.css +3120 -0
- package/docs/docs.js +556 -0
- package/docs/doko.html +969 -0
- package/docs/geo-proof.html +858 -0
- package/docs/getting-started.html +840 -0
- package/docs/gumba-tutorial.html +1144 -0
- package/docs/gumba.html +1098 -0
- package/docs/index.html +914 -0
- package/docs/jhilke.html +1312 -0
- package/docs/karma.html +1100 -0
- package/docs/katha.html +1037 -0
- package/docs/lama.html +978 -0
- package/docs/mandala.html +1067 -0
- package/docs/mani.html +964 -0
- package/docs/mantra.html +967 -0
- package/docs/mesh.html +1409 -0
- package/docs/nakpak.html +869 -0
- package/docs/namche.html +928 -0
- package/docs/nav-order.json +53 -0
- package/docs/prahari.html +1043 -0
- package/docs/prism-bash.min.js +1 -0
- package/docs/prism-javascript.min.js +1 -0
- package/docs/prism-json.min.js +1 -0
- package/docs/prism-tomorrow.min.css +1 -0
- package/docs/prism.min.js +1 -0
- package/docs/privacy.html +699 -0
- package/docs/quick-reference.html +1181 -0
- package/docs/sakshi.html +1402 -0
- package/docs/sandboxing.md +386 -0
- package/docs/seva.html +911 -0
- package/docs/sherpa.html +871 -0
- package/docs/studio.html +860 -0
- package/docs/stupa.html +995 -0
- package/docs/tailwind.min.css +2 -0
- package/docs/tattva.html +1332 -0
- package/docs/terms.html +686 -0
- package/docs/time-server-deployment.md +166 -0
- package/docs/time-sources.html +1392 -0
- package/docs/tivra.html +1127 -0
- package/docs/trademark-policy.html +686 -0
- package/docs/tribhuj.html +1183 -0
- package/docs/trust-security.html +1029 -0
- package/docs/tutorials/backup-recovery.html +654 -0
- package/docs/tutorials/dashboard.html +604 -0
- package/docs/tutorials/domain-setup.html +605 -0
- package/docs/tutorials/host-website.html +456 -0
- package/docs/tutorials/mesh-network.html +505 -0
- package/docs/tutorials/mobile-access.html +445 -0
- package/docs/tutorials/privacy.html +467 -0
- package/docs/tutorials/raspberry-pi.html +600 -0
- package/docs/tutorials/security-basics.html +539 -0
- package/docs/tutorials/share-files.html +431 -0
- package/docs/tutorials/troubleshooting.html +637 -0
- package/docs/tutorials/trust-karma.html +419 -0
- package/docs/tutorials/yak-protocol.html +456 -0
- package/docs/tutorials.html +1034 -0
- package/docs/vani.html +1270 -0
- package/docs/webserver.html +809 -0
- package/docs/yak-protocol.html +940 -0
- package/docs/yak-timeserver-design.md +475 -0
- package/docs/yakapp.html +1015 -0
- package/docs/ypc27.html +1069 -0
- package/docs/yurt.html +1344 -0
- package/embedded-docs/bundle.js +334 -74
- package/gossip/protocol.js +247 -27
- package/identity/key-resolver.js +262 -0
- package/identity/machine-seed.js +632 -0
- package/identity/node-key.js +669 -368
- package/identity/tribhuj-ratchet.js +506 -0
- package/knowledge-base.js +37 -8
- package/launcher/yakmesh.bat +62 -0
- package/launcher/yakmesh.sh +70 -0
- package/mesh/annex.js +462 -108
- package/mesh/beacon-broadcast.js +113 -1
- package/mesh/darshan.js +1718 -0
- package/mesh/gumba.js +1567 -0
- package/mesh/jhilke.js +651 -0
- package/mesh/katha.js +1012 -0
- package/mesh/nakpak-routing.js +8 -5
- package/mesh/network.js +724 -34
- package/mesh/pulse-sync.js +4 -1
- package/mesh/rate-limiter.js +127 -15
- package/mesh/seva.js +526 -0
- package/mesh/sherpa-discovery.js +89 -8
- package/mesh/sybil-defense.js +19 -5
- package/mesh/temporal-encoder.js +4 -3
- package/mesh/vani.js +1364 -0
- package/mesh/yurt.js +1340 -0
- package/models/entropy-sentinel.onnx +0 -0
- package/models/karma-trust.onnx +0 -0
- package/models/manifest.json +43 -0
- package/models/sakshi-anomaly.onnx +0 -0
- package/oracle/code-proof-protocol.js +7 -6
- package/oracle/codebase-lock.js +257 -28
- package/oracle/index.js +74 -15
- package/oracle/ma902-snmp.js +678 -0
- package/oracle/module-sealer.js +5 -3
- package/oracle/network-identity.js +16 -0
- package/oracle/packet-checksum.js +201 -0
- package/oracle/sst.js +579 -0
- package/oracle/ternary-144t.js +714 -0
- package/oracle/ternary-ml.js +481 -0
- package/oracle/time-api.js +239 -0
- package/oracle/time-source.js +137 -47
- package/oracle/validation-oracle-hardened.js +1111 -1071
- package/oracle/validation-oracle.js +4 -2
- package/oracle/ypc27.js +211 -0
- package/package.json +20 -3
- package/protocol/yak-handler.js +35 -9
- package/protocol/yak-protocol.js +28 -13
- package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
- package/reference/cpp/yakmesh_ypc27.cpp +179 -0
- package/sbom.json +87 -0
- package/scripts/security-audit.mjs +264 -0
- package/scripts/update-docs-nav.js +194 -0
- package/scripts/update-docs-sidebar.cjs +164 -0
- package/security/crypto-config.js +4 -3
- package/security/dharma-moderation.js +517 -0
- package/security/doko-identity.js +193 -143
- package/security/domain-consensus.js +86 -85
- package/security/fs-hardening.js +620 -0
- package/security/hardware-attestation.js +5 -3
- package/security/hybrid-trust.js +227 -87
- package/security/karma-rate-limiter.js +692 -0
- package/security/khata-protocol.js +22 -21
- package/security/khata-trust-integration.js +277 -150
- package/security/memory-safety.js +635 -0
- package/security/mesh-auth.js +11 -10
- package/security/mesh-revocation.js +373 -5
- package/security/namche-gateway.js +298 -69
- package/security/sakshi.js +460 -3
- package/security/sangha.js +770 -0
- package/security/secure-config.js +473 -0
- package/security/silicon-parity.js +13 -10
- package/security/steadywatch.js +1142 -0
- package/security/strike-system.js +32 -3
- package/security/temporal-signing.js +488 -0
- package/security/trit-commitment.js +464 -0
- package/server/crypto/annex.js +247 -0
- package/server/darshan-api.js +343 -0
- package/server/index.js +3259 -362
- package/server/komm-api.js +668 -0
- package/utils/accel.js +2273 -0
- package/utils/ternary-id.js +79 -0
- package/utils/verify-worker.js +57 -0
- package/webserver/index.js +95 -5
- package/assets/yakmesh-logo.png +0 -0
- package/assets/yakmesh-logo.svg +0 -80
- package/assets/yakmesh-logo2.png +0 -0
- package/assets/yakmesh-logo2sm.png +0 -0
- package/assets/ymsm.png +0 -0
- package/website/assets/silhouettes/adapters.svg +0 -107
- package/website/assets/silhouettes/api-endpoints.svg +0 -115
- package/website/assets/silhouettes/atomic-clock.svg +0 -83
- package/website/assets/silhouettes/base-camp.svg +0 -81
- package/website/assets/silhouettes/bridge.svg +0 -69
- package/website/assets/silhouettes/docs-bundle.svg +0 -113
- package/website/assets/silhouettes/doko-basket.svg +0 -70
- package/website/assets/silhouettes/fortress.svg +0 -93
- package/website/assets/silhouettes/gateway.svg +0 -54
- package/website/assets/silhouettes/gears.svg +0 -93
- package/website/assets/silhouettes/globe-satellite.svg +0 -67
- package/website/assets/silhouettes/karma-wheel.svg +0 -137
- package/website/assets/silhouettes/lama-council.svg +0 -141
- package/website/assets/silhouettes/mandala-network.svg +0 -169
- package/website/assets/silhouettes/mani-stones.svg +0 -149
- package/website/assets/silhouettes/mantra-wheel.svg +0 -116
- package/website/assets/silhouettes/mesh-nodes.svg +0 -113
- package/website/assets/silhouettes/nakpak.svg +0 -56
- package/website/assets/silhouettes/peak-lightning.svg +0 -73
- package/website/assets/silhouettes/sherpa.svg +0 -69
- package/website/assets/silhouettes/stupa-tower.svg +0 -119
- package/website/assets/silhouettes/tattva-eye.svg +0 -78
- package/website/assets/silhouettes/terminal.svg +0 -74
- package/website/assets/silhouettes/webserver.svg +0 -145
- package/website/assets/silhouettes/yak.svg +0 -78
- package/website/assets/yakmesh-logo.png +0 -0
- package/website/assets/yakmesh-logo.webp +0 -0
- package/website/assets/yakmesh-logo128x140.webp +0 -0
- package/website/assets/yakmesh-logo2.png +0 -0
- package/website/assets/yakmesh-logo2.svg +0 -51
- package/website/assets/yakmesh-logo40x44.webp +0 -0
- package/website/assets/yakmesh.gif +0 -0
- package/website/assets/yakmesh.ico +0 -0
- package/website/assets/yakmesh.jpg +0 -0
- package/website/assets/yakmesh.pdf +0 -0
- package/website/assets/yakmesh.png +0 -0
- package/website/assets/yakmesh.svg +0 -70
- package/website/assets/yakmesh128.webp +0 -0
- package/website/assets/yakmesh32.png +0 -0
- package/website/assets/yakmesh32.svg +0 -65
- package/website/assets/yakmesh32o.ico +0 -2
- package/website/assets/yakmesh32o.svg +0 -65
- package/website/assets/yakmesh32o.svgz +0 -0
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yakmesh Memory Safety — Circulating Canaries
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
* PHILOSOPHY: MEMORY AS LIVING TISSUE
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* Traditional memory safety: Static analysis, bounds checking, fuzzing.
|
|
9
|
+
* Circulating Canaries: Runtime memory integrity that flows through SANGHA.
|
|
10
|
+
*
|
|
11
|
+
* A CANARY is a strategically-placed memory region with known content.
|
|
12
|
+
* During SANGHA circulation, canaries are checksummed and attested.
|
|
13
|
+
* Corruption (buffer overflow, use-after-free exploit) is detected
|
|
14
|
+
* within one circulation cycle.
|
|
15
|
+
*
|
|
16
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
17
|
+
* CANARY TYPES
|
|
18
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
19
|
+
*
|
|
20
|
+
* 1. STACK CANARIES — Placed in hot function frames
|
|
21
|
+
* Node.js doesn't give direct stack access, so we use proxy objects
|
|
22
|
+
* that live on the JS heap but represent "stack-like" volatile state.
|
|
23
|
+
*
|
|
24
|
+
* 2. HEAP CANARIES — Typed arrays with known patterns
|
|
25
|
+
* These catch heap corruption from native modules (ONNX Runtime, etc.)
|
|
26
|
+
*
|
|
27
|
+
* 3. BUFFER CANARIES — Boundaries around shared ArrayBuffers
|
|
28
|
+
* Detect out-of-bounds writes in Worker-shared memory.
|
|
29
|
+
*
|
|
30
|
+
* 4. CLOSURE CANARIES — Captured variables in long-lived closures
|
|
31
|
+
* Detect corruption of closure state (rare but severe).
|
|
32
|
+
*
|
|
33
|
+
* @module security/memory-safety
|
|
34
|
+
* @version 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { createLogger } from '../utils/logger.js';
|
|
38
|
+
import { sha3_256 } from '../utils/accel.js';
|
|
39
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
40
|
+
import { randomBytes } from 'crypto';
|
|
41
|
+
import { EventEmitter } from 'events';
|
|
42
|
+
|
|
43
|
+
const log = createLogger('security:memory-safety');
|
|
44
|
+
|
|
45
|
+
// =============================================================================
|
|
46
|
+
// CONSTANTS
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
/** Canary types */
|
|
50
|
+
export const CANARY_TYPE = Object.freeze({
|
|
51
|
+
HEAP: 'HEAP', // Typed array with known pattern
|
|
52
|
+
BUFFER: 'BUFFER', // ArrayBuffer boundary markers
|
|
53
|
+
CLOSURE: 'CLOSURE', // Closure variable integrity
|
|
54
|
+
NATIVE: 'NATIVE', // Native module interface canary
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/** Default canary pattern size */
|
|
58
|
+
const CANARY_SIZE = 256;
|
|
59
|
+
|
|
60
|
+
/** Canary check interval (during SANGHA circulation) */
|
|
61
|
+
const DEFAULT_CHECK_INTERVAL_MS = 5000;
|
|
62
|
+
|
|
63
|
+
// =============================================================================
|
|
64
|
+
// CANARY
|
|
65
|
+
// =============================================================================
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Canary — A memory integrity checkpoint
|
|
69
|
+
*
|
|
70
|
+
* Each canary:
|
|
71
|
+
* - Holds a known pattern in memory
|
|
72
|
+
* - Computes a baseline hash at creation
|
|
73
|
+
* - Verifies integrity during circulation
|
|
74
|
+
*/
|
|
75
|
+
export class Canary {
|
|
76
|
+
#id;
|
|
77
|
+
#type;
|
|
78
|
+
#data;
|
|
79
|
+
#baselineHash;
|
|
80
|
+
#createdAt;
|
|
81
|
+
#lastCheck;
|
|
82
|
+
#checkCount;
|
|
83
|
+
#corrupted;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {string} id - Unique canary identifier
|
|
87
|
+
* @param {string} type - Canary type (HEAP/BUFFER/CLOSURE/NATIVE)
|
|
88
|
+
* @param {number} size - Size in bytes
|
|
89
|
+
*/
|
|
90
|
+
constructor(id, type = CANARY_TYPE.HEAP, size = CANARY_SIZE) {
|
|
91
|
+
this.#id = id;
|
|
92
|
+
this.#type = type;
|
|
93
|
+
this.#data = new Uint8Array(size);
|
|
94
|
+
this.#createdAt = Date.now();
|
|
95
|
+
this.#lastCheck = 0;
|
|
96
|
+
this.#checkCount = 0;
|
|
97
|
+
this.#corrupted = false;
|
|
98
|
+
|
|
99
|
+
// Fill with cryptographically random pattern
|
|
100
|
+
const pattern = randomBytes(size);
|
|
101
|
+
this.#data.set(pattern);
|
|
102
|
+
|
|
103
|
+
// Compute baseline hash
|
|
104
|
+
this.#baselineHash = bytesToHex(sha3_256(this.#data));
|
|
105
|
+
|
|
106
|
+
Object.seal(this);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Get canary ID */
|
|
110
|
+
get id() { return this.#id; }
|
|
111
|
+
|
|
112
|
+
/** Get canary type */
|
|
113
|
+
get type() { return this.#type; }
|
|
114
|
+
|
|
115
|
+
/** Get baseline hash */
|
|
116
|
+
get baselineHash() { return this.#baselineHash; }
|
|
117
|
+
|
|
118
|
+
/** Is canary corrupted? */
|
|
119
|
+
get isCorrupted() { return this.#corrupted; }
|
|
120
|
+
|
|
121
|
+
/** Get check count */
|
|
122
|
+
get checkCount() { return this.#checkCount; }
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Verify canary integrity
|
|
126
|
+
* @returns {{ valid: boolean, currentHash?: string }}
|
|
127
|
+
*/
|
|
128
|
+
verify() {
|
|
129
|
+
this.#lastCheck = Date.now();
|
|
130
|
+
this.#checkCount++;
|
|
131
|
+
|
|
132
|
+
const currentHash = bytesToHex(sha3_256(this.#data));
|
|
133
|
+
|
|
134
|
+
if (currentHash !== this.#baselineHash) {
|
|
135
|
+
this.#corrupted = true;
|
|
136
|
+
return {
|
|
137
|
+
valid: false,
|
|
138
|
+
currentHash,
|
|
139
|
+
expectedHash: this.#baselineHash,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { valid: true };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get pointer to underlying buffer (for native module boundary testing)
|
|
148
|
+
* @returns {Uint8Array}
|
|
149
|
+
*/
|
|
150
|
+
getBuffer() {
|
|
151
|
+
return this.#data;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get state for SANGHA attestation
|
|
156
|
+
*/
|
|
157
|
+
getState() {
|
|
158
|
+
return {
|
|
159
|
+
id: this.#id,
|
|
160
|
+
type: this.#type,
|
|
161
|
+
size: this.#data.length,
|
|
162
|
+
baselineHash: this.#baselineHash.slice(0, 16) + '...',
|
|
163
|
+
lastCheck: this.#lastCheck,
|
|
164
|
+
checkCount: this.#checkCount,
|
|
165
|
+
corrupted: this.#corrupted,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// CLOSURE CANARY
|
|
172
|
+
// =============================================================================
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* ClosureCanary — Protects closure state integrity
|
|
176
|
+
*
|
|
177
|
+
* JavaScript closures capture variables from outer scope.
|
|
178
|
+
* If those variables are corrupted (rare, but possible via
|
|
179
|
+
* native module bugs), the closure behavior changes silently.
|
|
180
|
+
*
|
|
181
|
+
* A ClosureCanary captures a set of sentinel values in a closure
|
|
182
|
+
* and verifies they haven't been mutated.
|
|
183
|
+
*/
|
|
184
|
+
export class ClosureCanary {
|
|
185
|
+
#id;
|
|
186
|
+
#verifier;
|
|
187
|
+
#expectedHash;
|
|
188
|
+
#corrupted;
|
|
189
|
+
#checkCount;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @param {string} id - Unique identifier
|
|
193
|
+
*/
|
|
194
|
+
constructor(id) {
|
|
195
|
+
this.#id = id;
|
|
196
|
+
this.#corrupted = false;
|
|
197
|
+
this.#checkCount = 0;
|
|
198
|
+
|
|
199
|
+
// Create sentinel values in a closure
|
|
200
|
+
const sentinel1 = 0xDEADBEEF;
|
|
201
|
+
const sentinel2 = 0xCAFEBABE;
|
|
202
|
+
const sentinel3 = 'YAKMESH_CLOSURE_CANARY_' + id;
|
|
203
|
+
const sentinel4 = Object.freeze({ magic: 0x144714, frozen: true });
|
|
204
|
+
|
|
205
|
+
// Compute expected hash
|
|
206
|
+
const combined = `${sentinel1}:${sentinel2}:${sentinel3}:${JSON.stringify(sentinel4)}`;
|
|
207
|
+
this.#expectedHash = bytesToHex(sha3_256(new TextEncoder().encode(combined)));
|
|
208
|
+
|
|
209
|
+
// Create verifier closure that captures the sentinels
|
|
210
|
+
this.#verifier = () => {
|
|
211
|
+
const combined = `${sentinel1}:${sentinel2}:${sentinel3}:${JSON.stringify(sentinel4)}`;
|
|
212
|
+
return bytesToHex(sha3_256(new TextEncoder().encode(combined)));
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
Object.seal(this);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Get canary ID */
|
|
219
|
+
get id() { return this.#id; }
|
|
220
|
+
|
|
221
|
+
/** Is canary corrupted? */
|
|
222
|
+
get isCorrupted() { return this.#corrupted; }
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Verify closure integrity
|
|
226
|
+
*/
|
|
227
|
+
verify() {
|
|
228
|
+
this.#checkCount++;
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
const currentHash = this.#verifier();
|
|
232
|
+
|
|
233
|
+
if (currentHash !== this.#expectedHash) {
|
|
234
|
+
this.#corrupted = true;
|
|
235
|
+
return {
|
|
236
|
+
valid: false,
|
|
237
|
+
error: 'Closure sentinel corruption detected',
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return { valid: true };
|
|
242
|
+
} catch (e) {
|
|
243
|
+
this.#corrupted = true;
|
|
244
|
+
return {
|
|
245
|
+
valid: false,
|
|
246
|
+
error: `Closure verification threw: ${e.message}`,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get state for SANGHA attestation
|
|
253
|
+
*/
|
|
254
|
+
getState() {
|
|
255
|
+
return {
|
|
256
|
+
id: this.#id,
|
|
257
|
+
type: CANARY_TYPE.CLOSURE,
|
|
258
|
+
expectedHash: this.#expectedHash.slice(0, 16) + '...',
|
|
259
|
+
checkCount: this.#checkCount,
|
|
260
|
+
corrupted: this.#corrupted,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// =============================================================================
|
|
266
|
+
// NATIVE MODULE CANARY
|
|
267
|
+
// =============================================================================
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* NativeModuleCanary — Boundary canary for native module interfaces
|
|
271
|
+
*
|
|
272
|
+
* Places canaries around data passed to native modules (ONNX Runtime, etc.)
|
|
273
|
+
* to detect buffer overflows or out-of-bounds writes.
|
|
274
|
+
*/
|
|
275
|
+
export class NativeModuleCanary {
|
|
276
|
+
#id;
|
|
277
|
+
#moduleName;
|
|
278
|
+
#preBuffer;
|
|
279
|
+
#postBuffer;
|
|
280
|
+
#preHash;
|
|
281
|
+
#postHash;
|
|
282
|
+
#corrupted;
|
|
283
|
+
#checkCount;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @param {string} id - Unique identifier
|
|
287
|
+
* @param {string} moduleName - Name of the native module being protected
|
|
288
|
+
* @param {number} size - Canary size (before and after)
|
|
289
|
+
*/
|
|
290
|
+
constructor(id, moduleName, size = 64) {
|
|
291
|
+
this.#id = id;
|
|
292
|
+
this.#moduleName = moduleName;
|
|
293
|
+
this.#corrupted = false;
|
|
294
|
+
this.#checkCount = 0;
|
|
295
|
+
|
|
296
|
+
// Create pre and post buffers with random patterns
|
|
297
|
+
this.#preBuffer = new Uint8Array(size);
|
|
298
|
+
this.#postBuffer = new Uint8Array(size);
|
|
299
|
+
|
|
300
|
+
const prePat = randomBytes(size);
|
|
301
|
+
const postPat = randomBytes(size);
|
|
302
|
+
|
|
303
|
+
this.#preBuffer.set(prePat);
|
|
304
|
+
this.#postBuffer.set(postPat);
|
|
305
|
+
|
|
306
|
+
this.#preHash = bytesToHex(sha3_256(this.#preBuffer));
|
|
307
|
+
this.#postHash = bytesToHex(sha3_256(this.#postBuffer));
|
|
308
|
+
|
|
309
|
+
Object.seal(this);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** Get canary ID */
|
|
313
|
+
get id() { return this.#id; }
|
|
314
|
+
|
|
315
|
+
/** Get module name */
|
|
316
|
+
get moduleName() { return this.#moduleName; }
|
|
317
|
+
|
|
318
|
+
/** Get pre-buffer (place before native call data) */
|
|
319
|
+
get preBuffer() { return this.#preBuffer; }
|
|
320
|
+
|
|
321
|
+
/** Get post-buffer (place after native call data) */
|
|
322
|
+
get postBuffer() { return this.#postBuffer; }
|
|
323
|
+
|
|
324
|
+
/** Is canary corrupted? */
|
|
325
|
+
get isCorrupted() { return this.#corrupted; }
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Verify both boundaries
|
|
329
|
+
*/
|
|
330
|
+
verify() {
|
|
331
|
+
this.#checkCount++;
|
|
332
|
+
|
|
333
|
+
const preHash = bytesToHex(sha3_256(this.#preBuffer));
|
|
334
|
+
const postHash = bytesToHex(sha3_256(this.#postBuffer));
|
|
335
|
+
|
|
336
|
+
const errors = [];
|
|
337
|
+
|
|
338
|
+
if (preHash !== this.#preHash) {
|
|
339
|
+
errors.push('Pre-buffer corrupted (underflow detected)');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (postHash !== this.#postHash) {
|
|
343
|
+
errors.push('Post-buffer corrupted (overflow detected)');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (errors.length > 0) {
|
|
347
|
+
this.#corrupted = true;
|
|
348
|
+
return {
|
|
349
|
+
valid: false,
|
|
350
|
+
errors,
|
|
351
|
+
module: this.#moduleName,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return { valid: true };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Get state for SANGHA attestation
|
|
360
|
+
*/
|
|
361
|
+
getState() {
|
|
362
|
+
return {
|
|
363
|
+
id: this.#id,
|
|
364
|
+
type: CANARY_TYPE.NATIVE,
|
|
365
|
+
module: this.#moduleName,
|
|
366
|
+
preHash: this.#preHash.slice(0, 16) + '...',
|
|
367
|
+
postHash: this.#postHash.slice(0, 16) + '...',
|
|
368
|
+
checkCount: this.#checkCount,
|
|
369
|
+
corrupted: this.#corrupted,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// =============================================================================
|
|
375
|
+
// MEMORY SAFETY MANAGER
|
|
376
|
+
// =============================================================================
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* MemorySafety — Manages all canaries and SANGHA integration
|
|
380
|
+
*/
|
|
381
|
+
export class MemorySafety extends EventEmitter {
|
|
382
|
+
#canaries;
|
|
383
|
+
#closureCanaries;
|
|
384
|
+
#nativeCanaries;
|
|
385
|
+
#sangha;
|
|
386
|
+
#started;
|
|
387
|
+
#checkInterval;
|
|
388
|
+
#lastCheck;
|
|
389
|
+
#totalCorruptions;
|
|
390
|
+
|
|
391
|
+
constructor() {
|
|
392
|
+
super();
|
|
393
|
+
this.#canaries = new Map();
|
|
394
|
+
this.#closureCanaries = new Map();
|
|
395
|
+
this.#nativeCanaries = new Map();
|
|
396
|
+
this.#sangha = null;
|
|
397
|
+
this.#started = false;
|
|
398
|
+
this.#checkInterval = null;
|
|
399
|
+
this.#lastCheck = 0;
|
|
400
|
+
this.#totalCorruptions = 0;
|
|
401
|
+
|
|
402
|
+
Object.seal(this);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Create a heap canary
|
|
407
|
+
* @param {string} id - Unique identifier
|
|
408
|
+
* @param {number} size - Size in bytes
|
|
409
|
+
* @returns {Canary}
|
|
410
|
+
*/
|
|
411
|
+
createHeapCanary(id, size = CANARY_SIZE) {
|
|
412
|
+
const canary = new Canary(id, CANARY_TYPE.HEAP, size);
|
|
413
|
+
this.#canaries.set(id, canary);
|
|
414
|
+
log.debug('Created heap canary', { id, size });
|
|
415
|
+
return canary;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Create a closure canary
|
|
420
|
+
* @param {string} id - Unique identifier
|
|
421
|
+
* @returns {ClosureCanary}
|
|
422
|
+
*/
|
|
423
|
+
createClosureCanary(id) {
|
|
424
|
+
const canary = new ClosureCanary(id);
|
|
425
|
+
this.#closureCanaries.set(id, canary);
|
|
426
|
+
log.debug('Created closure canary', { id });
|
|
427
|
+
return canary;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Create a native module canary
|
|
432
|
+
* @param {string} id - Unique identifier
|
|
433
|
+
* @param {string} moduleName - Native module name
|
|
434
|
+
* @param {number} size - Boundary size
|
|
435
|
+
* @returns {NativeModuleCanary}
|
|
436
|
+
*/
|
|
437
|
+
createNativeCanary(id, moduleName, size = 64) {
|
|
438
|
+
const canary = new NativeModuleCanary(id, moduleName, size);
|
|
439
|
+
this.#nativeCanaries.set(id, canary);
|
|
440
|
+
log.debug('Created native module canary', { id, module: moduleName });
|
|
441
|
+
return canary;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Initialize default canaries for critical components
|
|
446
|
+
*/
|
|
447
|
+
init() {
|
|
448
|
+
// Heap canaries for key memory regions
|
|
449
|
+
this.createHeapCanary('heap:crypto', 512); // Crypto operations
|
|
450
|
+
this.createHeapCanary('heap:mesh', 256); // Mesh state
|
|
451
|
+
this.createHeapCanary('heap:identity', 256); // Identity data
|
|
452
|
+
|
|
453
|
+
// Closure canaries for long-lived closures
|
|
454
|
+
this.createClosureCanary('closure:event-handlers');
|
|
455
|
+
this.createClosureCanary('closure:timers');
|
|
456
|
+
|
|
457
|
+
// Native module canaries
|
|
458
|
+
this.createNativeCanary('native:onnx', 'onnxruntime', 128);
|
|
459
|
+
this.createNativeCanary('native:sqlite', 'better-sqlite3', 64);
|
|
460
|
+
|
|
461
|
+
log.info('Memory safety initialized', {
|
|
462
|
+
heapCanaries: this.#canaries.size,
|
|
463
|
+
closureCanaries: this.#closureCanaries.size,
|
|
464
|
+
nativeCanaries: this.#nativeCanaries.size,
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Bind to SANGHA collective
|
|
470
|
+
* @param {Sangha} sangha - The SANGHA instance
|
|
471
|
+
*/
|
|
472
|
+
bindSangha(sangha) {
|
|
473
|
+
this.#sangha = sangha;
|
|
474
|
+
log.info('Memory safety bound to SANGHA collective');
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Verify all canaries
|
|
479
|
+
* @returns {{ valid: boolean, corruptions: object[] }}
|
|
480
|
+
*/
|
|
481
|
+
verifyAll() {
|
|
482
|
+
const corruptions = [];
|
|
483
|
+
this.#lastCheck = Date.now();
|
|
484
|
+
|
|
485
|
+
// Check heap canaries
|
|
486
|
+
for (const [id, canary] of this.#canaries) {
|
|
487
|
+
const result = canary.verify();
|
|
488
|
+
if (!result.valid) {
|
|
489
|
+
corruptions.push({
|
|
490
|
+
type: CANARY_TYPE.HEAP,
|
|
491
|
+
id,
|
|
492
|
+
...result,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Check closure canaries
|
|
498
|
+
for (const [id, canary] of this.#closureCanaries) {
|
|
499
|
+
const result = canary.verify();
|
|
500
|
+
if (!result.valid) {
|
|
501
|
+
corruptions.push({
|
|
502
|
+
type: CANARY_TYPE.CLOSURE,
|
|
503
|
+
id,
|
|
504
|
+
...result,
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Check native canaries
|
|
510
|
+
for (const [id, canary] of this.#nativeCanaries) {
|
|
511
|
+
const result = canary.verify();
|
|
512
|
+
if (!result.valid) {
|
|
513
|
+
corruptions.push({
|
|
514
|
+
type: CANARY_TYPE.NATIVE,
|
|
515
|
+
id,
|
|
516
|
+
...result,
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (corruptions.length > 0) {
|
|
522
|
+
this.#totalCorruptions += corruptions.length;
|
|
523
|
+
this.emit('corruption', corruptions);
|
|
524
|
+
log.error('🚨 MEMORY CORRUPTION DETECTED', {
|
|
525
|
+
count: corruptions.length,
|
|
526
|
+
corruptions,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return {
|
|
531
|
+
valid: corruptions.length === 0,
|
|
532
|
+
corruptions,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Start periodic verification
|
|
538
|
+
* @param {number} intervalMs - Check interval
|
|
539
|
+
*/
|
|
540
|
+
start(intervalMs = DEFAULT_CHECK_INTERVAL_MS) {
|
|
541
|
+
if (this.#started) return;
|
|
542
|
+
|
|
543
|
+
this.#started = true;
|
|
544
|
+
|
|
545
|
+
this.#checkInterval = setInterval(() => {
|
|
546
|
+
this.verifyAll();
|
|
547
|
+
}, intervalMs);
|
|
548
|
+
|
|
549
|
+
log.info('Memory safety monitoring started', { interval: intervalMs });
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Get state for SANGHA attestation
|
|
554
|
+
* @returns {Promise<object>}
|
|
555
|
+
*/
|
|
556
|
+
async getState() {
|
|
557
|
+
const heapStates = [];
|
|
558
|
+
const closureStates = [];
|
|
559
|
+
const nativeStates = [];
|
|
560
|
+
|
|
561
|
+
for (const canary of this.#canaries.values()) {
|
|
562
|
+
heapStates.push(canary.getState());
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
for (const canary of this.#closureCanaries.values()) {
|
|
566
|
+
closureStates.push(canary.getState());
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
for (const canary of this.#nativeCanaries.values()) {
|
|
570
|
+
nativeStates.push(canary.getState());
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return {
|
|
574
|
+
component: 'memory',
|
|
575
|
+
heapCanaries: heapStates.length,
|
|
576
|
+
closureCanaries: closureStates.length,
|
|
577
|
+
nativeCanaries: nativeStates.length,
|
|
578
|
+
totalCorruptions: this.#totalCorruptions,
|
|
579
|
+
allHealthy: heapStates.every(c => !c.corrupted) &&
|
|
580
|
+
closureStates.every(c => !c.corrupted) &&
|
|
581
|
+
nativeStates.every(c => !c.corrupted),
|
|
582
|
+
lastCheck: this.#lastCheck,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Get status summary
|
|
588
|
+
*/
|
|
589
|
+
getStatus() {
|
|
590
|
+
return {
|
|
591
|
+
started: this.#started,
|
|
592
|
+
sanghaConnected: !!this.#sangha,
|
|
593
|
+
heapCanaries: this.#canaries.size,
|
|
594
|
+
closureCanaries: this.#closureCanaries.size,
|
|
595
|
+
nativeCanaries: this.#nativeCanaries.size,
|
|
596
|
+
totalCorruptions: this.#totalCorruptions,
|
|
597
|
+
lastCheck: this.#lastCheck,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Stop monitoring
|
|
603
|
+
*/
|
|
604
|
+
stop() {
|
|
605
|
+
if (!this.#started) return;
|
|
606
|
+
|
|
607
|
+
this.#started = false;
|
|
608
|
+
|
|
609
|
+
if (this.#checkInterval) {
|
|
610
|
+
clearInterval(this.#checkInterval);
|
|
611
|
+
this.#checkInterval = null;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
log.info('Memory safety monitoring stopped');
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// =============================================================================
|
|
619
|
+
// SINGLETON & EXPORTS
|
|
620
|
+
// =============================================================================
|
|
621
|
+
|
|
622
|
+
let _instance = null;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Get the MemorySafety singleton
|
|
626
|
+
* @returns {MemorySafety}
|
|
627
|
+
*/
|
|
628
|
+
export function getMemorySafety() {
|
|
629
|
+
if (!_instance) {
|
|
630
|
+
_instance = new MemorySafety();
|
|
631
|
+
}
|
|
632
|
+
return _instance;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export default MemorySafety;
|
package/security/mesh-auth.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
12
|
-
import {
|
|
12
|
+
import { bytesToHex, hexToBytes, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
13
|
+
import { ternaryId } from '../utils/ternary-id.js';
|
|
13
14
|
import { EventEmitter } from 'events';
|
|
14
15
|
import { createLogger } from '../utils/logger.js';
|
|
15
16
|
|
|
@@ -33,7 +34,7 @@ export class MeshAuthenticator extends EventEmitter {
|
|
|
33
34
|
this.sessions = new Map();
|
|
34
35
|
this.stats = { authAttempts: 0, authSuccess: 0, authFailed: 0, blocked: 0 };
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
isAllowed(peerId) {
|
|
38
39
|
if (this.options.blocklist.has(peerId)) {
|
|
39
40
|
this.stats.blocked++;
|
|
@@ -42,15 +43,15 @@ export class MeshAuthenticator extends EventEmitter {
|
|
|
42
43
|
if (this.options.allowlist.size === 0) return true;
|
|
43
44
|
return this.options.allowlist.has(peerId);
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
generateChallenge(peerId) {
|
|
47
48
|
if (this.pendingChallenges.size >= this.options.maxPendingAuth) {
|
|
48
49
|
throw new Error('Too many pending authentication requests');
|
|
49
50
|
}
|
|
50
51
|
const challenge = {
|
|
51
52
|
type: 'auth_challenge',
|
|
52
|
-
challengeId:
|
|
53
|
-
nonce:
|
|
53
|
+
challengeId: ternaryId(16),
|
|
54
|
+
nonce: ternaryId(32),
|
|
54
55
|
timestamp: Date.now(),
|
|
55
56
|
challengerNodeId: this.identity.identity.nodeId,
|
|
56
57
|
};
|
|
@@ -59,7 +60,7 @@ export class MeshAuthenticator extends EventEmitter {
|
|
|
59
60
|
this.stats.authAttempts++;
|
|
60
61
|
return challenge;
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
respondToChallenge(challenge) {
|
|
64
65
|
const responseData = JSON.stringify({
|
|
65
66
|
challengeId: challenge.challengeId,
|
|
@@ -77,7 +78,7 @@ export class MeshAuthenticator extends EventEmitter {
|
|
|
77
78
|
signature,
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
verifyResponse(response) {
|
|
82
83
|
const pending = this.pendingChallenges.get(response.challengeId);
|
|
83
84
|
if (!pending) {
|
|
@@ -105,17 +106,17 @@ export class MeshAuthenticator extends EventEmitter {
|
|
|
105
106
|
this.emit('authenticated', { peerId: response.responderNodeId });
|
|
106
107
|
return { valid: true, peerId: response.responderNodeId, sessionKey: bytesToHex(sessionKey) };
|
|
107
108
|
}
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
isAuthenticated(peerId) { return this.sessions.has(peerId); }
|
|
110
111
|
getSession(peerId) { return this.sessions.get(peerId) || null; }
|
|
111
112
|
revokeSession(peerId) { this.sessions.delete(peerId); this.emit('session-revoked', { peerId }); }
|
|
112
113
|
block(peerId) { this.options.blocklist.add(peerId); this.revokeSession(peerId); }
|
|
113
114
|
unblock(peerId) { this.options.blocklist.delete(peerId); }
|
|
114
|
-
|
|
115
|
+
|
|
115
116
|
_deriveSessionKey(peerId, nonce) {
|
|
116
117
|
return sha3_256(utf8ToBytes(peerId + nonce + this.identity.identity.nodeId));
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
getStats() {
|
|
120
121
|
return { ...this.stats, pendingChallenges: this.pendingChallenges.size, activeSessions: this.sessions.size };
|
|
121
122
|
}
|