@blamejs/core 0.14.4 → 0.14.6
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 +4 -0
- package/README.md +1 -0
- package/lib/a2a-tasks.js +6 -6
- package/lib/ai-input.js +1 -1
- package/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/calendar.js +6 -6
- package/lib/content-credentials.js +2 -2
- package/lib/cra-report.js +3 -3
- package/lib/guard-cidr.js +1 -1
- package/lib/http-client-cache.js +1 -1
- package/lib/mail-auth.js +1 -1
- package/lib/mail-crypto-smime.js +1 -1
- package/lib/mail-deploy.js +1 -1
- package/lib/mail-dkim.js +1 -1
- package/lib/mail-server-jmap.js +2 -2
- package/lib/mcp.js +6 -6
- package/lib/middleware/age-gate.js +20 -7
- package/lib/middleware/bearer-auth.js +36 -35
- package/lib/middleware/bot-guard.js +17 -5
- package/lib/middleware/compose-pipeline.js +1 -1
- package/lib/middleware/cors.js +28 -12
- package/lib/middleware/csrf-protect.js +22 -14
- package/lib/middleware/daily-byte-quota.js +27 -13
- package/lib/middleware/deny-response.js +140 -0
- package/lib/middleware/dpop.js +32 -19
- package/lib/middleware/fetch-metadata.js +21 -12
- package/lib/middleware/host-allowlist.js +19 -8
- package/lib/middleware/index.js +3 -0
- package/lib/middleware/network-allowlist.js +24 -10
- package/lib/middleware/rate-limit.js +22 -5
- package/lib/middleware/require-aal.js +25 -10
- package/lib/middleware/require-auth.js +32 -16
- package/lib/middleware/require-bound-key.js +49 -18
- package/lib/middleware/require-content-type.js +19 -8
- package/lib/middleware/require-methods.js +17 -7
- package/lib/middleware/require-mtls.js +27 -14
- package/lib/network.js +4 -4
- package/lib/safe-decompress.js +1 -1
- package/lib/safe-url.js +1 -1
- package/lib/stream-throttle.js +2 -2
- package/lib/websocket.js +2 -2
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
var lazyRequire = require("../lazy-require");
|
|
19
|
+
var denyResponse = require("./deny-response").denyResponse;
|
|
19
20
|
var { defineClass } = require("../framework-error");
|
|
20
21
|
|
|
21
22
|
var RequireMethodsError = defineClass("RequireMethodsError", { alwaysPermanent: true });
|
|
@@ -38,7 +39,9 @@ var observability = lazyRequire(function () { return require("../observability")
|
|
|
38
39
|
*
|
|
39
40
|
* @opts
|
|
40
41
|
* {
|
|
41
|
-
* audit:
|
|
42
|
+
* audit: boolean, // default true
|
|
43
|
+
* onDeny: function(req, res, info): void, // own the 405; info = { status, reason, method, allowed }
|
|
44
|
+
* problemDetails: boolean, // default false — emit RFC 9457 application/problem+json instead of text/plain
|
|
42
45
|
* }
|
|
43
46
|
*
|
|
44
47
|
* @example
|
|
@@ -69,18 +72,25 @@ function create(allowed, opts) {
|
|
|
69
72
|
var allowHeader = normalized.join(", ");
|
|
70
73
|
opts = opts || {};
|
|
71
74
|
var auditOn = opts.audit !== false;
|
|
75
|
+
var onDeny = typeof opts.onDeny === "function" ? opts.onDeny : null;
|
|
76
|
+
var problemMode = opts.problemDetails === true;
|
|
72
77
|
|
|
73
78
|
return function requireMethodsMiddleware(req, res, next) {
|
|
74
79
|
var m = (req.method || "").toUpperCase();
|
|
75
80
|
if (normalized.indexOf(m) !== -1) return next();
|
|
76
81
|
if (!res.headersSent) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
+
denyResponse(req, res, {
|
|
83
|
+
onDeny: onDeny,
|
|
84
|
+
problem: problemMode,
|
|
85
|
+
status: 405,
|
|
86
|
+
info: { status: 405, reason: "method-not-allowed", method: m, allowed: normalized },
|
|
87
|
+
problemCode: "method-not-allowed",
|
|
88
|
+
problemTitle: "Method Not Allowed",
|
|
89
|
+
problemDetail: "The " + m + " method is not allowed on this resource.",
|
|
90
|
+
headers: { "Allow": allowHeader },
|
|
91
|
+
contentType: "text/plain; charset=utf-8",
|
|
92
|
+
body: "Method Not Allowed",
|
|
82
93
|
});
|
|
83
|
-
res.end(body);
|
|
84
94
|
}
|
|
85
95
|
if (auditOn) {
|
|
86
96
|
try {
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
var defineClass = require("../framework-error").defineClass;
|
|
49
49
|
var lazyRequire = require("../lazy-require");
|
|
50
50
|
var validateOpts = require("../validate-opts");
|
|
51
|
+
var denyResponse = require("./deny-response").denyResponse;
|
|
51
52
|
|
|
52
53
|
var bCrypto = lazyRequire(function () { return require("../crypto"); });
|
|
53
54
|
var audit = lazyRequire(function () { return require("../audit"); });
|
|
@@ -84,6 +85,8 @@ function _normalizeFingerprintEntry(entry) {
|
|
|
84
85
|
* fingerprintAllowList: string[],
|
|
85
86
|
* denyList: string[],
|
|
86
87
|
* onAuthenticated: function(req, res, next): void,
|
|
88
|
+
* onDeny: function(req, res, info): void, // own the refusal (mirrors onAuthenticated); info = { status, reason, ...metadata }
|
|
89
|
+
* problemDetails: boolean, // default false — emit RFC 9457 application/problem+json instead of the default JSON envelope
|
|
87
90
|
* auditAction: string,
|
|
88
91
|
* errorMessage: string,
|
|
89
92
|
* audit: object,
|
|
@@ -100,7 +103,7 @@ function create(opts) {
|
|
|
100
103
|
opts = opts || {};
|
|
101
104
|
validateOpts(opts, [
|
|
102
105
|
"fingerprintAllowList", "denyList",
|
|
103
|
-
"onAuthenticated", "audit",
|
|
106
|
+
"onAuthenticated", "onDeny", "problemDetails", "audit",
|
|
104
107
|
"auditAction", "errorMessage",
|
|
105
108
|
], "middleware.requireMtls");
|
|
106
109
|
|
|
@@ -109,6 +112,8 @@ function create(opts) {
|
|
|
109
112
|
var denyList = Array.isArray(opts.denyList)
|
|
110
113
|
? opts.denyList.map(_normalizeFingerprintEntry) : [];
|
|
111
114
|
var onAuthenticated = typeof opts.onAuthenticated === "function" ? opts.onAuthenticated : null;
|
|
115
|
+
var onDeny = typeof opts.onDeny === "function" ? opts.onDeny : null;
|
|
116
|
+
var problemMode = opts.problemDetails === true;
|
|
112
117
|
var auditOn = opts.audit !== false;
|
|
113
118
|
var actionBase = typeof opts.auditAction === "string" && opts.auditAction.length > 0
|
|
114
119
|
? opts.auditAction : "mtls.required";
|
|
@@ -126,16 +131,24 @@ function create(opts) {
|
|
|
126
131
|
} catch (_e) { /* drop-silent — audit is best-effort, never blocks the request */ }
|
|
127
132
|
}
|
|
128
133
|
|
|
129
|
-
function _refuse(res, reason, metadata) {
|
|
134
|
+
function _refuse(req, res, reason, metadata) {
|
|
130
135
|
_emit("denied", Object.assign({ reason: reason }, metadata || {}));
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
denyResponse(req, res, {
|
|
137
|
+
onDeny: onDeny,
|
|
138
|
+
problem: problemMode,
|
|
139
|
+
status: 401,
|
|
140
|
+
info: Object.assign({ status: 401, reason: reason }, metadata || {}),
|
|
141
|
+
problemCode: "client-certificate-required",
|
|
142
|
+
problemTitle: "Unauthorized",
|
|
143
|
+
problemDetail: errorMessage,
|
|
144
|
+
problemExt: { reason: reason },
|
|
145
|
+
headers: {
|
|
134
146
|
"WWW-Authenticate": "Mutual",
|
|
135
147
|
"Cache-Control": "no-store",
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
},
|
|
149
|
+
contentType: "application/json; charset=utf-8",
|
|
150
|
+
body: JSON.stringify({ error: errorMessage, reason: reason }),
|
|
151
|
+
});
|
|
139
152
|
}
|
|
140
153
|
|
|
141
154
|
return function requireMtlsMiddleware(req, res, next) {
|
|
@@ -158,10 +171,10 @@ function create(opts) {
|
|
|
158
171
|
|
|
159
172
|
if (!authorized) {
|
|
160
173
|
var authzError = (sock && sock.authorizationError) || "no-peer-cert";
|
|
161
|
-
return _refuse(res, "tls-unauthorized", { authorizationError: String(authzError) });
|
|
174
|
+
return _refuse(req, res, "tls-unauthorized", { authorizationError: String(authzError) });
|
|
162
175
|
}
|
|
163
176
|
if (!peerCert || !peerCert.raw) {
|
|
164
|
-
return _refuse(res, "no-peer-cert", {});
|
|
177
|
+
return _refuse(req, res, "no-peer-cert", {});
|
|
165
178
|
}
|
|
166
179
|
|
|
167
180
|
// Compute fingerprint via the framework's SHA3-512 helper. Buffer
|
|
@@ -171,17 +184,17 @@ function create(opts) {
|
|
|
171
184
|
try {
|
|
172
185
|
fp = bCrypto().hashCertFingerprint(peerCert.raw);
|
|
173
186
|
} catch (e) {
|
|
174
|
-
return _refuse(res, "fingerprint-failed", { error: (e && e.message) || String(e) });
|
|
187
|
+
return _refuse(req, res, "fingerprint-failed", { error: (e && e.message) || String(e) });
|
|
175
188
|
}
|
|
176
189
|
|
|
177
190
|
if (denyList.length > 0 && bCrypto().isCertRevoked(peerCert.raw, denyList)) {
|
|
178
|
-
return _refuse(res, "fingerprint-on-deny-list", {
|
|
191
|
+
return _refuse(req, res, "fingerprint-on-deny-list", {
|
|
179
192
|
fingerprint: fp.colon,
|
|
180
193
|
subject: (peerCert.subject && peerCert.subject.CN) || null,
|
|
181
194
|
});
|
|
182
195
|
}
|
|
183
196
|
if (allowList && allowList.length > 0 && !bCrypto().isCertRevoked(peerCert.raw, allowList)) {
|
|
184
|
-
return _refuse(res, "fingerprint-not-allowed", {
|
|
197
|
+
return _refuse(req, res, "fingerprint-not-allowed", {
|
|
185
198
|
fingerprint: fp.colon,
|
|
186
199
|
subject: (peerCert.subject && peerCert.subject.CN) || null,
|
|
187
200
|
});
|
|
@@ -199,7 +212,7 @@ function create(opts) {
|
|
|
199
212
|
if (onAuthenticated) {
|
|
200
213
|
try { return onAuthenticated(req, res, next); }
|
|
201
214
|
catch (e) {
|
|
202
|
-
return _refuse(res, "on-authenticated-threw", { error: (e && e.message) || String(e) });
|
|
215
|
+
return _refuse(req, res, "on-authenticated-threw", { error: (e && e.message) || String(e) });
|
|
203
216
|
}
|
|
204
217
|
}
|
|
205
218
|
return next();
|
package/lib/network.js
CHANGED
|
@@ -108,8 +108,8 @@ function _socketDefaults() {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
* @primitive b.network.applyToSocket
|
|
112
|
-
* @signature b.network.applyToSocket(socket)
|
|
111
|
+
* @primitive b.network.socket.applyToSocket
|
|
112
|
+
* @signature b.network.socket.applyToSocket(socket)
|
|
113
113
|
* @since 0.7.68
|
|
114
114
|
* @related b.network.bootFromEnv, b.network.snapshot
|
|
115
115
|
*
|
|
@@ -124,7 +124,7 @@ function _socketDefaults() {
|
|
|
124
124
|
* @example
|
|
125
125
|
* var net = require("net");
|
|
126
126
|
* var s = new net.Socket();
|
|
127
|
-
* var ret = b.network.applyToSocket(s);
|
|
127
|
+
* var ret = b.network.socket.applyToSocket(s);
|
|
128
128
|
* ret === s;
|
|
129
129
|
* // → true
|
|
130
130
|
* s.destroy();
|
|
@@ -164,7 +164,7 @@ var ntpFacade = {
|
|
|
164
164
|
* @primitive b.network.bootFromEnv
|
|
165
165
|
* @signature b.network.bootFromEnv(opts)
|
|
166
166
|
* @since 0.7.68
|
|
167
|
-
* @related b.network.snapshot, b.network.applyToSocket
|
|
167
|
+
* @related b.network.snapshot, b.network.socket.applyToSocket
|
|
168
168
|
*
|
|
169
169
|
* Read `BLAMEJS_*` environment variables once and apply the union to
|
|
170
170
|
* the live network facade. Recognised keys cover NTP servers /
|
package/lib/safe-decompress.js
CHANGED
|
@@ -105,7 +105,7 @@ var _algorithms = {
|
|
|
105
105
|
// classic bomb shapes (1000:1) while leaving headroom for legitimate
|
|
106
106
|
// text / JSON / XML payloads (which compress 20-50:1 commonly). Per
|
|
107
107
|
// RFC 8460 §5.2 community guidance for TLS-RPT report decompression.
|
|
108
|
-
var DEFAULT_MAX_RATIO = 50; // allow:raw-
|
|
108
|
+
var DEFAULT_MAX_RATIO = 50; // allow:raw-time-literal — RFC number not seconds
|
|
109
109
|
|
|
110
110
|
// Default input cap when operator omits opts.maxCompressedBytes —
|
|
111
111
|
// 4 MiB matches the TLS-RPT receive surface and is a reasonable
|
package/lib/safe-url.js
CHANGED
|
@@ -407,7 +407,7 @@ function format(url) {
|
|
|
407
407
|
}
|
|
408
408
|
// Constructing URL() is the path that surfaces the IDN-crash on
|
|
409
409
|
// older Node — wrap so the listener never crashes.
|
|
410
|
-
var u = new URL(url); // allow:raw-new-url — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
|
|
410
|
+
var u = new URL(url); // allow:raw-new-url — safeUrl.format wraps URL ctor for CVE-2026-21712; this IS the safe wrapper.
|
|
411
411
|
return u.href;
|
|
412
412
|
} catch (e) {
|
|
413
413
|
if (e && e.isSafeUrlError) throw e;
|
package/lib/stream-throttle.js
CHANGED
|
@@ -71,9 +71,9 @@ var StreamThrottleError = defineClass("StreamThrottleError", { alwaysPermanent:
|
|
|
71
71
|
// (bytes/sec ↔ wait-ms). This is a unit-conversion constant, not a
|
|
72
72
|
// memory cap or protocol-byte literal; the framework's C.TIME / C.BYTES
|
|
73
73
|
// helpers don't apply.
|
|
74
|
-
var MS_PER_SECOND = 1000; // allow:raw-
|
|
74
|
+
var MS_PER_SECOND = 1000; // allow:raw-time-literal — ms/sec unit conversion
|
|
75
75
|
var NS_PER_MS = 1e6; // ns/ms unit conversion
|
|
76
|
-
var MS_PER_SECOND_HRTIME = 1000; // allow:raw-
|
|
76
|
+
var MS_PER_SECOND_HRTIME = 1000; // allow:raw-time-literal — hrtime seconds→ms
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* @primitive b.streamThrottle.create
|
package/lib/websocket.js
CHANGED
|
@@ -190,8 +190,8 @@ var CLOSE_GRACE_MS = C.TIME.seconds(2);
|
|
|
190
190
|
// invalid.
|
|
191
191
|
function _isValidCloseCode(code) {
|
|
192
192
|
if (code === 1004 || code === 1005 || code === 1006 || code === 1015) return false; // RFC 6455 §7.4.2 reserved codes
|
|
193
|
-
if (code >= 1000 && code <= 1011) return true; // allow:raw-
|
|
194
|
-
if (code >= 3000 && code <= 4999) return true; // allow:raw-
|
|
193
|
+
if (code >= 1000 && code <= 1011) return true; // allow:raw-time-literal — code is a numeric, not seconds
|
|
194
|
+
if (code >= 3000 && code <= 4999) return true; // allow:raw-time-literal — code is a numeric, not seconds
|
|
195
195
|
return false;
|
|
196
196
|
}
|
|
197
197
|
|
package/package.json
CHANGED
package/sbom.cdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
|
3
3
|
"bomFormat": "CycloneDX",
|
|
4
4
|
"specVersion": "1.5",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:ba3e9bdd-f642-4d42-a03c-794d89554a0a",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-05-
|
|
8
|
+
"timestamp": "2026-05-30T16:30:23.236Z",
|
|
9
9
|
"lifecycles": [
|
|
10
10
|
{
|
|
11
11
|
"phase": "build"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"component": {
|
|
22
|
-
"bom-ref": "@blamejs/core@0.14.
|
|
22
|
+
"bom-ref": "@blamejs/core@0.14.6",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "blamejs",
|
|
25
|
-
"version": "0.14.
|
|
25
|
+
"version": "0.14.6",
|
|
26
26
|
"scope": "required",
|
|
27
27
|
"author": "blamejs contributors",
|
|
28
28
|
"description": "The Node framework that owns its stack.",
|
|
29
|
-
"purl": "pkg:npm/%40blamejs/core@0.14.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/core@0.14.6",
|
|
30
30
|
"properties": [],
|
|
31
31
|
"externalReferences": [
|
|
32
32
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"components": [],
|
|
55
55
|
"dependencies": [
|
|
56
56
|
{
|
|
57
|
-
"ref": "@blamejs/core@0.14.
|
|
57
|
+
"ref": "@blamejs/core@0.14.6",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|