@blamejs/core 0.14.1 → 0.14.2
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/_test/crypto-fixtures.js +3 -3
- package/lib/a2a-tasks.js +18 -18
- package/lib/a2a.js +4 -4
- package/lib/acme.js +3 -3
- package/lib/agent-idempotency.js +1 -1
- package/lib/agent-orchestrator.js +8 -8
- package/lib/agent-posture-chain.js +2 -2
- package/lib/agent-saga.js +1 -1
- package/lib/agent-snapshot.js +1 -1
- package/lib/agent-stream.js +1 -1
- package/lib/agent-tenant.js +1 -1
- package/lib/agent-trace.js +3 -3
- package/lib/ai-capability.js +1 -1
- package/lib/ai-dp.js +4 -4
- package/lib/ai-input.js +3 -3
- package/lib/ai-model-manifest.js +7 -7
- package/lib/ai-pref.js +3 -3
- package/lib/archive-gz.js +2 -2
- package/lib/archive-read.js +25 -25
- package/lib/archive-tar-read.js +2 -2
- package/lib/archive-tar.js +20 -20
- package/lib/archive-wrap.js +10 -10
- package/lib/argon2-builtin.js +1 -1
- package/lib/asn1-der.js +34 -34
- package/lib/atomic-file.js +2 -2
- package/lib/audit-daily-review.js +3 -3
- package/lib/audit-sign.js +5 -5
- package/lib/audit-tools.js +1 -1
- package/lib/audit.js +2 -2
- package/lib/auth/acr-vocabulary.js +2 -2
- package/lib/auth/bot-challenge.js +3 -3
- package/lib/auth/ciba.js +7 -7
- package/lib/auth/dpop.js +3 -3
- package/lib/auth/fido-mds3.js +8 -8
- package/lib/auth/jwt-external.js +5 -5
- package/lib/auth/oauth.js +2 -2
- package/lib/auth/oid4vci.js +9 -9
- package/lib/auth/oid4vp.js +2 -2
- package/lib/auth/openid-federation.js +2 -2
- package/lib/auth/passkey.js +3 -3
- package/lib/auth/saml.js +23 -23
- package/lib/auth/sd-jwt-vc-disclosure.js +1 -1
- package/lib/auth/sd-jwt-vc.js +4 -4
- package/lib/auth/status-list.js +10 -10
- package/lib/auth/step-up.js +1 -1
- package/lib/auth-bot-challenge.js +1 -1
- package/lib/backup/index.js +7 -7
- package/lib/base32.js +8 -8
- package/lib/budr.js +2 -2
- package/lib/cache-status.js +2 -2
- package/lib/calendar.js +23 -23
- package/lib/cbor.js +12 -12
- package/lib/cdn-cache-control.js +1 -1
- package/lib/cert.js +5 -5
- package/lib/cloud-events.js +5 -5
- package/lib/cms-codec.js +21 -21
- package/lib/codepoint-class.js +12 -12
- package/lib/compliance-sanctions-fuzzy.js +4 -4
- package/lib/compliance-sanctions.js +4 -4
- package/lib/compliance.js +29 -29
- package/lib/content-credentials.js +36 -36
- package/lib/cookies.js +1 -1
- package/lib/cose.js +13 -13
- package/lib/cra-report.js +1 -1
- package/lib/crdt.js +1 -1
- package/lib/crypto-field.js +2 -2
- package/lib/crypto-xwing.js +7 -7
- package/lib/crypto.js +6 -6
- package/lib/csp.js +2 -2
- package/lib/cwt.js +4 -4
- package/lib/dark-patterns.js +2 -2
- package/lib/data-act.js +2 -2
- package/lib/db-file-lifecycle.js +4 -4
- package/lib/db-query.js +1 -1
- package/lib/db.js +6 -6
- package/lib/dbsc.js +13 -13
- package/lib/did.js +17 -17
- package/lib/dora.js +4 -4
- package/lib/dsr.js +1 -1
- package/lib/early-hints.js +2 -2
- package/lib/eat.js +4 -4
- package/lib/external-db-migrate.js +1 -1
- package/lib/external-db.js +1 -1
- package/lib/flag-cache.js +1 -1
- package/lib/flag-evaluation-context.js +2 -2
- package/lib/graphql-federation.js +4 -4
- package/lib/guard-agent-registry.js +5 -5
- package/lib/guard-archive.js +24 -24
- package/lib/guard-cidr.js +33 -33
- package/lib/guard-csv.js +1 -1
- package/lib/guard-domain.js +10 -10
- package/lib/guard-dsn.js +4 -4
- package/lib/guard-email.js +19 -19
- package/lib/guard-event-bus-payload.js +4 -4
- package/lib/guard-event-bus-topic.js +6 -6
- package/lib/guard-filename.js +7 -7
- package/lib/guard-graphql.js +9 -9
- package/lib/guard-html-wcag-tagwalk.js +1 -1
- package/lib/guard-html-wcag.js +4 -4
- package/lib/guard-html.js +7 -7
- package/lib/guard-idempotency-key.js +6 -6
- package/lib/guard-image.js +4 -4
- package/lib/guard-imap-command.js +17 -17
- package/lib/guard-jmap.js +20 -20
- package/lib/guard-json.js +12 -12
- package/lib/guard-jsonpath.js +3 -3
- package/lib/guard-jwt.js +4 -4
- package/lib/guard-list-id.js +7 -7
- package/lib/guard-list-unsubscribe.js +8 -8
- package/lib/guard-mail-compose.js +4 -4
- package/lib/guard-mail-move.js +5 -5
- package/lib/guard-mail-query.js +3 -3
- package/lib/guard-mail-reply.js +3 -3
- package/lib/guard-mail-sieve.js +6 -6
- package/lib/guard-managesieve-command.js +25 -25
- package/lib/guard-markdown.js +31 -31
- package/lib/guard-message-id.js +5 -5
- package/lib/guard-mime.js +1 -1
- package/lib/guard-oauth.js +3 -3
- package/lib/guard-pdf.js +6 -6
- package/lib/guard-pop3-command.js +11 -11
- package/lib/guard-posture-chain.js +5 -5
- package/lib/guard-regex.js +10 -10
- package/lib/guard-saga-config.js +5 -5
- package/lib/guard-smtp-command.js +6 -6
- package/lib/guard-snapshot-envelope.js +3 -3
- package/lib/guard-stream-args.js +4 -4
- package/lib/guard-svg.js +11 -11
- package/lib/guard-tenant-id.js +5 -5
- package/lib/guard-time.js +15 -15
- package/lib/guard-trace-context.js +4 -4
- package/lib/guard-uuid.js +11 -11
- package/lib/guard-xml.js +12 -12
- package/lib/guard-yaml.js +16 -16
- package/lib/honeytoken.js +5 -5
- package/lib/http-client.js +1 -1
- package/lib/http-message-signature.js +2 -2
- package/lib/iab-mspa.js +3 -3
- package/lib/iab-tcf.js +70 -70
- package/lib/inbox.js +4 -4
- package/lib/ip-utils.js +15 -15
- package/lib/jose-jwe-experimental.js +2 -2
- package/lib/json-path.js +3 -3
- package/lib/json-schema.js +1 -1
- package/lib/jsonapi.js +3 -3
- package/lib/jtd.js +2 -2
- package/lib/link-header.js +1 -1
- package/lib/local-db-thin.js +1 -1
- package/lib/log.js +1 -1
- package/lib/lro.js +4 -4
- package/lib/mail-agent.js +1 -1
- package/lib/mail-arc-sign.js +6 -6
- package/lib/mail-auth.js +43 -43
- package/lib/mail-bimi.js +3 -3
- package/lib/mail-crypto-pgp.js +31 -31
- package/lib/mail-crypto-smime.js +5 -5
- package/lib/mail-dav.js +1 -1
- package/lib/mail-deploy.js +39 -39
- package/lib/mail-dkim.js +11 -11
- package/lib/mail-greylist.js +12 -12
- package/lib/mail-helo.js +1 -1
- package/lib/mail-journal.js +8 -8
- package/lib/mail-rbl.js +7 -7
- package/lib/mail-scan.js +7 -7
- package/lib/mail-send-deliver.js +2 -2
- package/lib/mail-server-imap.js +12 -12
- package/lib/mail-server-jmap.js +16 -16
- package/lib/mail-server-managesieve.js +4 -4
- package/lib/mail-server-mx.js +17 -17
- package/lib/mail-server-pop3.js +4 -4
- package/lib/mail-server-rate-limit.js +2 -2
- package/lib/mail-server-submission.js +21 -21
- package/lib/mail-sieve.js +2 -2
- package/lib/mail-spam-score.js +5 -5
- package/lib/mail-srs.js +12 -12
- package/lib/mail-store-fts.js +2 -2
- package/lib/mail-store.js +8 -8
- package/lib/mail-unsubscribe.js +4 -4
- package/lib/mail.js +4 -4
- package/lib/mcp-tool-registry.js +4 -4
- package/lib/mcp.js +8 -8
- package/lib/mdoc.js +2 -2
- package/lib/metrics.js +8 -8
- package/lib/middleware/age-gate.js +1 -1
- package/lib/middleware/api-encrypt.js +7 -7
- package/lib/middleware/assetlinks.js +2 -2
- package/lib/middleware/asyncapi-serve.js +2 -2
- package/lib/middleware/bearer-auth.js +5 -5
- package/lib/middleware/body-parser.js +5 -5
- package/lib/middleware/compose-pipeline.js +15 -15
- package/lib/middleware/csp-report.js +4 -4
- package/lib/middleware/daily-byte-quota.js +1 -1
- package/lib/middleware/dpop.js +1 -1
- package/lib/middleware/headers.js +2 -2
- package/lib/middleware/host-allowlist.js +1 -1
- package/lib/middleware/idempotency-key.js +12 -12
- package/lib/middleware/nel.js +1 -1
- package/lib/middleware/openapi-serve.js +2 -2
- package/lib/middleware/protected-resource-metadata.js +2 -2
- package/lib/middleware/require-aal.js +1 -1
- package/lib/middleware/require-bound-key.js +2 -2
- package/lib/middleware/require-content-type.js +1 -1
- package/lib/middleware/require-methods.js +1 -1
- package/lib/middleware/require-step-up.js +2 -2
- package/lib/middleware/scim-server.js +1 -1
- package/lib/middleware/security-txt.js +3 -3
- package/lib/middleware/tus-upload.js +12 -12
- package/lib/middleware/web-app-manifest.js +2 -2
- package/lib/network-byte-quota.js +1 -1
- package/lib/network-dns-resolver.js +23 -23
- package/lib/network-dns.js +29 -29
- package/lib/network-dnssec.js +33 -33
- package/lib/network-smtp-policy.js +10 -10
- package/lib/network-tls.js +87 -87
- package/lib/network-tsig.js +33 -33
- package/lib/nis2-report.js +1 -1
- package/lib/ntp-check.js +3 -3
- package/lib/observability-otlp-exporter.js +17 -17
- package/lib/observability-tracer.js +6 -6
- package/lib/observability.js +8 -8
- package/lib/openapi-yaml.js +1 -1
- package/lib/openapi.js +1 -1
- package/lib/outbox.js +6 -6
- package/lib/pqc-agent.js +4 -4
- package/lib/pqc-software.js +1 -1
- package/lib/privacy-pass.js +5 -5
- package/lib/problem-details.js +5 -5
- package/lib/promise-pool.js +1 -1
- package/lib/protobuf-encoder.js +1 -1
- package/lib/redact.js +2 -2
- package/lib/request-helpers.js +1 -1
- package/lib/router.js +10 -10
- package/lib/safe-async.js +2 -2
- package/lib/safe-dns.js +71 -71
- package/lib/safe-ical.js +19 -19
- package/lib/safe-icap.js +24 -24
- package/lib/safe-jsonpath.js +2 -2
- package/lib/safe-mime.js +10 -10
- package/lib/safe-mount-info.js +3 -3
- package/lib/safe-redirect.js +1 -1
- package/lib/safe-sieve.js +23 -23
- package/lib/safe-smtp.js +1 -1
- package/lib/safe-vcard.js +14 -14
- package/lib/sandbox.js +5 -5
- package/lib/sec-cyber.js +1 -1
- package/lib/self-update-standalone-verifier.js +3 -3
- package/lib/self-update.js +3 -3
- package/lib/server-timing.js +3 -3
- package/lib/session-device-binding.js +7 -7
- package/lib/session.js +8 -8
- package/lib/standard-webhooks.js +4 -4
- package/lib/storage.js +2 -2
- package/lib/stream-throttle.js +1 -1
- package/lib/structured-fields.js +15 -15
- package/lib/subject.js +1 -1
- package/lib/tcpa-10dlc.js +1 -1
- package/lib/tenant-quota.js +3 -3
- package/lib/test-harness.js +1 -1
- package/lib/tracing.js +1 -1
- package/lib/tsa.js +5 -5
- package/lib/uri-template.js +5 -5
- package/lib/vault/index.js +2 -2
- package/lib/vault/seal-pem-file.js +4 -4
- package/lib/vc.js +2 -2
- package/lib/vendor-data.js +1 -1
- package/lib/watcher.js +4 -4
- package/lib/web-push-vapid.js +21 -21
- package/lib/webhook.js +2 -2
- package/lib/websocket.js +3 -3
- package/lib/worker-pool.js +3 -3
- package/lib/ws-client.js +24 -24
- package/lib/xml-c14n.js +2 -2
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/mail-store.js
CHANGED
|
@@ -275,7 +275,7 @@ function create(opts) {
|
|
|
275
275
|
var f = filter || {};
|
|
276
276
|
var sinceModseq = f.sinceModseq || 0;
|
|
277
277
|
var limit = f.limit || 100;
|
|
278
|
-
if (limit > 1000) limit = 1000; //
|
|
278
|
+
if (limit > 1000) limit = 1000; // query row cap, not bytes
|
|
279
279
|
|
|
280
280
|
var matchClauses = [];
|
|
281
281
|
function addMatch(filterKey, term) {
|
|
@@ -342,7 +342,7 @@ function create(opts) {
|
|
|
342
342
|
"queryByModseq: folder '" + folderName + "' not found");
|
|
343
343
|
}
|
|
344
344
|
var sinceModseq = (queryOpts && queryOpts.sinceModseq) || 0;
|
|
345
|
-
var limit = (queryOpts && queryOpts.limit) || 1000; //
|
|
345
|
+
var limit = (queryOpts && queryOpts.limit) || 1000; // query row cap, not bytes
|
|
346
346
|
var rows = stmtQueryByModseq.all(folder.id, sinceModseq, limit);
|
|
347
347
|
return rows.map(function (r) {
|
|
348
348
|
return {
|
|
@@ -373,7 +373,7 @@ function create(opts) {
|
|
|
373
373
|
var fo = folderOpts || {};
|
|
374
374
|
var role = fo.role || null;
|
|
375
375
|
var parentId = fo.parentId || null;
|
|
376
|
-
var uidvalidity = Math.floor(Date.now() / 1000); //
|
|
376
|
+
var uidvalidity = Math.floor(Date.now() / 1000); // Unix timestamp, not bytes
|
|
377
377
|
stmtInsertFolder.run(name, role, parentId, uidvalidity);
|
|
378
378
|
return stmtGetFolderByName.get(name);
|
|
379
379
|
},
|
|
@@ -406,7 +406,7 @@ function create(opts) {
|
|
|
406
406
|
});
|
|
407
407
|
},
|
|
408
408
|
setLegalHold: function (objectids, holdOpts) {
|
|
409
|
-
var hold = (holdOpts && holdOpts.hold) ? 1 : 0; //
|
|
409
|
+
var hold = (holdOpts && holdOpts.hold) ? 1 : 0; // boolean cast for sqlite INTEGER column
|
|
410
410
|
objectids.forEach(function (oid) { stmtLegalHold.run(hold, oid); });
|
|
411
411
|
return { changed: objectids.length };
|
|
412
412
|
},
|
|
@@ -591,7 +591,7 @@ function _appendMessage(args) {
|
|
|
591
591
|
// token = 32-char hex = 128 bits, well above the birthday bound
|
|
592
592
|
// for any plausible message corpus. The prior `.slice(0, 24)` cut
|
|
593
593
|
// entropy to 96 bits; removed.
|
|
594
|
-
var objectid = "obj_" + bCrypto.generateToken(16); //
|
|
594
|
+
var objectid = "obj_" + bCrypto.generateToken(16); // 16-byte token, 32-char hex JMAP objectid (RFC 8474 §1.5.1)
|
|
595
595
|
var modseq = (folder.modseq_max || 0) + 1;
|
|
596
596
|
if (!threadRootId) threadRootId = objectid; // root of new thread
|
|
597
597
|
|
|
@@ -675,7 +675,7 @@ function _fetchByObjectId(args) {
|
|
|
675
675
|
bodyText: unsealed.body_text,
|
|
676
676
|
bodyHtml: unsealed.body_html,
|
|
677
677
|
flags: flags,
|
|
678
|
-
legalHold: row.legal_hold === 1, //
|
|
678
|
+
legalHold: row.legal_hold === 1, // sqlite INTEGER column 0|1
|
|
679
679
|
};
|
|
680
680
|
}
|
|
681
681
|
|
|
@@ -763,7 +763,7 @@ function _setFlags(args) {
|
|
|
763
763
|
// which both leaks a prepared-statement handle per chunk and
|
|
764
764
|
// doubles the SQL parse cost. Hold the stmt on a local + invoke
|
|
765
765
|
// .run() directly with the bound argument list.
|
|
766
|
-
var CHUNK = 500; //
|
|
766
|
+
var CHUNK = 500; // IN-clause chunk size, not bytes
|
|
767
767
|
for (var i = 0; i < args.objectids.length; i += CHUNK) {
|
|
768
768
|
var chunk = args.objectids.slice(i, i + CHUNK);
|
|
769
769
|
var placeholders = chunk.map(function () { return "?"; }).join(",");
|
|
@@ -915,7 +915,7 @@ function _ensureSchema(db, qMsgs, qFolders, qFlags, qQuota, qFts) {
|
|
|
915
915
|
function _ensureDefaultFolders(db, qFolders) {
|
|
916
916
|
var stmt = db.prepare("INSERT OR IGNORE INTO " + qFolders +
|
|
917
917
|
" (name, role, parent_id, modseq_max, uidvalidity) VALUES (?, ?, NULL, 0, ?)");
|
|
918
|
-
var uv = Math.floor(Date.now() / 1000); //
|
|
918
|
+
var uv = Math.floor(Date.now() / 1000); // Unix timestamp, not bytes
|
|
919
919
|
DEFAULT_FOLDERS.forEach(function (f) { stmt.run(f.name, f.role, uv); });
|
|
920
920
|
}
|
|
921
921
|
|
package/lib/mail-unsubscribe.js
CHANGED
|
@@ -75,7 +75,7 @@ var HEADER_VALUE_MAX_BYTES = C.BYTES.kib(2);
|
|
|
75
75
|
function _isLdhListLabel(label) {
|
|
76
76
|
if (typeof label !== "string" || label.length === 0) return false;
|
|
77
77
|
// RFC 1035 §2.3.4 — labels bounded at 63 octets.
|
|
78
|
-
if (label.length > 63) return false; //
|
|
78
|
+
if (label.length > 63) return false; // RFC 1035 §2.3.4 hostname-label limit
|
|
79
79
|
var n = label.length;
|
|
80
80
|
for (var i = 0; i < n; i += 1) {
|
|
81
81
|
var c = label.charCodeAt(i);
|
|
@@ -108,7 +108,7 @@ function _validateListId(value, label) {
|
|
|
108
108
|
if (bracket) inner = bracket[1];
|
|
109
109
|
// Inner is dot-separated labels; each label LDH per RFC 2919 §3.
|
|
110
110
|
var labels = inner.split(".");
|
|
111
|
-
if (labels.length < 2) { //
|
|
111
|
+
if (labels.length < 2) { // RFC 2919 §3 requires >= 2 labels
|
|
112
112
|
throw new MailUnsubscribeError("mailunsubscribe/invalid-list-header-shape",
|
|
113
113
|
label + " '" + value + "' must contain at least two dot-separated labels (RFC 2919 §3)");
|
|
114
114
|
}
|
|
@@ -144,13 +144,13 @@ function _validateHttpsUrl(value, label) {
|
|
|
144
144
|
} catch (e) {
|
|
145
145
|
throw new MailUnsubscribeError("mailunsubscribe/invalid-list-header-shape",
|
|
146
146
|
label + " must be a valid https URL (got " +
|
|
147
|
-
JSON.stringify(value).slice(0, 200) + "): " + //
|
|
147
|
+
JSON.stringify(value).slice(0, 200) + "): " + // diagnostic clamp characters
|
|
148
148
|
((e && e.message) || String(e)));
|
|
149
149
|
}
|
|
150
150
|
if (!parsed) {
|
|
151
151
|
throw new MailUnsubscribeError("mailunsubscribe/invalid-list-header-shape",
|
|
152
152
|
label + " must be a valid https URL (got " +
|
|
153
|
-
JSON.stringify(value).slice(0, 200) + ")"); //
|
|
153
|
+
JSON.stringify(value).slice(0, 200) + ")"); // diagnostic clamp characters
|
|
154
154
|
}
|
|
155
155
|
return parsed.href;
|
|
156
156
|
}
|
package/lib/mail.js
CHANGED
|
@@ -1003,7 +1003,7 @@ function _smtpSend(message, cfg) {
|
|
|
1003
1003
|
var peerSupportsSmtpUtf8 = false; // RFC 6531 — set from EHLO response
|
|
1004
1004
|
var peerSupportsChunking = false; // RFC 3030 §2 CHUNKING
|
|
1005
1005
|
var peerSupportsBinaryMime = false; // RFC 3030 §3 BINARYMIME
|
|
1006
|
-
var peerSupports8BitMime = false; // RFC 6152 (eight-bit MIME) //
|
|
1006
|
+
var peerSupports8BitMime = false; // RFC 6152 (eight-bit MIME) // RFC number, not a byte literal
|
|
1007
1007
|
var peerSizeCap = -1; // RFC 1870 SIZE — -1 unset, 0 = no cap, >0 = byte limit
|
|
1008
1008
|
var upgradedToTLS = false;
|
|
1009
1009
|
var settled = false;
|
|
@@ -1688,7 +1688,7 @@ function create(opts) {
|
|
|
1688
1688
|
if (country && footerHtml.indexOf(country) === -1) {
|
|
1689
1689
|
throw new MailError("mail/bad-footer-html",
|
|
1690
1690
|
"mail.create({ footerHtml }): override must contain the postalAddress.country '" +
|
|
1691
|
-
country + "' (CAN-SPAM §7704(a)(5)). Got: " + footerHtml.slice(0, 200), //
|
|
1691
|
+
country + "' (CAN-SPAM §7704(a)(5)). Got: " + footerHtml.slice(0, 200), // diagnostic clamp characters, not bytes
|
|
1692
1692
|
true);
|
|
1693
1693
|
}
|
|
1694
1694
|
if (postalCode && footerHtml.indexOf(postalCode) === -1) {
|
|
@@ -1896,7 +1896,7 @@ function feedbackId(opts) {
|
|
|
1896
1896
|
throw new MailError("mail/bad-feedback-id-field",
|
|
1897
1897
|
"feedbackId: " + f.key + " must be a non-empty string");
|
|
1898
1898
|
}
|
|
1899
|
-
if (f.value.length > 64) { //
|
|
1899
|
+
if (f.value.length > 64) { // Gmail FBL per-field cap, not byte arithmetic
|
|
1900
1900
|
throw new MailError("mail/bad-feedback-id-field",
|
|
1901
1901
|
"feedbackId: " + f.key + " exceeds 64 chars (Gmail FBL truncation threshold)");
|
|
1902
1902
|
}
|
|
@@ -1909,7 +1909,7 @@ function feedbackId(opts) {
|
|
|
1909
1909
|
// ranges in regex literals regardless of escape form.
|
|
1910
1910
|
for (var ci = 0; ci < f.value.length; ci += 1) {
|
|
1911
1911
|
var code = f.value.charCodeAt(ci);
|
|
1912
|
-
if (code < 32 || code === 127) { //
|
|
1912
|
+
if (code < 32 || code === 127) { // C0 + DEL codepoint range
|
|
1913
1913
|
throw new MailError("mail/bad-feedback-id-field",
|
|
1914
1914
|
"feedbackId: " + f.key + " contains control characters");
|
|
1915
1915
|
}
|
package/lib/mcp-tool-registry.js
CHANGED
|
@@ -114,7 +114,7 @@ function _validateTool(tool, where) {
|
|
|
114
114
|
where + ": tool must be a non-null object", true);
|
|
115
115
|
}
|
|
116
116
|
validateOpts.requireNonEmptyString(tool.name, where + ".name", McpError, "mcp/bad-tool-name");
|
|
117
|
-
if (tool.name.length > 64 || !TOOL_NAME_RE.test(tool.name)) { //
|
|
117
|
+
if (tool.name.length > 64 || !TOOL_NAME_RE.test(tool.name)) { // MCP tool-name length cap, not byte count
|
|
118
118
|
throw new McpError("mcp/bad-tool-name",
|
|
119
119
|
where + ".name '" + tool.name + "' must match " + TOOL_NAME_RE);
|
|
120
120
|
}
|
|
@@ -185,7 +185,7 @@ function create(opts) {
|
|
|
185
185
|
opts.verifyingKey, "toolRegistry.create.verifyingKey", McpError, "mcp/bad-verifying-key");
|
|
186
186
|
var alg = _validateAlg(opts.alg, "toolRegistry.create.alg");
|
|
187
187
|
var defaultTtlMs = opts.ttlMs !== undefined ? opts.ttlMs : C.TIME.minutes(5);
|
|
188
|
-
if (typeof defaultTtlMs !== "number" || !isFinite(defaultTtlMs) || defaultTtlMs < 1000) { //
|
|
188
|
+
if (typeof defaultTtlMs !== "number" || !isFinite(defaultTtlMs) || defaultTtlMs < 1000) { // minimum-ttl threshold (1 second), not bytes
|
|
189
189
|
throw new McpError("mcp/bad-ttl",
|
|
190
190
|
"toolRegistry.create.ttlMs must be >= 1000 ms", true);
|
|
191
191
|
}
|
|
@@ -303,13 +303,13 @@ function create(opts) {
|
|
|
303
303
|
"signCall: tool '" + callOpts.toolName + "' not registered", true);
|
|
304
304
|
}
|
|
305
305
|
var ttlMs = callOpts.ttlMs !== undefined ? callOpts.ttlMs : defaultTtlMs;
|
|
306
|
-
if (typeof ttlMs !== "number" || !isFinite(ttlMs) || ttlMs < 1000) { //
|
|
306
|
+
if (typeof ttlMs !== "number" || !isFinite(ttlMs) || ttlMs < 1000) { // minimum-ttl threshold (1 second), not bytes
|
|
307
307
|
throw new McpError("mcp/bad-ttl",
|
|
308
308
|
"signCall: ttlMs must be >= 1000 ms", true);
|
|
309
309
|
}
|
|
310
310
|
var nonce = typeof callOpts.nonce === "string" && callOpts.nonce.length > 0
|
|
311
311
|
? callOpts.nonce
|
|
312
|
-
: bCrypto().generateToken(16); //
|
|
312
|
+
: bCrypto().generateToken(16); // 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 = {
|
package/lib/mcp.js
CHANGED
|
@@ -39,9 +39,9 @@ var requestHelpers = require("./request-helpers");
|
|
|
39
39
|
var audit = require("./audit");
|
|
40
40
|
var { McpError } = require("./framework-error");
|
|
41
41
|
|
|
42
|
-
var TOOL_NAME_MAX = 64; //
|
|
43
|
-
var RESOURCE_NAME_MAX = 256; //
|
|
44
|
-
var METHOD_NAME_MAX = 256; //
|
|
42
|
+
var TOOL_NAME_MAX = 64; // string-length cap, not bytes
|
|
43
|
+
var RESOURCE_NAME_MAX = 256; // string-length cap, not bytes
|
|
44
|
+
var METHOD_NAME_MAX = 256; // string-length cap, not bytes
|
|
45
45
|
// JSON-RPC 2.0 error codes (https://www.jsonrpc.org/specification#error_object).
|
|
46
46
|
// Negative numerics by spec; mapped to HTTP status for the framework's
|
|
47
47
|
// HTTP-shaped reply envelope.
|
|
@@ -143,9 +143,9 @@ function refuse(res, code, message, id) {
|
|
|
143
143
|
res.setHeader("Content-Type", "application/json");
|
|
144
144
|
}
|
|
145
145
|
// HTTP status mapping for the JSON-RPC error code we reply with.
|
|
146
|
-
res.statusCode = code === JSONRPC_PARSE_ERROR || code === JSONRPC_INVALID_REQUEST ? 400 : //
|
|
147
|
-
code === JSONRPC_METHOD_NOT_FOUND ? 404 : //
|
|
148
|
-
code === JSONRPC_INTERNAL_ERROR ? 500 : 400; //
|
|
146
|
+
res.statusCode = code === JSONRPC_PARSE_ERROR || code === JSONRPC_INVALID_REQUEST ? 400 : // HTTP status code (RFC 9110)
|
|
147
|
+
code === JSONRPC_METHOD_NOT_FOUND ? 404 : // HTTP status code (RFC 9110)
|
|
148
|
+
code === JSONRPC_INTERNAL_ERROR ? 500 : 400; // HTTP status code (RFC 9110)
|
|
149
149
|
res.end(body);
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -617,7 +617,7 @@ function _validateValueAgainstSchema(value, schema, path) {
|
|
|
617
617
|
// time, not request-controlled. Cap value length first per the
|
|
618
618
|
// codebase-patterns regex-bound rule so a 10MB string doesn't
|
|
619
619
|
// ReDoS the validator.
|
|
620
|
-
if (value.length > 4096) return path + ": value exceeds 4 KiB cap before regex test"; //
|
|
620
|
+
if (value.length > 4096) return path + ": value exceeds 4 KiB cap before regex test"; // 4 KiB regex-input cap
|
|
621
621
|
try {
|
|
622
622
|
var pat = new RegExp(schema.pattern); // allow:dynamic-regex — schema.pattern from registered tool author, not request input; bounded above
|
|
623
623
|
if (!pat.test(value)) return path + ": does not match pattern";
|
|
@@ -752,7 +752,7 @@ function _assertProtocolVersion(req, opts) {
|
|
|
752
752
|
var SAMPLING_DEFAULTS = {
|
|
753
753
|
maxRequestsPerSession: 10,
|
|
754
754
|
maxMessagesPerRequest: 20,
|
|
755
|
-
maxTokensPerRequest: 4096, //
|
|
755
|
+
maxTokensPerRequest: 4096, // LLM token count, not bytes
|
|
756
756
|
allowedModelHint: null, // null = allow all
|
|
757
757
|
refuseStopSequences: false,
|
|
758
758
|
};
|
package/lib/mdoc.js
CHANGED
|
@@ -58,8 +58,8 @@ var { defineClass } = require("./framework-error");
|
|
|
58
58
|
|
|
59
59
|
var MdocError = defineClass("MdocError", { alwaysPermanent: true });
|
|
60
60
|
|
|
61
|
-
var HDR_X5CHAIN = 33; // allow:raw-
|
|
62
|
-
var TAG_ENCODED_CBOR = 24; //
|
|
61
|
+
var HDR_X5CHAIN = 33; // allow:raw-time-literal — x5chain COSE header label (RFC 9360 is a spec number, not a size/duration)
|
|
62
|
+
var TAG_ENCODED_CBOR = 24; // RFC 8949 §3.4.5.1 embedded-CBOR tag
|
|
63
63
|
// Tags ISO 18013-5 uses in issuer data: tdate(0), epoch(1), embedded
|
|
64
64
|
// CBOR(24), full-date(1004, RFC 8943). Bounded — others are refused.
|
|
65
65
|
var ALLOWED_TAGS = [0, 1, TAG_ENCODED_CBOR, 1004];
|
package/lib/metrics.js
CHANGED
|
@@ -161,8 +161,8 @@ function _normalizeLabelArg(callLabels, value, defaultValue) {
|
|
|
161
161
|
// a heuristic fallback so unknown-issuer tokens still get caught
|
|
162
162
|
var _CRED_PREFIX_RE = /^(?:Bearer|Basic|Negotiate|Token|Digest)\s+\S/i;
|
|
163
163
|
var _CRED_ISSUER_RE = /^(?:sk-|pk-|rk-|ghp_|ghs_|gho_|github_pat_|xoxb-|xoxa-|xoxp-|xoxr-|xapp-)/;
|
|
164
|
-
var _CRED_JWT_RE = /^[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}$/; //
|
|
165
|
-
var _CRED_ENTROPY_RE = /^[A-Za-z0-9_+/=-]{40,}$/; //
|
|
164
|
+
var _CRED_JWT_RE = /^[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}$/; // JWT segment min length
|
|
165
|
+
var _CRED_ENTROPY_RE = /^[A-Za-z0-9_+/=-]{40,}$/; // high-entropy length floor
|
|
166
166
|
|
|
167
167
|
// CRED_MAX_SCAN — upper bound on the byte slice the credential
|
|
168
168
|
// detector inspects. Operator-supplied label values longer than this
|
|
@@ -170,11 +170,11 @@ var _CRED_ENTROPY_RE = /^[A-Za-z0-9_+/=-]{40,}$/;
|
|
|
170
170
|
// still a credential), but the regex tests run on the prefix slice so
|
|
171
171
|
// a 1 GB string can't ReDoS the scanner. Counter cardinality stays
|
|
172
172
|
// stable: the same long string always maps to the same prefix slice.
|
|
173
|
-
var CRED_MAX_SCAN = 256; //
|
|
173
|
+
var CRED_MAX_SCAN = 256; // prefix-scan length cap
|
|
174
174
|
|
|
175
175
|
function _looksLikeCredential(str) {
|
|
176
176
|
if (typeof str !== "string") return false;
|
|
177
|
-
if (str.length < 8) return false; //
|
|
177
|
+
if (str.length < 8) return false; // minimum credential length floor
|
|
178
178
|
// Clamp to the prefix slice so a hostile label value can't push the
|
|
179
179
|
// regex into superlinear time. All four credential shapes have
|
|
180
180
|
// signature in the first ~256 bytes; Stripe / GitHub / OpenAI tokens
|
|
@@ -185,7 +185,7 @@ function _looksLikeCredential(str) {
|
|
|
185
185
|
// enough entropy to be real tokens; hoisted to a named constant so
|
|
186
186
|
// every test() has its length floor visible at the call site
|
|
187
187
|
// (testFormatValidatorLengthCap convention).
|
|
188
|
-
var CRED_MIN_LEN = 8; //
|
|
188
|
+
var CRED_MIN_LEN = 8; // minimum credential length floor
|
|
189
189
|
if (clamped.length >= CRED_MIN_LEN && _CRED_PREFIX_RE.test(clamped)) return true;
|
|
190
190
|
if (clamped.length >= CRED_MIN_LEN && _CRED_ISSUER_RE.test(clamped)) return true;
|
|
191
191
|
if (clamped.length >= CRED_MIN_LEN && _CRED_JWT_RE.test(clamped)) return true;
|
|
@@ -990,7 +990,7 @@ function snapshotStartWriter(opts) {
|
|
|
990
990
|
// (owner rw, group r, world none). Operators with a sidecar
|
|
991
991
|
// reader in a different group override to 0o644; multi-tenant
|
|
992
992
|
// hosts may even tighten to 0o600.
|
|
993
|
-
var fileMode = opts.fileMode !== undefined ? opts.fileMode : 0o640; //
|
|
993
|
+
var fileMode = opts.fileMode !== undefined ? opts.fileMode : 0o640; // POSIX file mode octal
|
|
994
994
|
if (typeof fileMode !== "number" || !isFinite(fileMode) ||
|
|
995
995
|
fileMode < 0 || fileMode > 0o777 || Math.floor(fileMode) !== fileMode) {
|
|
996
996
|
throw new MetricsError("metrics-snapshot/bad-file-mode",
|
|
@@ -1263,7 +1263,7 @@ function snapshotRender(snap, opts) {
|
|
|
1263
1263
|
var kd = keys2[jd];
|
|
1264
1264
|
var vd = fields[kd];
|
|
1265
1265
|
if (typeof vd !== "string") continue;
|
|
1266
|
-
if (vd.length > 64) continue; //
|
|
1266
|
+
if (vd.length > 64) continue; // ISO 8601 max length cap, not bytes
|
|
1267
1267
|
if (!ISO_DATE_RE.test(vd)) continue; // allow:regex-no-length-cap — length-bounded immediately above
|
|
1268
1268
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(kd)) continue; // allow:regex-no-length-cap — field-name shape, length-bounded by snap field naming
|
|
1269
1269
|
var ms = Date.parse(vd);
|
|
@@ -1311,7 +1311,7 @@ function snapshotRender(snap, opts) {
|
|
|
1311
1311
|
* shadow.set("queue_depth", 42);
|
|
1312
1312
|
* shadow.snapshot();
|
|
1313
1313
|
*/
|
|
1314
|
-
var SHADOW_DEFAULT_CARDINALITY = 10000; //
|
|
1314
|
+
var SHADOW_DEFAULT_CARDINALITY = 10000; // cardinality cap, not bytes
|
|
1315
1315
|
function shadowRegistry(opts) {
|
|
1316
1316
|
if (!opts || typeof opts !== "object") {
|
|
1317
1317
|
throw new MetricsError("metrics-shadow/bad-opts",
|
|
@@ -169,7 +169,7 @@ function create(opts) {
|
|
|
169
169
|
if (!hasConsent) {
|
|
170
170
|
_emitAudit("refused", "denied", { age: age, classification: classification, requireAge: requireAge });
|
|
171
171
|
if (!res.writableEnded && typeof res.writeHead === "function") {
|
|
172
|
-
res.writeHead(451, { //
|
|
172
|
+
res.writeHead(451, { // HTTP 451 Unavailable For Legal Reasons
|
|
173
173
|
"Content-Type": "application/json; charset=utf-8",
|
|
174
174
|
"Cache-Control": "no-store, private",
|
|
175
175
|
});
|
|
@@ -855,18 +855,18 @@ function client(opts) {
|
|
|
855
855
|
// _generateUuidV4 — UUID v4 from 16 random bytes, formatted dash-separated.
|
|
856
856
|
// Used for client-side session-id generation in per-session keying.
|
|
857
857
|
// Slice offsets are RFC 4122 UUID hex-byte boundaries (`xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx`)
|
|
858
|
-
// — protocol-fixed values, not byte sizes.
|
|
858
|
+
// — protocol-fixed values, not byte sizes.
|
|
859
859
|
function _generateUuidV4() {
|
|
860
|
-
var b = bCrypto.generateBytes(16); //
|
|
860
|
+
var b = bCrypto.generateBytes(16); // 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;
|
|
864
864
|
var hex = b.toString("hex");
|
|
865
|
-
return hex.slice(0, 8) + "-" + //
|
|
866
|
-
hex.slice(8, 12) + "-" +
|
|
867
|
-
hex.slice(12, 16) + "-" +
|
|
868
|
-
hex.slice(16, 20) + "-" +
|
|
869
|
-
hex.slice(20, 32);
|
|
865
|
+
return hex.slice(0, 8) + "-" + // RFC 4122 hex offsets
|
|
866
|
+
hex.slice(8, 12) + "-" +
|
|
867
|
+
hex.slice(12, 16) + "-" +
|
|
868
|
+
hex.slice(16, 20) + "-" +
|
|
869
|
+
hex.slice(20, 32);
|
|
870
870
|
}
|
|
871
871
|
|
|
872
872
|
// ---- Server-to-server convenience ----
|
|
@@ -109,7 +109,7 @@ function create(opts) {
|
|
|
109
109
|
if (path !== "/.well-known/assetlinks.json") return next();
|
|
110
110
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
111
111
|
var bodyMsg = "Method Not Allowed";
|
|
112
|
-
res.writeHead(405, { //
|
|
112
|
+
res.writeHead(405, { // HTTP 405 status
|
|
113
113
|
"Allow": "GET, HEAD",
|
|
114
114
|
"Content-Type": "text/plain; charset=utf-8",
|
|
115
115
|
"Content-Length": Buffer.byteLength(bodyMsg),
|
|
@@ -117,7 +117,7 @@ function create(opts) {
|
|
|
117
117
|
res.end(bodyMsg);
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
|
-
res.writeHead(200, { //
|
|
120
|
+
res.writeHead(200, { // HTTP 200 status
|
|
121
121
|
"Content-Type": "application/json; charset=utf-8",
|
|
122
122
|
"Content-Length": bodyBuf.length,
|
|
123
123
|
"Cache-Control": "public, max-age=86400",
|
|
@@ -107,7 +107,7 @@ function create(opts) {
|
|
|
107
107
|
function _writeBody(req, res, body, etag, contentType) {
|
|
108
108
|
var requestEtag = (req.headers && req.headers["if-none-match"]) || null;
|
|
109
109
|
if (requestEtag && requestEtag === etag) {
|
|
110
|
-
res.writeHead(304, { "ETag": etag, "Cache-Control": cacheControl }); //
|
|
110
|
+
res.writeHead(304, { "ETag": etag, "Cache-Control": cacheControl }); // HTTP 304
|
|
111
111
|
res.end();
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
@@ -120,7 +120,7 @@ function create(opts) {
|
|
|
120
120
|
if (accessControl === "public") {
|
|
121
121
|
headers["Access-Control-Allow-Origin"] = "*";
|
|
122
122
|
}
|
|
123
|
-
res.writeHead(200, headers); //
|
|
123
|
+
res.writeHead(200, headers); // HTTP 200
|
|
124
124
|
res.end(body);
|
|
125
125
|
}
|
|
126
126
|
|
|
@@ -46,7 +46,7 @@ function _writeUnauthorized(res, scheme, message, realm) {
|
|
|
46
46
|
if (res.headersSent) return;
|
|
47
47
|
var body = JSON.stringify({ error: message });
|
|
48
48
|
var challenge = scheme + (realm ? ' realm="' + realm + '"' : "");
|
|
49
|
-
res.writeHead(401, { //
|
|
49
|
+
res.writeHead(401, { // HTTP 401 status
|
|
50
50
|
"Content-Type": "application/json; charset=utf-8",
|
|
51
51
|
"Content-Length": Buffer.byteLength(body),
|
|
52
52
|
"WWW-Authenticate": challenge,
|
|
@@ -146,7 +146,7 @@ function create(opts) {
|
|
|
146
146
|
}
|
|
147
147
|
for (var ri = 0; ri < realm.length; ri += 1) {
|
|
148
148
|
var rcode = realm.charCodeAt(ri);
|
|
149
|
-
if (rcode < 32 || rcode === 127) { //
|
|
149
|
+
if (rcode < 32 || rcode === 127) { // ASCII control codepoints
|
|
150
150
|
throw new AuthError("auth-bearer/bad-realm",
|
|
151
151
|
"realm contains control character at index " + ri);
|
|
152
152
|
}
|
|
@@ -198,7 +198,7 @@ function create(opts) {
|
|
|
198
198
|
var malformedChallenge = scheme + ' error="invalid_request"' +
|
|
199
199
|
(realm ? ', realm="' + realm + '"' : "");
|
|
200
200
|
var malformedBody = JSON.stringify({ error: errorMessage });
|
|
201
|
-
res.writeHead(401, { //
|
|
201
|
+
res.writeHead(401, { // HTTP 401 status
|
|
202
202
|
"Content-Type": "application/json; charset=utf-8",
|
|
203
203
|
"Content-Length": Buffer.byteLength(malformedBody),
|
|
204
204
|
"WWW-Authenticate": malformedChallenge,
|
|
@@ -222,7 +222,7 @@ function create(opts) {
|
|
|
222
222
|
(realm ? ', realm="' + realm + '"' : "");
|
|
223
223
|
if (!res.headersSent) {
|
|
224
224
|
var body = JSON.stringify({ error: errorMessage });
|
|
225
|
-
res.writeHead(401, { //
|
|
225
|
+
res.writeHead(401, { // HTTP 401 status
|
|
226
226
|
"Content-Type": "application/json; charset=utf-8",
|
|
227
227
|
"Content-Length": Buffer.byteLength(body),
|
|
228
228
|
"WWW-Authenticate": challenge,
|
|
@@ -264,7 +264,7 @@ function create(opts) {
|
|
|
264
264
|
error: "insufficient_scope",
|
|
265
265
|
required: opts.requiredScopes.slice(),
|
|
266
266
|
});
|
|
267
|
-
res.writeHead(403, { //
|
|
267
|
+
res.writeHead(403, { // HTTP 403 status
|
|
268
268
|
"Content-Type": "application/json; charset=utf-8",
|
|
269
269
|
"Content-Length": Buffer.byteLength(scopeBody),
|
|
270
270
|
"WWW-Authenticate": scopeChallenge,
|
|
@@ -574,7 +574,7 @@ function _parseMultipartHeaders(rawHeaders) {
|
|
|
574
574
|
var line = lines[i];
|
|
575
575
|
if (!line) continue;
|
|
576
576
|
var first = line.charCodeAt(0);
|
|
577
|
-
if (first === 32 || first === 9) { //
|
|
577
|
+
if (first === 32 || first === 9) { // SP/HTAB obs-fold sentinels
|
|
578
578
|
throw new BodyParserError(
|
|
579
579
|
"body-parser/multipart-obs-fold",
|
|
580
580
|
"multipart part header uses obsolete line folding (RFC 9112 §5.2)",
|
|
@@ -587,7 +587,7 @@ function _parseMultipartHeaders(rawHeaders) {
|
|
|
587
587
|
var v = line.slice(idx + 1).trim();
|
|
588
588
|
for (var j = 0; j < v.length; j++) {
|
|
589
589
|
var c = v.charCodeAt(j);
|
|
590
|
-
if (c === 0 || c === 10 || c === 13) { //
|
|
590
|
+
if (c === 0 || c === 10 || c === 13) { // NUL/LF/CR forbidden in field-value (RFC 9110 §5.5)
|
|
591
591
|
throw new BodyParserError(
|
|
592
592
|
"body-parser/multipart-bad-header-value",
|
|
593
593
|
"multipart part header `" + k + "` contains CR/LF/NUL (RFC 9110 §5.5)",
|
|
@@ -674,8 +674,8 @@ async function _parseMultipart(req, opts, ctParams) {
|
|
|
674
674
|
// newlines) drive quadratic match cost in scanners. Refuse at
|
|
675
675
|
// the parse boundary so the rest of the engine doesn't have to
|
|
676
676
|
// defend against them.
|
|
677
|
-
if (boundary.length > 70 || //
|
|
678
|
-
!/^[A-Za-z0-9'()+_,\-./:=?]{1,70}$/.test(boundary)) { //
|
|
677
|
+
if (boundary.length > 70 || // RFC 2046 §5.1.1 boundary length cap
|
|
678
|
+
!/^[A-Za-z0-9'()+_,\-./:=?]{1,70}$/.test(boundary)) { // RFC 2046 §5.1.1 bchars + cap
|
|
679
679
|
throw new BodyParserError(
|
|
680
680
|
"body-parser/multipart-bad-boundary",
|
|
681
681
|
"multipart boundary violates RFC 2046 §5.1.1 (1-70 chars, bcharsnospace grammar)",
|
|
@@ -1353,7 +1353,7 @@ function create(opts) {
|
|
|
1353
1353
|
outcome: "denied",
|
|
1354
1354
|
metadata: {
|
|
1355
1355
|
code: e.code || null,
|
|
1356
|
-
message: (e && e.message) ? String(e.message).slice(0, 256) : "", //
|
|
1356
|
+
message: (e && e.message) ? String(e.message).slice(0, 256) : "", // diagnostic-message clamp characters, not bytes
|
|
1357
1357
|
},
|
|
1358
1358
|
});
|
|
1359
1359
|
} catch (_e) { /* audit best-effort */ }
|
|
@@ -85,20 +85,20 @@ var ComposePipelineError = defineClass("ComposePipelineError", { alwaysPermanent
|
|
|
85
85
|
// 60-89 : application handlers
|
|
86
86
|
// >= 90 : error-handler (must be last; trailing catch)
|
|
87
87
|
var CANONICAL_POSITIONS = Object.freeze({
|
|
88
|
-
requestId: 5, //
|
|
89
|
-
apiEncrypt: 10, //
|
|
90
|
-
bodyParser: 20, //
|
|
91
|
-
cspNonce: 22, //
|
|
92
|
-
securityHeaders: 25, //
|
|
93
|
-
csrf: 30, //
|
|
94
|
-
idempotency: 30, //
|
|
95
|
-
fetchMetadata: 32, //
|
|
96
|
-
rateLimit: 40, //
|
|
97
|
-
botGuard: 42, //
|
|
98
|
-
requireAuth: 50, //
|
|
99
|
-
attachUser: 52, //
|
|
88
|
+
requestId: 5, // canonical position bucket
|
|
89
|
+
apiEncrypt: 10, // canonical position bucket
|
|
90
|
+
bodyParser: 20, // canonical position bucket
|
|
91
|
+
cspNonce: 22, // canonical position bucket
|
|
92
|
+
securityHeaders: 25, // canonical position bucket
|
|
93
|
+
csrf: 30, // canonical position bucket
|
|
94
|
+
idempotency: 30, // canonical position bucket (same as csrf)
|
|
95
|
+
fetchMetadata: 32, // canonical position bucket
|
|
96
|
+
rateLimit: 40, // canonical position bucket
|
|
97
|
+
botGuard: 42, // canonical position bucket
|
|
98
|
+
requireAuth: 50, // canonical position bucket
|
|
99
|
+
attachUser: 52, // canonical position bucket
|
|
100
100
|
handler: 60, // allow:raw-byte-literal — canonical position bucket // allow:raw-time-literal — pipeline position int, not seconds
|
|
101
|
-
errorHandler: 90, //
|
|
101
|
+
errorHandler: 90, // canonical position bucket
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
/**
|
|
@@ -154,7 +154,7 @@ function composePipeline(entries, opts) {
|
|
|
154
154
|
throw new ComposePipelineError("compose-pipeline/bad-entry",
|
|
155
155
|
"composePipeline: entry at index " + i + " must be an object");
|
|
156
156
|
}
|
|
157
|
-
if (typeof e.name !== "string" || e.name.length === 0 || e.name.length > 64) { //
|
|
157
|
+
if (typeof e.name !== "string" || e.name.length === 0 || e.name.length > 64) { // middleware-name cap
|
|
158
158
|
throw new ComposePipelineError("compose-pipeline/bad-entry",
|
|
159
159
|
"composePipeline: entries[" + i + "].name must be a non-empty string ≤ 64 bytes");
|
|
160
160
|
}
|
|
@@ -187,7 +187,7 @@ function composePipeline(entries, opts) {
|
|
|
187
187
|
// natural sequential flow. Use 100 so canonical positions
|
|
188
188
|
// (5..90) can interleave without colliding when an operator
|
|
189
189
|
// mixes named + unnamed entries.
|
|
190
|
-
position = (i + 1) * 100; //
|
|
190
|
+
position = (i + 1) * 100; // index→position scale; canonical-pos ceiling is 90
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
if (Object.prototype.hasOwnProperty.call(seenPositions, position)) {
|
|
@@ -125,7 +125,7 @@ function create(opts) {
|
|
|
125
125
|
|
|
126
126
|
return async function cspReport(req, res, _next) {
|
|
127
127
|
if (req.method !== "POST") {
|
|
128
|
-
res.writeHead(405, { "Allow": "POST" }); //
|
|
128
|
+
res.writeHead(405, { "Allow": "POST" }); // HTTP 405 status
|
|
129
129
|
res.end();
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
@@ -133,14 +133,14 @@ function create(opts) {
|
|
|
133
133
|
try {
|
|
134
134
|
body = await safeBuffer.boundedChunkCollector(req, { maxBytes: maxBytes });
|
|
135
135
|
} catch (_e) {
|
|
136
|
-
res.writeHead(413); //
|
|
136
|
+
res.writeHead(413); // HTTP 413 status
|
|
137
137
|
res.end();
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
140
140
|
var parsed;
|
|
141
141
|
try { parsed = safeJson.parse(body.toString("utf8")); }
|
|
142
142
|
catch (_e) {
|
|
143
|
-
res.writeHead(400); //
|
|
143
|
+
res.writeHead(400); // HTTP 400 status
|
|
144
144
|
res.end();
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
@@ -159,7 +159,7 @@ function create(opts) {
|
|
|
159
159
|
try { onReport(normalized); } catch (_e) { /* hook best-effort */ }
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
res.writeHead(204); //
|
|
162
|
+
res.writeHead(204); // HTTP 204 status
|
|
163
163
|
res.end();
|
|
164
164
|
};
|
|
165
165
|
}
|
|
@@ -199,7 +199,7 @@ function create(opts) {
|
|
|
199
199
|
var keys = Object.keys(req.headers);
|
|
200
200
|
for (var hi = 0; hi < keys.length; hi++) {
|
|
201
201
|
var v = req.headers[keys[hi]];
|
|
202
|
-
inboundBytes += keys[hi].length + 2 + (typeof v === "string" ? v.length : 0) + 2; //
|
|
202
|
+
inboundBytes += keys[hi].length + 2 + (typeof v === "string" ? v.length : 0) + 2; // ": " + "\r\n" overhead
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
if (req.headers && req.headers["content-length"]) {
|
package/lib/middleware/dpop.js
CHANGED
|
@@ -55,7 +55,7 @@ function _writeUnauthorized(res, errorCode, description, freshNonce) {
|
|
|
55
55
|
// RFC 9449 §7 — error code is invalid_dpop_proof OR use_dpop_nonce.
|
|
56
56
|
var challenge = 'DPoP error="' + errorCode + '", error_description="' +
|
|
57
57
|
description.replace(/"/g, "'") + '"';
|
|
58
|
-
var headers = { //
|
|
58
|
+
var headers = { // HTTP 401 status
|
|
59
59
|
"Content-Type": "application/json; charset=utf-8",
|
|
60
60
|
"Content-Length": Buffer.byteLength(body),
|
|
61
61
|
"WWW-Authenticate": challenge,
|
|
@@ -104,7 +104,7 @@ function _detectIssues(headers, opts) {
|
|
|
104
104
|
}
|
|
105
105
|
for (var ci = 0; ci < v.length; ci += 1) {
|
|
106
106
|
var cc = v.charCodeAt(ci);
|
|
107
|
-
if (cc === 0x0D || cc === 0x0A || cc === 0x00) { //
|
|
107
|
+
if (cc === 0x0D || cc === 0x0A || cc === 0x00) { // CR / LF / NUL forbidden in header value
|
|
108
108
|
issues.push({
|
|
109
109
|
kind: "header-value-control-byte", severity: "high", header: name,
|
|
110
110
|
snippet: "header `" + name + "` value contains CR / LF / NUL " +
|
|
@@ -200,7 +200,7 @@ function create(opts) {
|
|
|
200
200
|
var refuseOnHigh = opts.refuseOnHigh !== false && mode === "enforce";
|
|
201
201
|
var audit = opts.audit || null;
|
|
202
202
|
var resolved = {
|
|
203
|
-
maxHeaderCount: opts.maxHeaderCount || 100, //
|
|
203
|
+
maxHeaderCount: opts.maxHeaderCount || 100, // header count ceiling
|
|
204
204
|
maxValueBytes: opts.maxValueBytes || 8 * 1024, // allow:raw-byte-literal — header value cap (8 KiB)
|
|
205
205
|
trustProxy: !!opts.trustProxy,
|
|
206
206
|
};
|
|
@@ -131,7 +131,7 @@ function create(opts) {
|
|
|
131
131
|
hosts.push(n);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
var denyStatus = (typeof opts.denyStatus === "number") ? opts.denyStatus : 421; //
|
|
134
|
+
var denyStatus = (typeof opts.denyStatus === "number") ? opts.denyStatus : 421; // HTTP 421 status
|
|
135
135
|
var denyBody = typeof opts.denyBody === "string" ? opts.denyBody : "Misdirected Request";
|
|
136
136
|
var auditOn = opts.audit !== false;
|
|
137
137
|
|