@blamejs/core 0.14.0 → 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 +4 -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 +45 -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/jar.js +11 -0
- package/lib/auth/jwt-external.js +5 -5
- package/lib/auth/oauth.js +7 -9
- package/lib/auth/oid4vci.js +10 -10
- 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 +29 -25
- 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 +53 -45
- 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 +99 -94
- 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 +9 -1
- package/lib/queue.js +4 -2
- 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-auth.js
CHANGED
|
@@ -70,12 +70,12 @@ var SPF_DNS_LOOKUP_LIMIT = 10;
|
|
|
70
70
|
// that the policy MUST permerror. Attackers chain misconfigured
|
|
71
71
|
// `include:`s pointing at non-existent domains to amplify recursive
|
|
72
72
|
// resolver work without tripping the 10-lookup ceiling.
|
|
73
|
-
var SPF_VOID_LOOKUP_LIMIT = 2; //
|
|
73
|
+
var SPF_VOID_LOOKUP_LIMIT = 2; // RFC 7208 §4.6.4 void-lookup ceiling
|
|
74
74
|
|
|
75
75
|
// RFC 7208 §3.3 — each SPF TXT record MUST NOT exceed 450 bytes when
|
|
76
76
|
// concatenated across multi-string TXT chunks. The spec lifts a
|
|
77
77
|
// receiver MUST-refuse on >450-byte records to bound parse work.
|
|
78
|
-
var SPF_RECORD_MAX_BYTES = 450; //
|
|
78
|
+
var SPF_RECORD_MAX_BYTES = 450; // RFC 7208 §3.3 record ceiling
|
|
79
79
|
|
|
80
80
|
// SPF redirect= modifier (RFC 7208 §6.1) recursion cap. The modifier
|
|
81
81
|
// re-evaluates against a different domain; a chain of redirect= cycles
|
|
@@ -84,7 +84,7 @@ var SPF_RECORD_MAX_BYTES = 450;
|
|
|
84
84
|
// hard cap below is an additional belt-and-braces against malformed
|
|
85
85
|
// upstream policies that would otherwise spin until the lookup cap
|
|
86
86
|
// alone tripped.
|
|
87
|
-
var SPF_REDIRECT_DEPTH_LIMIT = 10; //
|
|
87
|
+
var SPF_REDIRECT_DEPTH_LIMIT = 10; // same shape as RFC 7208 §4.6.4 lookup ceiling
|
|
88
88
|
|
|
89
89
|
// Shared safe-DNS TXT/A/AAAA/MX/PTR lookup. Operator-supplied
|
|
90
90
|
// `dnsLookup(qname, type)` is honored for every type when present:
|
|
@@ -114,7 +114,7 @@ async function _safeResolveTxt(qname, operatorLookup) {
|
|
|
114
114
|
var out = [];
|
|
115
115
|
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
116
116
|
var rr = r.rrs[i];
|
|
117
|
-
if (rr && rr.type === 16) { //
|
|
117
|
+
if (rr && rr.type === 16) { // IANA DNS qtype TXT
|
|
118
118
|
out.push(Array.isArray(rr.decoded) ? rr.decoded : [String(rr.decoded)]);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -145,7 +145,7 @@ async function _safeResolveA(qname, family /* 4|6 */, operatorLookup) {
|
|
|
145
145
|
var out = [];
|
|
146
146
|
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
147
147
|
var rr = r.rrs[i];
|
|
148
|
-
var wantType = family === 6 ? 28 : 1; //
|
|
148
|
+
var wantType = family === 6 ? 28 : 1; // IANA DNS qtype AAAA / A
|
|
149
149
|
if (rr && rr.type === wantType) out.push(rr.decoded);
|
|
150
150
|
}
|
|
151
151
|
if (out.length === 0) {
|
|
@@ -183,7 +183,7 @@ async function _safeResolveMx(qname, operatorLookup) {
|
|
|
183
183
|
var entries = [];
|
|
184
184
|
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
185
185
|
var rr = r.rrs[i];
|
|
186
|
-
if (rr && rr.type === 15) { //
|
|
186
|
+
if (rr && rr.type === 15) { // IANA DNS qtype MX
|
|
187
187
|
var d = rr.decoded || {};
|
|
188
188
|
if (d.exchange) {
|
|
189
189
|
entries.push({ exchange: String(d.exchange).replace(/\.$/, ""),
|
|
@@ -213,7 +213,7 @@ async function _safeReverse(ip) {
|
|
|
213
213
|
var out = [];
|
|
214
214
|
for (var i = 0; i < r.rrs.length; i += 1) {
|
|
215
215
|
var rr = r.rrs[i];
|
|
216
|
-
if (rr && rr.type === 12) { //
|
|
216
|
+
if (rr && rr.type === 12) { // IANA DNS qtype PTR
|
|
217
217
|
// Strip trailing dot if present (PTR rdata is FQDN with root dot).
|
|
218
218
|
var name = String(rr.decoded || "").replace(/\.$/, "");
|
|
219
219
|
if (name.length > 0) out.push(name);
|
|
@@ -231,7 +231,7 @@ function _ipToReverseArpa(ip) {
|
|
|
231
231
|
if (typeof ip !== "string") return null;
|
|
232
232
|
if (net.isIPv4(ip)) {
|
|
233
233
|
var p = ip.split(".");
|
|
234
|
-
if (p.length !== 4) return null; //
|
|
234
|
+
if (p.length !== 4) return null; // IPv4 octet count
|
|
235
235
|
return p[3] + "." + p[2] + "." + p[1] + "." + p[0] + ".in-addr.arpa";
|
|
236
236
|
}
|
|
237
237
|
if (net.isIPv6(ip)) {
|
|
@@ -239,8 +239,8 @@ function _ipToReverseArpa(ip) {
|
|
|
239
239
|
if (!groups) return null;
|
|
240
240
|
var hex = "";
|
|
241
241
|
for (var i = 0; i < groups.length; i += 1) {
|
|
242
|
-
var s = groups[i].toString(16); //
|
|
243
|
-
while (s.length < 4) s = "0" + s; //
|
|
242
|
+
var s = groups[i].toString(16); // hex radix
|
|
243
|
+
while (s.length < 4) s = "0" + s; // IPv6 group nibble count
|
|
244
244
|
hex += s;
|
|
245
245
|
}
|
|
246
246
|
var rev = hex.split("").reverse().join(".");
|
|
@@ -253,12 +253,12 @@ function _ipToReverseArpa(ip) {
|
|
|
253
253
|
|
|
254
254
|
function _ipv4ToInt(ip) {
|
|
255
255
|
var parts = ip.split(".");
|
|
256
|
-
if (parts.length !== 4) return null; //
|
|
256
|
+
if (parts.length !== 4) return null; // IPv4 octet count
|
|
257
257
|
var n = 0;
|
|
258
|
-
for (var i = 0; i < 4; i += 1) { //
|
|
258
|
+
for (var i = 0; i < 4; i += 1) { // IPv4 octet count
|
|
259
259
|
var p = parseInt(parts[i], 10);
|
|
260
|
-
if (!isFinite(p) || p < 0 || p > 255) return null; //
|
|
261
|
-
n = (n * 256) + p; //
|
|
260
|
+
if (!isFinite(p) || p < 0 || p > 255) return null; // IPv4 octet range
|
|
261
|
+
n = (n * 256) + p; // IPv4 octet base
|
|
262
262
|
}
|
|
263
263
|
return n;
|
|
264
264
|
}
|
|
@@ -274,20 +274,20 @@ function _ipv6Expand(ip) {
|
|
|
274
274
|
function _ipv6InCidr(ip, cidr) {
|
|
275
275
|
var slash = cidr.indexOf("/");
|
|
276
276
|
var net = slash === -1 ? cidr : cidr.slice(0, slash);
|
|
277
|
-
var mask = slash === -1 ? 128 : parseInt(cidr.slice(slash + 1), 10); //
|
|
278
|
-
if (!isFinite(mask) || mask < 0 || mask > 128) return false; //
|
|
277
|
+
var mask = slash === -1 ? 128 : parseInt(cidr.slice(slash + 1), 10); // IPv6 max prefix
|
|
278
|
+
if (!isFinite(mask) || mask < 0 || mask > 128) return false; // IPv6 max prefix
|
|
279
279
|
var ipGroups = _ipv6Expand(ip);
|
|
280
280
|
var netGroups = _ipv6Expand(net);
|
|
281
281
|
if (!ipGroups || !netGroups) return false;
|
|
282
282
|
if (mask === 0) return true;
|
|
283
283
|
// Compare group-by-group up to the prefix boundary.
|
|
284
|
-
var fullGroups = Math.floor(mask / 16); //
|
|
285
|
-
var remainBits = mask - fullGroups * 16; //
|
|
284
|
+
var fullGroups = Math.floor(mask / 16); // bits per group
|
|
285
|
+
var remainBits = mask - fullGroups * 16; // bits per group
|
|
286
286
|
for (var g = 0; g < fullGroups; g += 1) {
|
|
287
287
|
if (ipGroups[g] !== netGroups[g]) return false;
|
|
288
288
|
}
|
|
289
|
-
if (remainBits > 0 && fullGroups < 8) { //
|
|
290
|
-
var groupMask = (0xffff << (16 - remainBits)) & 0xffff; //
|
|
289
|
+
if (remainBits > 0 && fullGroups < 8) { // IPv6 group count
|
|
290
|
+
var groupMask = (0xffff << (16 - remainBits)) & 0xffff; // bits per group
|
|
291
291
|
if ((ipGroups[fullGroups] & groupMask) !== (netGroups[fullGroups] & groupMask)) return false;
|
|
292
292
|
}
|
|
293
293
|
return true;
|
|
@@ -296,13 +296,13 @@ function _ipv6InCidr(ip, cidr) {
|
|
|
296
296
|
function _ipv4InCidr(ip, cidr) {
|
|
297
297
|
var slash = cidr.indexOf("/");
|
|
298
298
|
var net = slash === -1 ? cidr : cidr.slice(0, slash);
|
|
299
|
-
var mask = slash === -1 ? 32 : parseInt(cidr.slice(slash + 1), 10); //
|
|
300
|
-
if (mask < 0 || mask > 32) return false; //
|
|
299
|
+
var mask = slash === -1 ? 32 : parseInt(cidr.slice(slash + 1), 10); // IPv4 max prefix
|
|
300
|
+
if (mask < 0 || mask > 32) return false; // IPv4 max prefix
|
|
301
301
|
var ipInt = _ipv4ToInt(ip);
|
|
302
302
|
var netInt = _ipv4ToInt(net);
|
|
303
303
|
if (ipInt === null || netInt === null) return false;
|
|
304
304
|
if (mask === 0) return true;
|
|
305
|
-
var bits = 32 - mask; //
|
|
305
|
+
var bits = 32 - mask; // IPv4 max prefix
|
|
306
306
|
// Use BigInt to avoid 32-bit signed-int wrap.
|
|
307
307
|
var maskInt = (BigInt("0xFFFFFFFF") << BigInt(bits)) & BigInt("0xFFFFFFFF");
|
|
308
308
|
return (BigInt(ipInt) & maskInt) === (BigInt(netInt) & maskInt);
|
|
@@ -411,8 +411,8 @@ async function _fetchSpfRecord(domain, dnsLookup) {
|
|
|
411
411
|
function _parseADualCidr(raw, mech, defaultDomain) {
|
|
412
412
|
var rest = raw.slice(mech.length);
|
|
413
413
|
var domain = defaultDomain;
|
|
414
|
-
var v4Mask = 32; //
|
|
415
|
-
var v6Mask = 128; //
|
|
414
|
+
var v4Mask = 32; // IPv4 max prefix
|
|
415
|
+
var v6Mask = 128; // IPv6 max prefix
|
|
416
416
|
|
|
417
417
|
if (rest.charAt(0) === ":") {
|
|
418
418
|
rest = rest.slice(1);
|
|
@@ -451,7 +451,7 @@ function _parseADualCidr(raw, mech, defaultDomain) {
|
|
|
451
451
|
JSON.stringify(raw));
|
|
452
452
|
}
|
|
453
453
|
var v4n = parseInt(v4Str, 10);
|
|
454
|
-
if (!isFinite(v4n) || v4n < 0 || v4n > 32 || String(v4n) !== v4Str) { //
|
|
454
|
+
if (!isFinite(v4n) || v4n < 0 || v4n > 32 || String(v4n) !== v4Str) { // IPv4 max prefix
|
|
455
455
|
throw new MailAuthError("mail-auth/spf-bad-cidr",
|
|
456
456
|
"SPF " + mech + " v4 cidr-length invalid: " + JSON.stringify(raw));
|
|
457
457
|
}
|
|
@@ -468,7 +468,7 @@ function _parseADualCidr(raw, mech, defaultDomain) {
|
|
|
468
468
|
JSON.stringify(raw));
|
|
469
469
|
}
|
|
470
470
|
var v6n = parseInt(v6Part, 10);
|
|
471
|
-
if (!isFinite(v6n) || v6n < 0 || v6n > 128 || String(v6n) !== v6Part) { //
|
|
471
|
+
if (!isFinite(v6n) || v6n < 0 || v6n > 128 || String(v6n) !== v6Part) { // IPv6 max prefix
|
|
472
472
|
throw new MailAuthError("mail-auth/spf-bad-cidr",
|
|
473
473
|
"SPF " + mech + " v6 cidr-length invalid: " + JSON.stringify(raw));
|
|
474
474
|
}
|
|
@@ -509,7 +509,7 @@ async function _spfMatchAMx(mech, raw, ip, isIpv6, defaultDomain, dnsLookup, loo
|
|
|
509
509
|
catch (e) { return { error: "permerror", reason: e.message }; }
|
|
510
510
|
|
|
511
511
|
var mask = isIpv6 ? parsed.v6Mask : parsed.v4Mask;
|
|
512
|
-
var family = isIpv6 ? 6 : 4; //
|
|
512
|
+
var family = isIpv6 ? 6 : 4; // IP family marker
|
|
513
513
|
|
|
514
514
|
var targetIps = [];
|
|
515
515
|
if (mech === "a") {
|
|
@@ -535,7 +535,7 @@ async function _spfMatchAMx(mech, raw, ip, isIpv6, defaultDomain, dnsLookup, loo
|
|
|
535
535
|
// Crossing this is a permerror; receivers MUST NOT silently
|
|
536
536
|
// truncate, since a misconfigured sender publishing 20 MX hosts
|
|
537
537
|
// would otherwise have only the first 10 contribute to authz.
|
|
538
|
-
if (mxHosts.length > 10) { //
|
|
538
|
+
if (mxHosts.length > 10) { // RFC 7208 §4.6.4 MX limit
|
|
539
539
|
return { error: "permerror",
|
|
540
540
|
reason: "SPF mx:" + parsed.domain + " resolved " + mxHosts.length +
|
|
541
541
|
" MX hosts (RFC 7208 §4.6.4 caps at 10)" };
|
|
@@ -831,7 +831,7 @@ var DMARCBIS_VALID_PSD = { y: 1, n: 1, u: 1 };
|
|
|
831
831
|
|
|
832
832
|
function _parseDmarcRecord(text) {
|
|
833
833
|
var policy = { v: null, p: null, sp: null, np: null, psd: null,
|
|
834
|
-
pct: 100, adkim: "r", aspf: "r" }; //
|
|
834
|
+
pct: 100, adkim: "r", aspf: "r" }; // RFC 7489 default pct
|
|
835
835
|
var pairs = text.split(";"); // allow:bare-split-on-quoted-header — RFC 7489 §6.4 DMARC tag-list grammar: `tag-spec *( ";" tag-spec )` with tag-value = 0*( tval *( WSP / FWS ) ); NO quoted-string allowed
|
|
836
836
|
for (var i = 0; i < pairs.length; i += 1) {
|
|
837
837
|
var kv = pairs[i].trim();
|
|
@@ -1023,8 +1023,8 @@ async function dmarcEvaluate(opts) {
|
|
|
1023
1023
|
// retry-stable. The fallback is the framework's hardening floor
|
|
1024
1024
|
// (replaces Math.random); retry-stability requires the operator to
|
|
1025
1025
|
// wire a key.
|
|
1026
|
-
var pctRaw = parseInt(policy.pct, 10); //
|
|
1027
|
-
var pct = isFinite(pctRaw) && pctRaw >= 0 && pctRaw <= 100 ? pctRaw : 100; //
|
|
1026
|
+
var pctRaw = parseInt(policy.pct, 10); // pct percentage, not bytes
|
|
1027
|
+
var pct = isFinite(pctRaw) && pctRaw >= 0 && pctRaw <= 100 ? pctRaw : 100; // pct percentage, not bytes
|
|
1028
1028
|
var sampleRoll;
|
|
1029
1029
|
if (typeof opts.pctSampleKey === "string" && opts.pctSampleKey.length > 0) {
|
|
1030
1030
|
// Deterministic per-message sample roll. SHAKE256 → first 4 bytes
|
|
@@ -1032,10 +1032,10 @@ async function dmarcEvaluate(opts) {
|
|
|
1032
1032
|
// information needed for 0..99 and uniform mapping is fine.
|
|
1033
1033
|
var hash = nodeCrypto.createHash("shake256", { outputLength: 4 })
|
|
1034
1034
|
.update(String(opts.pctSampleKey)).digest();
|
|
1035
|
-
var u32 = (hash[0] << 24 >>> 0) + (hash[1] << 16) + (hash[2] << 8) + hash[3]; //
|
|
1036
|
-
sampleRoll = u32 % 100; //
|
|
1035
|
+
var u32 = (hash[0] << 24 >>> 0) + (hash[1] << 16) + (hash[2] << 8) + hash[3]; // uint32 bit assembly
|
|
1036
|
+
sampleRoll = u32 % 100; // pct sample roll
|
|
1037
1037
|
} else {
|
|
1038
|
-
sampleRoll = bCrypto.randomInt(0, 100); //
|
|
1038
|
+
sampleRoll = bCrypto.randomInt(0, 100); // pct sample roll
|
|
1039
1039
|
}
|
|
1040
1040
|
var sampled = !pass && pct < 100 && sampleRoll >= pct;
|
|
1041
1041
|
var recommendedAction = pass ? "deliver" :
|
|
@@ -1098,7 +1098,7 @@ function _parseHeaderLines(headerSection) {
|
|
|
1098
1098
|
|
|
1099
1099
|
// RFC 8617 §5.1.2 caps the chain at 50 sets to bound verifier work and
|
|
1100
1100
|
// limit how far an attacker can push junk headers.
|
|
1101
|
-
var ARC_MAX_HOPS = 50; //
|
|
1101
|
+
var ARC_MAX_HOPS = 50; // RFC 8617 §5.1.2 chain ceiling
|
|
1102
1102
|
|
|
1103
1103
|
async function arcVerify(rfc822, opts) {
|
|
1104
1104
|
if (typeof rfc822 !== "string" || rfc822.length === 0) {
|
|
@@ -1253,7 +1253,7 @@ async function arcVerify(rfc822, opts) {
|
|
|
1253
1253
|
// timestamp) and x= (expiration) tags. Default 5 min.
|
|
1254
1254
|
var arcClockSkewMs = typeof opts.clockSkewMs === "number" && opts.clockSkewMs >= 0 // allow:numeric-opt-Infinity — operator-supplied skew, default 5 min
|
|
1255
1255
|
? opts.clockSkewMs : C.TIME.minutes(5);
|
|
1256
|
-
var nowSec = Math.floor(Date.now() / 1000); //
|
|
1256
|
+
var nowSec = Math.floor(Date.now() / 1000); // Unix epoch seconds divisor
|
|
1257
1257
|
|
|
1258
1258
|
for (var hopIdx = 0; hopIdx < hops.length; hopIdx += 1) {
|
|
1259
1259
|
var hop = hops[hopIdx];
|
|
@@ -1268,7 +1268,7 @@ async function arcVerify(rfc822, opts) {
|
|
|
1268
1268
|
var amsX = amsTags.x ? parseInt(amsTags.x, 10) : null;
|
|
1269
1269
|
var asT = asTags.t ? parseInt(asTags.t, 10) : null;
|
|
1270
1270
|
var asX = asTags.x ? parseInt(asTags.x, 10) : null;
|
|
1271
|
-
var skewSec = Math.floor(arcClockSkewMs / 1000); //
|
|
1271
|
+
var skewSec = Math.floor(arcClockSkewMs / 1000); // sec divisor
|
|
1272
1272
|
var timeFault = null;
|
|
1273
1273
|
if (amsT && isFinite(amsT) && amsT - skewSec > nowSec) timeFault = "ams-t-future";
|
|
1274
1274
|
if (amsX && isFinite(amsX) && amsX + skewSec < nowSec) timeFault = "ams-x-expired";
|
|
@@ -1512,8 +1512,8 @@ function _canonRelaxedHeader(name, value) {
|
|
|
1512
1512
|
|
|
1513
1513
|
function _pemFromB64KeyMaterial(b64) {
|
|
1514
1514
|
var pem = "-----BEGIN PUBLIC KEY-----\n";
|
|
1515
|
-
for (var i = 0; i < b64.length; i += 64) { //
|
|
1516
|
-
pem += b64.slice(i, i + 64) + "\n"; //
|
|
1515
|
+
for (var i = 0; i < b64.length; i += 64) { // PEM wrap width
|
|
1516
|
+
pem += b64.slice(i, i + 64) + "\n"; // PEM wrap width
|
|
1517
1517
|
}
|
|
1518
1518
|
pem += "-----END PUBLIC KEY-----\n";
|
|
1519
1519
|
return pem;
|
|
@@ -1819,7 +1819,7 @@ function authResultsEmit(opts) {
|
|
|
1819
1819
|
// // }
|
|
1820
1820
|
|
|
1821
1821
|
var DMARC_RUA_MAX_REPORT_BYTES = C.BYTES.mib(8);
|
|
1822
|
-
var DMARC_RUA_MAX_RECORDS_PER_REPORT = 10000; // allow:raw-
|
|
1822
|
+
var DMARC_RUA_MAX_RECORDS_PER_REPORT = 10000; // allow:raw-time-literal — record cap, not seconds
|
|
1823
1823
|
|
|
1824
1824
|
function _arrayOf(value) {
|
|
1825
1825
|
if (value === undefined || value === null) return [];
|
|
@@ -2020,7 +2020,7 @@ function _shapeAggregateReport(parsed) {
|
|
|
2020
2020
|
function _isValidPtrName(name) {
|
|
2021
2021
|
if (typeof name !== "string") return false;
|
|
2022
2022
|
var trimmed = name.replace(/\.$/, "");
|
|
2023
|
-
if (trimmed.length === 0 || trimmed.length > 253) return false; //
|
|
2023
|
+
if (trimmed.length === 0 || trimmed.length > 253) return false; // RFC 1035 hostname cap
|
|
2024
2024
|
// Labels: 1..63 octets, LDH (letter / digit / hyphen) + leading
|
|
2025
2025
|
// alphanum (RFC 1035 §2.3.1). Permissive: PTR rdata can in practice
|
|
2026
2026
|
// contain underscores (mail-server idiom) — allow underscore in
|
|
@@ -2028,7 +2028,7 @@ function _isValidPtrName(name) {
|
|
|
2028
2028
|
var labels = trimmed.split(".");
|
|
2029
2029
|
for (var i = 0; i < labels.length; i += 1) {
|
|
2030
2030
|
var lab = labels[i];
|
|
2031
|
-
if (lab.length === 0 || lab.length > 63) return false; //
|
|
2031
|
+
if (lab.length === 0 || lab.length > 63) return false; // RFC 1035 label cap
|
|
2032
2032
|
if (!/^[A-Za-z0-9_](?:[A-Za-z0-9_-]{0,61}[A-Za-z0-9_])?$/.test(lab)) return false;
|
|
2033
2033
|
}
|
|
2034
2034
|
return true;
|
package/lib/mail-bimi.js
CHANGED
|
@@ -387,7 +387,7 @@ function validateTinyPsSvg(svgBytes) {
|
|
|
387
387
|
if (t.type === "processingInstruction") {
|
|
388
388
|
var pir = (t.raw || "").trim();
|
|
389
389
|
if (!/^<\?xml\b/i.test(pir)) {
|
|
390
|
-
_vio("pi-forbidden", "processing instruction is forbidden in Tiny-PS: " + pir.slice(0, 40)) /*
|
|
390
|
+
_vio("pi-forbidden", "processing instruction is forbidden in Tiny-PS: " + pir.slice(0, 40)) /* display truncation chars, not bytes */;
|
|
391
391
|
}
|
|
392
392
|
continue;
|
|
393
393
|
}
|
|
@@ -979,7 +979,7 @@ function _extractBimiCertPolicy(cert) {
|
|
|
979
979
|
// RFC 3709 4.1 - LogotypeExtn carries SubjectLogo (best-effort
|
|
980
980
|
// SVG extraction; full RFC 3709 unpack requires walking nested
|
|
981
981
|
// SEQUENCEs to LogotypeImageData).
|
|
982
|
-
var found = _scanForEmbeddedSvg(inner, 8); /*
|
|
982
|
+
var found = _scanForEmbeddedSvg(inner, 8); /* string-prefix length for magic-bytes match, not bytes */
|
|
983
983
|
if (found) rv.logoSvg = found;
|
|
984
984
|
}
|
|
985
985
|
}
|
|
@@ -992,7 +992,7 @@ function _scanForEmbeddedSvg(node, depthBudget) {
|
|
|
992
992
|
|
|
993
993
|
if (!node.constructed) {
|
|
994
994
|
if (!node.value || node.value.length < 4) return null;
|
|
995
|
-
var prefix = node.value.slice(0, Math.min(node.value.length, 64)).toString("utf8"); /*
|
|
995
|
+
var prefix = node.value.slice(0, Math.min(node.value.length, 64)).toString("utf8"); /* display truncation length, not bytes */
|
|
996
996
|
if (prefix.indexOf("<svg") !== -1 || /<\?xml[\s\S]*<svg/.test(prefix)) {
|
|
997
997
|
return node.value.toString("utf8");
|
|
998
998
|
}
|
package/lib/mail-crypto-pgp.js
CHANGED
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
* audit: opts.audit, // optional b.audit handle
|
|
85
85
|
* });
|
|
86
86
|
* // → { armored: "-----BEGIN PGP SIGNATURE----- ...",
|
|
87
|
-
* // multipartSigned:
|
|
87
|
+
* // multipartSigned: <Buffer ...>, // RFC 3156 wrapper bytes
|
|
88
88
|
* // signedAt: epochSeconds, fingerprint: "abcd..." }
|
|
89
89
|
*
|
|
90
90
|
* var rv = b.mail.crypto.pgp.verify({
|
|
@@ -122,23 +122,23 @@ var { defineClass } = require("./framework-error");
|
|
|
122
122
|
var MailCryptoError = defineClass("MailCryptoError", { alwaysPermanent: true });
|
|
123
123
|
|
|
124
124
|
// RFC 9580 §9 public-key algorithm IDs that this module emits/accepts.
|
|
125
|
-
var PUB_ALG_RSA = 1; //
|
|
126
|
-
var PUB_ALG_ED25519_LEGACY = 22; //
|
|
125
|
+
var PUB_ALG_RSA = 1; // RFC 9580 §9.1 RSA
|
|
126
|
+
var PUB_ALG_ED25519_LEGACY = 22; // RFC 9580 §9.1 EdDSA Ed25519Legacy
|
|
127
127
|
|
|
128
128
|
// RFC 9580 §9.5 hash algorithm IDs.
|
|
129
|
-
var HASH_ALG_SHA256 = 8; //
|
|
130
|
-
var HASH_ALG_SHA512 = 10; //
|
|
129
|
+
var HASH_ALG_SHA256 = 8; // RFC 9580 §9.5 SHA2-256
|
|
130
|
+
var HASH_ALG_SHA512 = 10; // RFC 9580 §9.5 SHA2-512
|
|
131
131
|
|
|
132
132
|
// RFC 9580 §5.2.1 signature type — Signature of a binary document.
|
|
133
|
-
var SIG_TYPE_BINARY = 0; //
|
|
133
|
+
var SIG_TYPE_BINARY = 0; // RFC 9580 §5.2.1
|
|
134
134
|
|
|
135
135
|
// RFC 9580 §5.2.3.1 subpacket types we emit / consume.
|
|
136
|
-
var SUBPKT_SIG_CREATION_TIME = 2; //
|
|
137
|
-
var SUBPKT_ISSUER_FPR = 33; //
|
|
136
|
+
var SUBPKT_SIG_CREATION_TIME = 2; // RFC 9580 §5.2.3.4
|
|
137
|
+
var SUBPKT_ISSUER_FPR = 33; // RFC 9580 §5.2.3.35 Issuer Fingerprint
|
|
138
138
|
|
|
139
139
|
// RSA modulus floor — matches DKIM RFC 8301 §3.1 and the framework's
|
|
140
140
|
// cross-mail-surface posture (lib/mail-dkim.js RSA_WEAK_BITS).
|
|
141
|
-
var RSA_MIN_BITS = 2048; //
|
|
141
|
+
var RSA_MIN_BITS = 2048; // RFC 8301 §3.1
|
|
142
142
|
|
|
143
143
|
// ASCII armor framing per RFC 9580 §6.2.
|
|
144
144
|
var ARMOR_BEGIN = "-----BEGIN PGP SIGNATURE-----";
|
|
@@ -564,19 +564,27 @@ function sign(opts) {
|
|
|
564
564
|
// key/cert material flows through createSign/verify, not this path.
|
|
565
565
|
// allow:raw-randombytes-token — boundary string, not auth credential
|
|
566
566
|
var boundary = "blamejs-pgp-" + nodeCrypto.randomBytes(12).toString("hex");
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
567
|
+
// The OpenPGP signature covers the signed-part bytes exactly, so the
|
|
568
|
+
// multipart/signed wrapper is assembled as a Buffer — a JS-string round
|
|
569
|
+
// trip through latin1/utf8 could corrupt non-ASCII signed content and
|
|
570
|
+
// break signature verification. `multipartSigned` is therefore a Buffer.
|
|
571
|
+
var messageBytes = Buffer.isBuffer(message) ? message : Buffer.from(message, "utf8");
|
|
572
|
+
var multipartSigned = Buffer.concat([
|
|
573
|
+
Buffer.from(
|
|
574
|
+
'Content-Type: multipart/signed; micalg="pgp-' + hashName + '"; ' +
|
|
575
|
+
'protocol="application/pgp-signature"; boundary="' + boundary + '"\r\n' +
|
|
576
|
+
"\r\n" +
|
|
577
|
+
"--" + boundary + "\r\n", "utf8"),
|
|
578
|
+
messageBytes,
|
|
579
|
+
Buffer.from(
|
|
580
|
+
"\r\n--" + boundary + "\r\n" +
|
|
581
|
+
'Content-Type: application/pgp-signature; name="signature.asc"\r\n' +
|
|
582
|
+
"Content-Description: OpenPGP digital signature\r\n" +
|
|
583
|
+
'Content-Disposition: attachment; filename="signature.asc"\r\n' +
|
|
584
|
+
"\r\n" +
|
|
585
|
+
armored +
|
|
586
|
+
"--" + boundary + "--\r\n", "utf8"),
|
|
587
|
+
]);
|
|
580
588
|
|
|
581
589
|
// Audit (drop-silent — never crash the request that triggered us).
|
|
582
590
|
_audit(opts.audit, "mail.crypto.pgp.sign", "success", {
|
|
@@ -932,8 +940,8 @@ function _audit(auditHandle, action, outcome, metadata) {
|
|
|
932
940
|
var bCrypto = require("./crypto");
|
|
933
941
|
var pqcSoftware = require("./pqc-software");
|
|
934
942
|
|
|
935
|
-
var PGP_PQ_MAGIC = Buffer.from("BJ-PGP-PQ", "ascii"); //
|
|
936
|
-
var PGP_PQ_VERSION = 1; //
|
|
943
|
+
var PGP_PQ_MAGIC = Buffer.from("BJ-PGP-PQ", "ascii"); // 9-byte framework magic
|
|
944
|
+
var PGP_PQ_VERSION = 1; // envelope version
|
|
937
945
|
|
|
938
946
|
function experimentalEncrypt(opts) {
|
|
939
947
|
opts = validateOpts.requireObject(opts, "mail.crypto.pgp.experimental.encrypt",
|
|
@@ -948,7 +956,7 @@ function experimentalEncrypt(opts) {
|
|
|
948
956
|
"encrypt: opts.recipients must be a non-empty array");
|
|
949
957
|
}
|
|
950
958
|
var plaintext = Buffer.isBuffer(opts.message) ? opts.message : Buffer.from(opts.message, "utf8");
|
|
951
|
-
var sessionKey = bCrypto.generateBytes(32); //
|
|
959
|
+
var sessionKey = bCrypto.generateBytes(32); // 256-bit session key
|
|
952
960
|
var ciphertext = bCrypto.encryptPacked(plaintext, sessionKey);
|
|
953
961
|
var recipientBlobs = [];
|
|
954
962
|
for (var i = 0; i < opts.recipients.length; i += 1) {
|
|
@@ -961,7 +969,7 @@ function experimentalEncrypt(opts) {
|
|
|
961
969
|
throw new MailCryptoError("mail-crypto/pgp/bad-recipient",
|
|
962
970
|
"encrypt: recipients[" + i + "].publicKey must be a Uint8Array (ML-KEM-1024)");
|
|
963
971
|
}
|
|
964
|
-
if (r.recipientId.length > 255) { //
|
|
972
|
+
if (r.recipientId.length > 255) { // u8 length cap
|
|
965
973
|
throw new MailCryptoError("mail-crypto/pgp/bad-recipient",
|
|
966
974
|
"encrypt: recipients[" + i + "].recipientId must be <= 255 bytes");
|
|
967
975
|
}
|
|
@@ -969,7 +977,7 @@ function experimentalEncrypt(opts) {
|
|
|
969
977
|
var kek = bCrypto.kdf(Buffer.concat([
|
|
970
978
|
Buffer.from(encap.sharedSecret),
|
|
971
979
|
Buffer.from("pgp/experimental/chacha20-poly1305", "ascii"),
|
|
972
|
-
]), 32); //
|
|
980
|
+
]), 32); // 256-bit KEK
|
|
973
981
|
var wrappedKey = bCrypto.encryptPacked(sessionKey, kek);
|
|
974
982
|
var ct = Buffer.from(encap.cipherText);
|
|
975
983
|
recipientBlobs.push(Buffer.concat([
|
|
@@ -984,7 +992,7 @@ function experimentalEncrypt(opts) {
|
|
|
984
992
|
var envelope = Buffer.concat([
|
|
985
993
|
PGP_PQ_MAGIC,
|
|
986
994
|
Buffer.from([PGP_PQ_VERSION]),
|
|
987
|
-
Buffer.from([opts.recipients.length]), //
|
|
995
|
+
Buffer.from([opts.recipients.length]), // u8 recipient count
|
|
988
996
|
Buffer.concat(recipientBlobs),
|
|
989
997
|
_u32be(ciphertext.length),
|
|
990
998
|
ciphertext,
|
|
@@ -1038,9 +1046,9 @@ function experimentalDecrypt(opts) {
|
|
|
1038
1046
|
}
|
|
1039
1047
|
var ridLen = envelope[off]; off += 1;
|
|
1040
1048
|
var rid = envelope.slice(off, off + ridLen); off += ridLen;
|
|
1041
|
-
var ctLen = envelope.readUInt16BE(off); off += 2; //
|
|
1049
|
+
var ctLen = envelope.readUInt16BE(off); off += 2; // u16-be width
|
|
1042
1050
|
var ct = envelope.slice(off, off + ctLen); off += ctLen;
|
|
1043
|
-
var wkLen = envelope.readUInt16BE(off); off += 2; //
|
|
1051
|
+
var wkLen = envelope.readUInt16BE(off); off += 2; // u16-be width
|
|
1044
1052
|
var wrappedKey = envelope.slice(off, off + wkLen); off += wkLen;
|
|
1045
1053
|
if (matchedSessionKey) continue;
|
|
1046
1054
|
if (!rid.equals(opts.recipientId)) continue;
|
|
@@ -1053,7 +1061,7 @@ function experimentalDecrypt(opts) {
|
|
|
1053
1061
|
var kek = bCrypto.kdf(Buffer.concat([
|
|
1054
1062
|
Buffer.from(shared),
|
|
1055
1063
|
Buffer.from("pgp/experimental/chacha20-poly1305", "ascii"),
|
|
1056
|
-
]), 32); //
|
|
1064
|
+
]), 32); // 256-bit KEK
|
|
1057
1065
|
try { matchedSessionKey = bCrypto.decryptPacked(wrappedKey, kek); }
|
|
1058
1066
|
catch (e2) {
|
|
1059
1067
|
throw new MailCryptoError("mail-crypto/pgp/unwrap-failed",
|
|
@@ -1064,7 +1072,7 @@ function experimentalDecrypt(opts) {
|
|
|
1064
1072
|
throw new MailCryptoError("mail-crypto/pgp/no-matching-recipient",
|
|
1065
1073
|
"decrypt: no recipient in envelope matches opts.recipientId");
|
|
1066
1074
|
}
|
|
1067
|
-
var bodyLen = envelope.readUInt32BE(off); off += 4; //
|
|
1075
|
+
var bodyLen = envelope.readUInt32BE(off); off += 4; // u32-be width
|
|
1068
1076
|
var body = envelope.slice(off, off + bodyLen);
|
|
1069
1077
|
var plaintext;
|
|
1070
1078
|
try { plaintext = bCrypto.decryptPacked(body, matchedSessionKey); }
|
|
@@ -1079,8 +1087,8 @@ function experimentalDecrypt(opts) {
|
|
|
1079
1087
|
function _armorMessage(bytes) {
|
|
1080
1088
|
var b64 = bytes.toString("base64");
|
|
1081
1089
|
var lines = [];
|
|
1082
|
-
for (var i = 0; i < b64.length; i += 64) { //
|
|
1083
|
-
lines.push(b64.slice(i, i + 64)); //
|
|
1090
|
+
for (var i = 0; i < b64.length; i += 64) { // RFC 2045 base64 line length
|
|
1091
|
+
lines.push(b64.slice(i, i + 64)); // RFC 2045 base64 line length
|
|
1084
1092
|
}
|
|
1085
1093
|
return "-----BEGIN PGP MESSAGE-----\r\nVersion: blamejs-pgp-pq-v1\r\n\r\n" +
|
|
1086
1094
|
lines.join("\r\n") + "\r\n-----END PGP MESSAGE-----\r\n";
|
|
@@ -1159,7 +1167,7 @@ function wkdFetch(email, opts) {
|
|
|
1159
1167
|
var maxBytes = typeof opts.maxKeyBytes === "number" ? opts.maxKeyBytes : (256 * 1024); // allow:raw-byte-literal — 256 KiB default key cap
|
|
1160
1168
|
var urls = wkdComputeUrl(email, { advancedHost: opts.advancedHost });
|
|
1161
1169
|
return Promise.resolve(opts.httpsGet(urls.direct)).then(function (resp) {
|
|
1162
|
-
if (resp && resp.status === 200 && Buffer.isBuffer(resp.body) && resp.body.length > 0) { //
|
|
1170
|
+
if (resp && resp.status === 200 && Buffer.isBuffer(resp.body) && resp.body.length > 0) { // HTTP 200
|
|
1163
1171
|
if (resp.body.length > maxBytes) {
|
|
1164
1172
|
throw new MailCryptoError("mail-crypto/pgp/wkd-too-large",
|
|
1165
1173
|
"wkd.fetch: key bytes " + resp.body.length + " exceed maxKeyBytes=" + maxBytes);
|
|
@@ -1167,7 +1175,7 @@ function wkdFetch(email, opts) {
|
|
|
1167
1175
|
return { keyBytes: resp.body, source: "direct", url: urls.direct };
|
|
1168
1176
|
}
|
|
1169
1177
|
return Promise.resolve(opts.httpsGet(urls.advanced)).then(function (resp2) {
|
|
1170
|
-
if (resp2 && resp2.status === 200 && Buffer.isBuffer(resp2.body) && resp2.body.length > 0) { //
|
|
1178
|
+
if (resp2 && resp2.status === 200 && Buffer.isBuffer(resp2.body) && resp2.body.length > 0) { // HTTP 200
|
|
1171
1179
|
if (resp2.body.length > maxBytes) {
|
|
1172
1180
|
throw new MailCryptoError("mail-crypto/pgp/wkd-too-large",
|
|
1173
1181
|
"wkd.fetch: key bytes " + resp2.body.length + " exceed maxKeyBytes=" + maxBytes);
|
|
@@ -1190,7 +1198,7 @@ function wkdComputeUrl(email, opts) {
|
|
|
1190
1198
|
// upper bound (64 local + 1 @ + 255 domain). Refuse beyond that BEFORE
|
|
1191
1199
|
// any further processing to defend tokenisation paths against
|
|
1192
1200
|
// adversarial-length inputs.
|
|
1193
|
-
if (email.length > 320) { //
|
|
1201
|
+
if (email.length > 320) { // RFC 5321 max email length
|
|
1194
1202
|
throw new MailCryptoError("mail-crypto/pgp/bad-email",
|
|
1195
1203
|
"wkd.computeUrl: email length " + email.length + " exceeds RFC 5321 max 320 octets");
|
|
1196
1204
|
}
|
|
@@ -1214,11 +1222,11 @@ function wkdComputeUrl(email, opts) {
|
|
|
1214
1222
|
throw new MailCryptoError("mail-crypto/pgp/bad-domain",
|
|
1215
1223
|
"wkd.computeUrl: domain must not contain empty labels");
|
|
1216
1224
|
}
|
|
1217
|
-
if (domain.length > 253) { //
|
|
1225
|
+
if (domain.length > 253) { // RFC 1035 §2.3.4 max domain length
|
|
1218
1226
|
throw new MailCryptoError("mail-crypto/pgp/bad-domain",
|
|
1219
1227
|
"wkd.computeUrl: domain length " + domain.length + " exceeds RFC 1035 max 253 octets");
|
|
1220
1228
|
}
|
|
1221
|
-
var hashed = bCrypto.kdf(Buffer.from(localLower, "utf8"), 20); //
|
|
1229
|
+
var hashed = bCrypto.kdf(Buffer.from(localLower, "utf8"), 20); // 20-byte hash per draft-koch §3.1
|
|
1222
1230
|
var encoded = _zbase32Encode(hashed);
|
|
1223
1231
|
var advancedHost = opts.advancedHost || ("openpgpkey." + domain);
|
|
1224
1232
|
var encodedLocal = encodeURIComponent(localRaw);
|
|
@@ -1238,15 +1246,15 @@ function _zbase32Encode(buf) {
|
|
|
1238
1246
|
var bitCount = 0;
|
|
1239
1247
|
var out = "";
|
|
1240
1248
|
for (var i = 0; i < buf.length; i += 1) {
|
|
1241
|
-
bits = (bits << 8) | buf[i]; //
|
|
1242
|
-
bitCount += 8; //
|
|
1243
|
-
while (bitCount >= 5) { //
|
|
1244
|
-
bitCount -= 5; //
|
|
1245
|
-
out += ZBASE32_ALPHABET.charAt((bits >> bitCount) & 0x1f); //
|
|
1249
|
+
bits = (bits << 8) | buf[i]; // 8 bits per input byte
|
|
1250
|
+
bitCount += 8; // 8 bits per input byte
|
|
1251
|
+
while (bitCount >= 5) { // 5 bits per zbase32 char
|
|
1252
|
+
bitCount -= 5; // 5 bits per zbase32 char
|
|
1253
|
+
out += ZBASE32_ALPHABET.charAt((bits >> bitCount) & 0x1f); // 5-bit mask
|
|
1246
1254
|
}
|
|
1247
1255
|
}
|
|
1248
1256
|
if (bitCount > 0) {
|
|
1249
|
-
out += ZBASE32_ALPHABET.charAt((bits << (5 - bitCount)) & 0x1f); //
|
|
1257
|
+
out += ZBASE32_ALPHABET.charAt((bits << (5 - bitCount)) & 0x1f); // final partial char
|
|
1250
1258
|
}
|
|
1251
1259
|
return out;
|
|
1252
1260
|
}
|
package/lib/mail-crypto-smime.js
CHANGED
|
@@ -109,9 +109,9 @@ var MailCryptoError = defineClass("MailCryptoError", { alwaysPermanent: true });
|
|
|
109
109
|
// Constant posture values exported so operators reading this module
|
|
110
110
|
// from configuration code can pin to them by reference rather than
|
|
111
111
|
// hand-copying strings. These reflect RFC 8551 §2.5 + RFC 8301 floors.
|
|
112
|
-
var RSA_MIN_BITS = 2048; //
|
|
112
|
+
var RSA_MIN_BITS = 2048; // RFC 8301 §3.1
|
|
113
113
|
var ALLOWED_HASHES = ["sha256", "sha384", "sha512"];
|
|
114
|
-
var REFUSED_HASHES = ["md5", "sha1"]; //
|
|
114
|
+
var REFUSED_HASHES = ["md5", "sha1"]; // SHAttered / RFC 8551 §2.5
|
|
115
115
|
|
|
116
116
|
// PROFILES + COMPLIANCE_POSTURES — the framework's standard cross-
|
|
117
117
|
// primitive contract. sign() and verify() read these to determine which
|
|
@@ -207,7 +207,7 @@ function sign(opts) {
|
|
|
207
207
|
"smime.sign: " + ((e && e.message) || String(e)));
|
|
208
208
|
}
|
|
209
209
|
var boundary = opts.boundary ||
|
|
210
|
-
"blamejs-smime-" + bCrypto.generateToken(32); //
|
|
210
|
+
"blamejs-smime-" + bCrypto.generateToken(32); // 32-hex-char boundary token
|
|
211
211
|
var sigBase64 = _wrapBase64(sd.toString("base64"));
|
|
212
212
|
var multipart =
|
|
213
213
|
"Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; " +
|
|
@@ -679,8 +679,8 @@ function _oidToDigest(oid) {
|
|
|
679
679
|
function _wrapBase64(s) {
|
|
680
680
|
// 64-char lines per RFC 2045 §6.8.
|
|
681
681
|
var out = [];
|
|
682
|
-
for (var i = 0; i < s.length; i += 64) { //
|
|
683
|
-
out.push(s.slice(i, i + 64)); //
|
|
682
|
+
for (var i = 0; i < s.length; i += 64) { // RFC 2045 §6.8 line length
|
|
683
|
+
out.push(s.slice(i, i + 64)); // RFC 2045 §6.8 line length
|
|
684
684
|
}
|
|
685
685
|
return out.join("\r\n");
|
|
686
686
|
}
|
package/lib/mail-dav.js
CHANGED
|
@@ -244,7 +244,7 @@ function create(opts) {
|
|
|
244
244
|
var qIdx = reqUrl.indexOf("?");
|
|
245
245
|
var path = qIdx >= 0 ? reqUrl.slice(0, qIdx) : reqUrl;
|
|
246
246
|
// Refuse path traversal / null bytes before decoding.
|
|
247
|
-
if (path.indexOf("\0") >= 0 || //
|
|
247
|
+
if (path.indexOf("\0") >= 0 || // NUL byte refusal
|
|
248
248
|
/(?:^|\/)\.\.(?:\/|$)/.test(path) ||
|
|
249
249
|
/%2e%2e/i.test(path) ||
|
|
250
250
|
/%00/i.test(path)) {
|