@blamejs/core 0.9.14 → 0.9.16
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 +2 -0
- package/lib/a2a-tasks.js +2 -2
- package/lib/a2a.js +11 -11
- package/lib/acme.js +5 -5
- package/lib/ai-input.js +2 -2
- package/lib/api-key.js +4 -4
- package/lib/api-snapshot.js +6 -6
- package/lib/app-shutdown.js +2 -2
- package/lib/app.js +5 -5
- package/lib/archive.js +8 -8
- package/lib/argon2-builtin.js +2 -2
- package/lib/atomic-file.js +53 -53
- package/lib/audit-sign.js +8 -8
- package/lib/audit-tools.js +22 -22
- package/lib/auth/dpop.js +3 -3
- package/lib/auth/elevation-grant.js +3 -3
- package/lib/auth/fido-mds3.js +6 -6
- package/lib/auth/jwt-external.js +2 -2
- package/lib/auth/sd-jwt-vc.js +2 -2
- package/lib/backup/bundle.js +17 -17
- package/lib/backup/index.js +36 -36
- package/lib/budr.js +3 -3
- package/lib/bundler.js +20 -20
- package/lib/circuit-breaker.js +4 -4
- package/lib/cli.js +25 -26
- package/lib/cluster.js +2 -2
- package/lib/compliance-sanctions.js +2 -2
- package/lib/compliance.js +6 -7
- package/lib/config-drift.js +15 -15
- package/lib/config.js +6 -6
- package/lib/content-credentials.js +4 -4
- package/lib/credential-hash.js +7 -7
- package/lib/crypto-field.js +9 -9
- package/lib/daemon.js +19 -19
- package/lib/db-file-lifecycle.js +24 -24
- package/lib/db-schema.js +2 -2
- package/lib/db.js +34 -34
- package/lib/dev.js +10 -10
- package/lib/dr-runbook.js +5 -5
- package/lib/dual-control.js +2 -2
- package/lib/external-db-migrate.js +17 -17
- package/lib/external-db.js +2 -2
- package/lib/fdx.js +2 -2
- package/lib/file-upload.js +30 -30
- package/lib/flag-evaluation-context.js +2 -2
- package/lib/flag-providers.js +4 -4
- package/lib/gate-contract.js +5 -5
- package/lib/graphql-federation.js +4 -7
- package/lib/honeytoken.js +6 -6
- package/lib/http-client-cookie-jar.js +6 -6
- package/lib/http-client.js +18 -18
- package/lib/i18n.js +5 -5
- package/lib/keychain.js +5 -5
- package/lib/legal-hold.js +2 -2
- package/lib/local-db-thin.js +9 -9
- package/lib/log-stream-local.js +17 -17
- package/lib/log-stream-syslog.js +2 -2
- package/lib/log-stream.js +3 -3
- package/lib/log.js +2 -2
- package/lib/mail-bounce.js +2 -2
- package/lib/mail-mdn.js +2 -2
- package/lib/mail-srs.js +2 -2
- package/lib/mail.js +7 -7
- package/lib/mcp-tool-registry.js +6 -6
- package/lib/mcp.js +2 -2
- package/lib/metrics.js +2 -2
- package/lib/middleware/api-encrypt.js +16 -16
- package/lib/middleware/body-parser.js +18 -18
- package/lib/middleware/compression.js +3 -3
- package/lib/middleware/csp-nonce.js +4 -4
- package/lib/middleware/health.js +7 -7
- package/lib/middleware/idempotency-key.js +163 -63
- package/lib/middleware/require-bound-key.js +4 -4
- package/lib/middleware/require-mtls.js +4 -4
- package/lib/migrations.js +5 -5
- package/lib/mtls-ca.js +26 -26
- package/lib/mtls-engine-default.js +5 -5
- package/lib/network-byte-quota.js +2 -2
- package/lib/network-dns.js +2 -2
- package/lib/network-nts.js +2 -2
- package/lib/network-proxy.js +3 -3
- package/lib/network-smtp-policy.js +2 -2
- package/lib/network-tls.js +17 -17
- package/lib/network.js +25 -25
- package/lib/notify.js +11 -11
- package/lib/object-store/gcs-bucket-ops.js +2 -2
- package/lib/object-store/gcs.js +5 -5
- package/lib/object-store/index.js +6 -6
- package/lib/object-store/local.js +19 -19
- package/lib/object-store/sigv4.js +3 -3
- package/lib/observability-tracer.js +4 -4
- package/lib/otel-export.js +3 -3
- package/lib/pagination.js +5 -5
- package/lib/parsers/safe-env.js +3 -3
- package/lib/parsers/safe-xml.js +3 -3
- package/lib/pqc-gate.js +5 -5
- package/lib/pubsub-redis.js +2 -2
- package/lib/queue-local.js +3 -3
- package/lib/queue.js +2 -2
- package/lib/redis-client.js +4 -4
- package/lib/restore-bundle.js +17 -17
- package/lib/restore-rollback.js +34 -34
- package/lib/restore.js +16 -16
- package/lib/router.js +25 -25
- package/lib/sandbox.js +8 -8
- package/lib/sec-cyber.js +3 -3
- package/lib/security-assert.js +2 -2
- package/lib/seeders.js +6 -6
- package/lib/self-update.js +18 -18
- package/lib/session-device-binding.js +2 -2
- package/lib/static.js +22 -22
- package/lib/template.js +19 -19
- package/lib/testing.js +9 -9
- package/lib/tls-exporter.js +5 -5
- package/lib/tracing.js +3 -3
- package/lib/vault/index.js +11 -11
- package/lib/vault/passphrase-ops.js +37 -37
- package/lib/vault/passphrase-source.js +2 -2
- package/lib/vault/rotate.js +64 -64
- package/lib/vault/seal-pem-file.js +26 -26
- package/lib/vault-aad.js +5 -5
- package/lib/watcher.js +22 -22
- package/lib/webhook.js +10 -10
- package/lib/worker-pool.js +6 -6
- package/lib/ws-client.js +6 -6
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/local-db-thin.js
CHANGED
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
* localdb.thin.closed { file }
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
-
var
|
|
57
|
-
var
|
|
56
|
+
var nodeFs = require("fs");
|
|
57
|
+
var nodePath = require("path");
|
|
58
58
|
var lazyRequire = require("./lazy-require");
|
|
59
59
|
var validateOpts = require("./validate-opts");
|
|
60
60
|
var safeSql = require("./safe-sql");
|
|
@@ -77,7 +77,7 @@ var NUL_BYTE = String.fromCharCode(0);
|
|
|
77
77
|
function _validateOpts(opts) {
|
|
78
78
|
validateOpts.requireObject(opts, "localDb.thin", LocalDbThinError, "localdb-thin/bad-opts");
|
|
79
79
|
validateOpts.requireNonEmptyString(opts.file, "file", LocalDbThinError, "localdb-thin/bad-file");
|
|
80
|
-
// `file` is operator-supplied (daemon's chosen storage
|
|
80
|
+
// `file` is operator-supplied (daemon's chosen storage nodePath), not
|
|
81
81
|
// request-driven input. Reject NUL bytes defensively — Node's path
|
|
82
82
|
// routines silently truncate at the first NUL, which would let a
|
|
83
83
|
// typo open a different file than the operator intended.
|
|
@@ -144,7 +144,7 @@ function thin(opts) {
|
|
|
144
144
|
_validateOpts(opts);
|
|
145
145
|
|
|
146
146
|
var auditOn = opts.audit !== false;
|
|
147
|
-
// opts.file is operator-config (daemon-author chosen storage
|
|
147
|
+
// opts.file is operator-config (daemon-author chosen storage nodePath),
|
|
148
148
|
// not request-driven input. Validation above already rejected non-
|
|
149
149
|
// strings and NUL bytes. The operator picks the file location; the
|
|
150
150
|
// wrapper opens it as-is.
|
|
@@ -168,7 +168,7 @@ function thin(opts) {
|
|
|
168
168
|
|
|
169
169
|
// Ensure parent directory exists — operators commonly point this at
|
|
170
170
|
// an OS app-data path that may not exist on first daemon launch.
|
|
171
|
-
try {
|
|
171
|
+
try { nodeFs.mkdirSync(nodePath.dirname(file), { recursive: true }); } catch (_e) { /* best-effort */ }
|
|
172
172
|
|
|
173
173
|
var database = null;
|
|
174
174
|
var renamedTo = null;
|
|
@@ -203,13 +203,13 @@ function thin(opts) {
|
|
|
203
203
|
var lastRenameErr = null;
|
|
204
204
|
for (var attempt = 0; attempt < 20 && !renamed; attempt += 1) {
|
|
205
205
|
try {
|
|
206
|
-
if (
|
|
206
|
+
if (nodeFs.existsSync(file)) nodeFs.renameSync(file, renamedTo);
|
|
207
207
|
renamed = true;
|
|
208
208
|
} catch (re) {
|
|
209
209
|
lastRenameErr = re;
|
|
210
210
|
if (re && (re.code === "EBUSY" || re.code === "EPERM")) {
|
|
211
211
|
// Synchronous spin — don't reach for setTimeout in a
|
|
212
|
-
// boot-time
|
|
212
|
+
// boot-time nodePath. 100ms × 20 = 2s upper bound.
|
|
213
213
|
var until = Date.now() + 100;
|
|
214
214
|
while (Date.now() < until) { /* spin */ }
|
|
215
215
|
continue;
|
|
@@ -227,8 +227,8 @@ function thin(opts) {
|
|
|
227
227
|
// re-attach a half-open journal.
|
|
228
228
|
["-wal", "-shm"].forEach(function (suffix) {
|
|
229
229
|
var sibling = file + suffix;
|
|
230
|
-
if (
|
|
231
|
-
try {
|
|
230
|
+
if (nodeFs.existsSync(sibling)) {
|
|
231
|
+
try { nodeFs.renameSync(sibling, sibling + ".corrupt-" + stamp); }
|
|
232
232
|
catch (_se) { /* best-effort */ }
|
|
233
233
|
}
|
|
234
234
|
});
|
package/lib/log-stream-local.js
CHANGED
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
* fileNamePrefix: 'blamejs'
|
|
24
24
|
* }
|
|
25
25
|
*/
|
|
26
|
-
var
|
|
27
|
-
var
|
|
26
|
+
var nodeFs = require("fs");
|
|
27
|
+
var nodePath = require("path");
|
|
28
28
|
var zlib = require("zlib");
|
|
29
29
|
var atomicFile = require("./atomic-file");
|
|
30
30
|
var C = require("./constants");
|
|
@@ -48,19 +48,19 @@ var _err = LogStreamError.factory;
|
|
|
48
48
|
function create(config) {
|
|
49
49
|
if (!config || !config.dir) throw new Error("log-stream local requires { dir }");
|
|
50
50
|
var cfg = Object.assign({}, DEFAULTS, config);
|
|
51
|
-
var dir =
|
|
52
|
-
if (!
|
|
51
|
+
var dir = nodePath.resolve(cfg.dir);
|
|
52
|
+
if (!nodeFs.existsSync(dir)) nodeFs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
53
53
|
|
|
54
|
-
var activePath =
|
|
54
|
+
var activePath = nodePath.join(dir, cfg.fileNamePrefix + ".log");
|
|
55
55
|
var fd = null;
|
|
56
56
|
var openedAt = 0;
|
|
57
57
|
var bytesWritten = 0;
|
|
58
58
|
|
|
59
59
|
function _open() {
|
|
60
|
-
fd =
|
|
60
|
+
fd = nodeFs.openSync(activePath, "a", cfg.fileMode);
|
|
61
61
|
openedAt = Date.now();
|
|
62
62
|
try {
|
|
63
|
-
var stat =
|
|
63
|
+
var stat = nodeFs.fstatSync(fd);
|
|
64
64
|
bytesWritten = stat.size;
|
|
65
65
|
} catch (_e) {
|
|
66
66
|
bytesWritten = 0;
|
|
@@ -77,20 +77,20 @@ function create(config) {
|
|
|
77
77
|
function _rotate() {
|
|
78
78
|
try {
|
|
79
79
|
if (fd != null) {
|
|
80
|
-
try {
|
|
80
|
+
try { nodeFs.closeSync(fd); }
|
|
81
81
|
catch (e) { log.warn("rotate-close-failed: " + e.message); }
|
|
82
82
|
fd = null;
|
|
83
83
|
}
|
|
84
84
|
// Build rotated filename: blamejs-YYYYMMDDTHHMMSSZ.log
|
|
85
85
|
var stamp = time.toIso8601NoMs(new Date()).replace(/[-:]/g, "");
|
|
86
|
-
var rotated =
|
|
87
|
-
if (
|
|
88
|
-
|
|
86
|
+
var rotated = nodePath.join(dir, cfg.fileNamePrefix + "-" + stamp + ".log");
|
|
87
|
+
if (nodeFs.existsSync(activePath)) {
|
|
88
|
+
nodeFs.renameSync(activePath, rotated);
|
|
89
89
|
if (cfg.compressRotations) {
|
|
90
|
-
var data =
|
|
90
|
+
var data = nodeFs.readFileSync(rotated);
|
|
91
91
|
var gz = zlib.gzipSync(data);
|
|
92
92
|
atomicFile.writeSync(rotated + ".gz", gz, { fileMode: cfg.fileMode });
|
|
93
|
-
|
|
93
|
+
nodeFs.unlinkSync(rotated);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
_pruneOld();
|
|
@@ -109,7 +109,7 @@ function create(config) {
|
|
|
109
109
|
includeStat: true,
|
|
110
110
|
}).sort(function (a, b) { return b.mtimeMs - a.mtimeMs; }); // newest first
|
|
111
111
|
for (var i = cfg.keepRotations; i < entries.length; i++) {
|
|
112
|
-
try {
|
|
112
|
+
try { nodeFs.unlinkSync(entries[i].fullPath); } catch (_e) { /* best effort */ }
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -117,15 +117,15 @@ function create(config) {
|
|
|
117
117
|
if (_shouldRotate()) _rotate();
|
|
118
118
|
var line = JSON.stringify(record) + "\n";
|
|
119
119
|
var buf = Buffer.from(line, "utf8");
|
|
120
|
-
|
|
120
|
+
nodeFs.writeSync(fd, buf, 0, buf.length, null);
|
|
121
121
|
bytesWritten += buf.length;
|
|
122
122
|
return Promise.resolve({ bytes: buf.length });
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
function close() {
|
|
126
126
|
if (fd != null) {
|
|
127
|
-
try {
|
|
128
|
-
try {
|
|
127
|
+
try { nodeFs.fsyncSync(fd); } catch (_e) { /* best effort */ }
|
|
128
|
+
try { nodeFs.closeSync(fd); }
|
|
129
129
|
catch (e) { log.warn("close-failed: " + e.message); }
|
|
130
130
|
fd = null;
|
|
131
131
|
}
|
package/lib/log-stream-syslog.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
var dgram = require("dgram");
|
|
31
31
|
var net = require("net");
|
|
32
32
|
var os = require("os");
|
|
33
|
-
var
|
|
33
|
+
var nodeTls = require("tls");
|
|
34
34
|
var C = require("./constants");
|
|
35
35
|
var { boot } = require("./log");
|
|
36
36
|
var safeAsync = require("./safe-async");
|
|
@@ -223,7 +223,7 @@ function create(config) {
|
|
|
223
223
|
});
|
|
224
224
|
if (cfg.ca) tlsOpts.ca = cfg.ca;
|
|
225
225
|
if (cfg.servername) tlsOpts.servername = cfg.servername;
|
|
226
|
-
sock =
|
|
226
|
+
sock = nodeTls.connect(tlsOpts, onConnect);
|
|
227
227
|
} else {
|
|
228
228
|
sock = net.connect(connectOpts, onConnect);
|
|
229
229
|
}
|
package/lib/log-stream.js
CHANGED
|
@@ -55,7 +55,7 @@ var otlpGrpcProto = require("./log-stream-otlp-grpc");
|
|
|
55
55
|
var cloudwatchProto = require("./log-stream-cloudwatch");
|
|
56
56
|
var syslogProto = require("./log-stream-syslog");
|
|
57
57
|
var { boot } = require("./log");
|
|
58
|
-
var
|
|
58
|
+
var redact = require("./redact");
|
|
59
59
|
var lazyRequire = require("./lazy-require");
|
|
60
60
|
var protocolDispatcher = require("./protocol-dispatcher");
|
|
61
61
|
var { LogStreamError } = require("./framework-error");
|
|
@@ -215,7 +215,7 @@ function emit(level, message, meta) {
|
|
|
215
215
|
message: message == null ? null : String(message),
|
|
216
216
|
};
|
|
217
217
|
if (meta) {
|
|
218
|
-
record.meta =
|
|
218
|
+
record.meta = redact.redact(meta);
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// Fire-and-forget to all sinks. Sink errors don't bubble — they're
|
|
@@ -367,7 +367,7 @@ function onIncoming(handler) {
|
|
|
367
367
|
*/
|
|
368
368
|
async function deliverIncoming(payload, opts) {
|
|
369
369
|
opts = opts || {};
|
|
370
|
-
var redacted =
|
|
370
|
+
var redacted = redact.redact(payload);
|
|
371
371
|
// Audit-log the inbound command BEFORE invoking handlers — even handler
|
|
372
372
|
// exceptions don't lose the receipt.
|
|
373
373
|
audit().safeEmit({
|
package/lib/log.js
CHANGED
|
@@ -72,7 +72,7 @@ var { FrameworkError } = require("./framework-error");
|
|
|
72
72
|
// pulling the whole crypto bundle into the framework's earliest
|
|
73
73
|
// boot path (request-id middleware needs only generateToken).
|
|
74
74
|
var safeEnv = lazyRequire(function () { return require("./parsers/safe-env"); });
|
|
75
|
-
var
|
|
75
|
+
var bCrypto = lazyRequire(function () { return require("./crypto"); });
|
|
76
76
|
|
|
77
77
|
// Request-id correlation token — 8 bytes hex-encoded (16 chars). Short
|
|
78
78
|
// enough to read in a log line, long enough to keep collisions far below
|
|
@@ -384,7 +384,7 @@ function create(opts) {
|
|
|
384
384
|
// 16 random hex chars — short, sufficient correlation entropy.
|
|
385
385
|
// Routes through the framework token primitive so the entropy
|
|
386
386
|
// source matches the rest of the codebase.
|
|
387
|
-
return
|
|
387
|
+
return bCrypto().generateToken(REQUEST_ID_BYTES);
|
|
388
388
|
};
|
|
389
389
|
return function logRequestIdMiddleware(req, res, next) {
|
|
390
390
|
var inbound = req.headers && req.headers[headerName];
|
package/lib/mail-bounce.js
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* Inbound mail bounce-handler — parse the vendor's webhook DSN / complaint / delivery payload, normalize it into one event shape, classify hard vs soft bounces, and feed an operator-supplied suppression-list hook.
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
var
|
|
42
|
+
var bCrypto = require("./crypto");
|
|
43
43
|
var lazyRequire = require("./lazy-require");
|
|
44
44
|
var mimeParse = require("./mime-parse");
|
|
45
45
|
var numericBounds = require("./numeric-bounds");
|
|
@@ -817,7 +817,7 @@ function _foldFieldValue(name, value) {
|
|
|
817
817
|
}
|
|
818
818
|
|
|
819
819
|
function _generateBoundary() {
|
|
820
|
-
return "blamejs-dsn-" +
|
|
820
|
+
return "blamejs-dsn-" + bCrypto.generateToken(C.BYTES.bytes(12));
|
|
821
821
|
}
|
|
822
822
|
|
|
823
823
|
function _buildDsn(opts) {
|
package/lib/mail-mdn.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* RFC 3798 / RFC 8098 Message Disposition Notification builder + parser — generate "message read" return-receipts and parse inbound MDNs into a normalized event shape. Auto-generation refuses without explicit operator opt-in to prevent accidental privacy leaks.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
var
|
|
31
|
+
var bCrypto = require("./crypto");
|
|
32
32
|
var lazyRequire = require("./lazy-require");
|
|
33
33
|
var mimeParse = require("./mime-parse");
|
|
34
34
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
@@ -99,7 +99,7 @@ function _parseDisposition(value) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
function _generateBoundary() {
|
|
102
|
-
return "blamejs-mdn-" +
|
|
102
|
+
return "blamejs-mdn-" + bCrypto.generateToken(C.BYTES.bytes(12));
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
package/lib/mail-srs.js
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
45
|
var nodeCrypto = require("node:crypto");
|
|
46
|
-
var
|
|
46
|
+
var bCrypto = require("./crypto");
|
|
47
47
|
var validateOpts = require("./validate-opts");
|
|
48
48
|
var { defineClass } = require("./framework-error");
|
|
49
49
|
|
|
@@ -239,7 +239,7 @@ function create(opts) {
|
|
|
239
239
|
|
|
240
240
|
function _timingSafeStringEqual(a, b) {
|
|
241
241
|
if (typeof a !== "string" || typeof b !== "string") return false;
|
|
242
|
-
return
|
|
242
|
+
return bCrypto.timingSafeEqual(Buffer.from(a, "utf8"), Buffer.from(b, "utf8"));
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
module.exports = {
|
package/lib/mail.js
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
* SMTP / HTTP-API email send with multipart RFC 5322 message composition, DKIM signing on the way out, and full inbound mail- authentication parsing on the way in.
|
|
57
57
|
*/
|
|
58
58
|
var C = require("./constants");
|
|
59
|
-
var
|
|
59
|
+
var bCrypto = require("./crypto");
|
|
60
60
|
var lazyRequire = require("./lazy-require");
|
|
61
61
|
var safeBuffer = require("./safe-buffer");
|
|
62
62
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
@@ -64,7 +64,7 @@ var httpClient = lazyRequire(function () { return require("./http-client"); });
|
|
|
64
64
|
var guardEmail = lazyRequire(function () { return require("./guard-email"); });
|
|
65
65
|
var guardFilename = lazyRequire(function () { return require("./guard-filename"); });
|
|
66
66
|
var fileType = lazyRequire(function () { return require("./file-type"); });
|
|
67
|
-
var
|
|
67
|
+
var dkim = require("./mail-dkim");
|
|
68
68
|
var mailAuth = require("./mail-auth");
|
|
69
69
|
var mailBimi = require("./mail-bimi");
|
|
70
70
|
var mailUnsubscribe = require("./mail-unsubscribe");
|
|
@@ -72,7 +72,7 @@ var net = lazyRequire(function () { return require("net"); });
|
|
|
72
72
|
var networkDns = lazyRequire(function () { return require("./network-dns"); });
|
|
73
73
|
var nodeUrl = require("url");
|
|
74
74
|
var numericBounds = require("./numeric-bounds");
|
|
75
|
-
var
|
|
75
|
+
var nodeTls = lazyRequire(function () { return require("tls"); });
|
|
76
76
|
var safeJson = require("./safe-json");
|
|
77
77
|
var safeSchema = require("./safe-schema");
|
|
78
78
|
var validateOpts = require("./validate-opts");
|
|
@@ -634,7 +634,7 @@ function _newBoundary(label) {
|
|
|
634
634
|
// convention. RFC 5322 only requires uniqueness within a message,
|
|
635
635
|
// but consistency with how every other identifier in lib/ is built
|
|
636
636
|
// wins over premature differentiation.
|
|
637
|
-
return "blamejs-" + label + "-" + Date.now() + "-" +
|
|
637
|
+
return "blamejs-" + label + "-" + Date.now() + "-" + bCrypto.generateToken(C.BYTES.bytes(8));
|
|
638
638
|
}
|
|
639
639
|
|
|
640
640
|
// base64-encode the buffer with line wrapping at 76 chars (RFC 2045
|
|
@@ -1142,7 +1142,7 @@ function _smtpSend(message, cfg) {
|
|
|
1142
1142
|
tlsConnectOpts.host = cfg.host;
|
|
1143
1143
|
tlsConnectOpts.port = cfg.port;
|
|
1144
1144
|
if (family === 4 || family === 6) tlsConnectOpts.family = family;
|
|
1145
|
-
attachSocket(
|
|
1145
|
+
attachSocket(nodeTls().connect(tlsConnectOpts));
|
|
1146
1146
|
} else {
|
|
1147
1147
|
var netOpts = { host: cfg.host, port: cfg.port };
|
|
1148
1148
|
if (family === 4 || family === 6) netOpts.family = family;
|
|
@@ -1211,7 +1211,7 @@ function _smtpSend(message, cfg) {
|
|
|
1211
1211
|
if (code !== 220) { fail("starttls-rejected (code " + code + ")"); return; }
|
|
1212
1212
|
var tlsConnectOpts = Object.assign({ socket: socket }, cfg.tlsOpts);
|
|
1213
1213
|
if (cfg.servername) tlsConnectOpts.servername = cfg.servername;
|
|
1214
|
-
var tlsSocket =
|
|
1214
|
+
var tlsSocket = nodeTls().connect(tlsConnectOpts, function () {
|
|
1215
1215
|
upgradedToTLS = true;
|
|
1216
1216
|
try { socket.removeAllListeners("data"); } catch (_e) { /* listeners migrate to upgraded socket */ }
|
|
1217
1217
|
attachSocket(tlsSocket);
|
|
@@ -1841,7 +1841,7 @@ module.exports = {
|
|
|
1841
1841
|
// DKIM-Signature header generation for outbound mail (rsa-sha256
|
|
1842
1842
|
// default, ed25519-sha256 opt-in). Wire it into the smtp transport
|
|
1843
1843
|
// via opts.dkimSigner. See lib/mail-dkim.js for the full surface.
|
|
1844
|
-
dkim:
|
|
1844
|
+
dkim: dkim,
|
|
1845
1845
|
// Inbound mail authentication-results verification: SPF (RFC 7208),
|
|
1846
1846
|
// DMARC (RFC 7489), ARC (RFC 8617). Outbound DKIM signing lives in
|
|
1847
1847
|
// .dkim above; per-hop DKIM verification is deferred (composes with
|
package/lib/mcp-tool-registry.js
CHANGED
|
@@ -64,7 +64,7 @@ var lazyRequire = require("./lazy-require");
|
|
|
64
64
|
var validateOpts = require("./validate-opts");
|
|
65
65
|
var { McpError } = require("./framework-error");
|
|
66
66
|
|
|
67
|
-
var
|
|
67
|
+
var bCrypto = lazyRequire(function () { return require("./crypto"); });
|
|
68
68
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
69
69
|
var C = require("./constants");
|
|
70
70
|
|
|
@@ -202,7 +202,7 @@ function create(opts) {
|
|
|
202
202
|
outputSchema: tool.outputSchema || null,
|
|
203
203
|
alg: alg,
|
|
204
204
|
});
|
|
205
|
-
var sig =
|
|
205
|
+
var sig = bCrypto().sign(Buffer.from(payload, "utf8"), signingKey);
|
|
206
206
|
return {
|
|
207
207
|
tool: tool.name,
|
|
208
208
|
description: tool.description || "",
|
|
@@ -254,7 +254,7 @@ function create(opts) {
|
|
|
254
254
|
}),
|
|
255
255
|
issuedAt: new Date().toISOString(),
|
|
256
256
|
});
|
|
257
|
-
var sig =
|
|
257
|
+
var sig = bCrypto().sign(Buffer.from(manifestBody, "utf8"), signingKey);
|
|
258
258
|
return {
|
|
259
259
|
body: manifestBody,
|
|
260
260
|
signature: sig.toString("base64"),
|
|
@@ -309,7 +309,7 @@ function create(opts) {
|
|
|
309
309
|
}
|
|
310
310
|
var nonce = typeof callOpts.nonce === "string" && callOpts.nonce.length > 0
|
|
311
311
|
? callOpts.nonce
|
|
312
|
-
:
|
|
312
|
+
: bCrypto().generateToken(16); // allow:raw-byte-literal — 128-bit nonce, not byte arithmetic on a payload
|
|
313
313
|
var iat = new Date();
|
|
314
314
|
var exp = new Date(iat.getTime() + ttlMs);
|
|
315
315
|
var envelope = {
|
|
@@ -320,7 +320,7 @@ function create(opts) {
|
|
|
320
320
|
exp: exp.toISOString(),
|
|
321
321
|
};
|
|
322
322
|
var payload = Buffer.from(canonicalJson.stringify(envelope), "utf8");
|
|
323
|
-
var sig =
|
|
323
|
+
var sig = bCrypto().sign(payload, signingKey);
|
|
324
324
|
_emitAudit("mcp.tool_registry.call_signed",
|
|
325
325
|
{ tool: envelope.tool, nonce: nonce, alg: alg });
|
|
326
326
|
return {
|
|
@@ -438,7 +438,7 @@ function create(opts) {
|
|
|
438
438
|
"verifyCall: signature not valid base64");
|
|
439
439
|
}
|
|
440
440
|
var ok;
|
|
441
|
-
try { ok =
|
|
441
|
+
try { ok = bCrypto().verify(payload, sigBuf, verifyingKey); }
|
|
442
442
|
catch (verifyErr) {
|
|
443
443
|
_emitAudit("mcp.tool_registry.call_verify_error",
|
|
444
444
|
{ tool: env.tool, nonce: env.nonce, error: String(verifyErr.message || verifyErr) }, "denied");
|
package/lib/mcp.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
var C = require("./constants");
|
|
34
|
-
var
|
|
34
|
+
var numericBounds = require("./numeric-bounds");
|
|
35
35
|
var safeUrl = require("./safe-url");
|
|
36
36
|
var safeJson = require("./safe-json");
|
|
37
37
|
var safeBuffer = require("./safe-buffer");
|
|
@@ -261,7 +261,7 @@ function serverGuard(opts) {
|
|
|
261
261
|
}
|
|
262
262
|
var toolAllowlist = Array.isArray(opts.toolAllowlist) ? opts.toolAllowlist : null;
|
|
263
263
|
var resourceAllowlist = Array.isArray(opts.resourceAllowlist) ? opts.resourceAllowlist : null;
|
|
264
|
-
|
|
264
|
+
numericBounds.requirePositiveFiniteIntIfPresent(opts.maxBodyBytes, "mcp.serverGuard: opts.maxBodyBytes", errorClass, "BAD_MAX_BYTES");
|
|
265
265
|
var maxBodyBytes = opts.maxBodyBytes || C.BYTES.mib(1);
|
|
266
266
|
var auditOn = opts.audit !== false;
|
|
267
267
|
|
package/lib/metrics.js
CHANGED
|
@@ -44,7 +44,7 @@ var atomicFile = require("./atomic-file");
|
|
|
44
44
|
var safeJson = require("./safe-json");
|
|
45
45
|
var { defineClass } = require("./framework-error");
|
|
46
46
|
var { boot } = require("./log");
|
|
47
|
-
var
|
|
47
|
+
var numericBounds = require("./numeric-bounds");
|
|
48
48
|
var { resolveRoute, captureResponseStatus, HTTP_STATUS } = require("./request-helpers");
|
|
49
49
|
var validateOpts = require("./validate-opts");
|
|
50
50
|
|
|
@@ -279,7 +279,7 @@ function create(opts) {
|
|
|
279
279
|
], "b.metrics");
|
|
280
280
|
var namespace = opts.namespace || "";
|
|
281
281
|
var defaultLabels = opts.defaultLabels || {};
|
|
282
|
-
|
|
282
|
+
numericBounds.requirePositiveFiniteIntIfPresent(opts.labelCardinalityCap,
|
|
283
283
|
"labelCardinalityCap", MetricsError, "metrics/bad-opt");
|
|
284
284
|
var cardinalityCap = opts.labelCardinalityCap || DEFAULT_CARDINALITY_CAP;
|
|
285
285
|
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
* public/private routes can debug their wiring.
|
|
97
97
|
*/
|
|
98
98
|
|
|
99
|
-
var
|
|
99
|
+
var bCrypto = require("../crypto");
|
|
100
100
|
var C = require("../constants");
|
|
101
101
|
var lazyRequire = require("../lazy-require");
|
|
102
102
|
var nonceStoreLib = require("../nonce-store");
|
|
@@ -449,7 +449,7 @@ function create(opts) {
|
|
|
449
449
|
res.json = function (data) {
|
|
450
450
|
try {
|
|
451
451
|
var ptBuf = Buffer.from(JSON.stringify(data), "utf8");
|
|
452
|
-
var ctBuf =
|
|
452
|
+
var ctBuf = bCrypto.encryptPacked(ptBuf, sessionKey);
|
|
453
453
|
var encrypted = { _ct: ctBuf.toString("base64") };
|
|
454
454
|
if (sessionCtx) {
|
|
455
455
|
encrypted._sid = sessionCtx.sid;
|
|
@@ -480,7 +480,7 @@ function create(opts) {
|
|
|
480
480
|
function _decryptEkToSessionKey(ek) {
|
|
481
481
|
for (var ki = 0; ki < keypairs.length; ki++) {
|
|
482
482
|
try {
|
|
483
|
-
var sessionKeyB64 =
|
|
483
|
+
var sessionKeyB64 = bCrypto.decrypt(ek, keypairs[ki]);
|
|
484
484
|
var candidate = Buffer.from(sessionKeyB64, "base64");
|
|
485
485
|
if (candidate.length === SESSION_KEY_BYTES) return candidate;
|
|
486
486
|
} catch (_e) { /* try next keypair */ }
|
|
@@ -518,7 +518,7 @@ function create(opts) {
|
|
|
518
518
|
|
|
519
519
|
if (typeof ek === "string" && typeof nonce === "string") {
|
|
520
520
|
// ---- Bootstrap path (per-request mode OR first request of session) ----
|
|
521
|
-
var nonceHash =
|
|
521
|
+
var nonceHash = bCrypto.sha3Hash(nonce, "hex");
|
|
522
522
|
var expireAt = now + replayWindowMs;
|
|
523
523
|
var freshNonce;
|
|
524
524
|
try { freshNonce = await nonceStore.checkAndInsert(nonceHash, expireAt); }
|
|
@@ -655,7 +655,7 @@ function create(opts) {
|
|
|
655
655
|
var clearObj;
|
|
656
656
|
try {
|
|
657
657
|
var ctBuf = Buffer.from(ct, "base64");
|
|
658
|
-
var ptBuf =
|
|
658
|
+
var ptBuf = bCrypto.decryptPacked(ctBuf, sessionKey);
|
|
659
659
|
clearObj = safeJson.parse(ptBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
|
|
660
660
|
} catch (_e) {
|
|
661
661
|
_emitFailure(req, "tag");
|
|
@@ -751,7 +751,7 @@ function client(opts) {
|
|
|
751
751
|
var perSessionLastResCtr = 0;
|
|
752
752
|
|
|
753
753
|
function _resetSession() {
|
|
754
|
-
perSessionKey =
|
|
754
|
+
perSessionKey = bCrypto.generateBytes(SESSION_KEY_BYTES);
|
|
755
755
|
perSessionSid = _generateUuidV4();
|
|
756
756
|
perSessionReqCtr = 0;
|
|
757
757
|
perSessionLastResCtr = 0;
|
|
@@ -774,7 +774,7 @@ function client(opts) {
|
|
|
774
774
|
}
|
|
775
775
|
perSessionLastResCtr = responseBody._ctr;
|
|
776
776
|
var resCtBuf = Buffer.from(responseBody._ct, "base64");
|
|
777
|
-
var resPtBuf =
|
|
777
|
+
var resPtBuf = bCrypto.decryptPacked(resCtBuf, perSessionKey);
|
|
778
778
|
return safeJson.parse(resPtBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
|
|
779
779
|
}
|
|
780
780
|
|
|
@@ -783,13 +783,13 @@ function client(opts) {
|
|
|
783
783
|
if (!perSessionKey) _resetSession();
|
|
784
784
|
var ts = Date.now();
|
|
785
785
|
var ptBuf = Buffer.from(JSON.stringify(payload), "utf8");
|
|
786
|
-
var ctBuf =
|
|
786
|
+
var ctBuf = bCrypto.encryptPacked(ptBuf, perSessionKey);
|
|
787
787
|
perSessionReqCtr += 1;
|
|
788
788
|
var body;
|
|
789
789
|
if (perSessionReqCtr === 1) {
|
|
790
790
|
// Bootstrap envelope — full _ek + _nonce; server stores sid → sessionKey.
|
|
791
|
-
var ek =
|
|
792
|
-
var nonce =
|
|
791
|
+
var ek = bCrypto.encrypt(perSessionKey.toString("base64"), pubkey);
|
|
792
|
+
var nonce = bCrypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
|
|
793
793
|
body = {
|
|
794
794
|
_ek: ek,
|
|
795
795
|
_ct: ctBuf.toString("base64"),
|
|
@@ -812,11 +812,11 @@ function client(opts) {
|
|
|
812
812
|
|
|
813
813
|
function _encryptPerRequest(payload) {
|
|
814
814
|
if (payload === undefined) payload = null;
|
|
815
|
-
var sessionKey =
|
|
816
|
-
var ek =
|
|
815
|
+
var sessionKey = bCrypto.generateBytes(SESSION_KEY_BYTES);
|
|
816
|
+
var ek = bCrypto.encrypt(sessionKey.toString("base64"), pubkey);
|
|
817
817
|
var ptBuf = Buffer.from(JSON.stringify(payload), "utf8");
|
|
818
|
-
var ctBuf =
|
|
819
|
-
var requestNonce =
|
|
818
|
+
var ctBuf = bCrypto.encryptPacked(ptBuf, sessionKey);
|
|
819
|
+
var requestNonce = bCrypto.generateBytes(REQUEST_NONCE_BYTES).toString("hex");
|
|
820
820
|
var ts = Date.now();
|
|
821
821
|
return {
|
|
822
822
|
body: {
|
|
@@ -832,7 +832,7 @@ function client(opts) {
|
|
|
832
832
|
"apiEncrypt.client: response missing _ct field");
|
|
833
833
|
}
|
|
834
834
|
var resCtBuf = Buffer.from(responseBody._ct, "base64");
|
|
835
|
-
var resPtBuf =
|
|
835
|
+
var resPtBuf = bCrypto.decryptPacked(resCtBuf, sessionKey);
|
|
836
836
|
return safeJson.parse(resPtBuf.toString("utf8"), { maxBytes: maxDecryptedBytes });
|
|
837
837
|
},
|
|
838
838
|
};
|
|
@@ -857,7 +857,7 @@ function client(opts) {
|
|
|
857
857
|
// Slice offsets are RFC 4122 UUID hex-byte boundaries (`xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`)
|
|
858
858
|
// — protocol-fixed values, not byte sizes. allow:raw-byte-literal
|
|
859
859
|
function _generateUuidV4() {
|
|
860
|
-
var b =
|
|
860
|
+
var b = bCrypto.generateBytes(16); // allow:raw-byte-literal — UUID is exactly 16 bytes
|
|
861
861
|
// Set version (4) and variant (10x) bits per RFC 4122.
|
|
862
862
|
b[6] = (b[6] & 0x0f) | 0x40;
|
|
863
863
|
b[8] = (b[8] & 0x3f) | 0x80;
|