@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-server-imap.js
CHANGED
|
@@ -140,10 +140,10 @@ var DEFAULT_GREETING_VENDOR = "blamejs IMAP4rev2";
|
|
|
140
140
|
var pkgVersion = require("../package.json").version;
|
|
141
141
|
|
|
142
142
|
// Error-message clamp bytes — protocol-string clamp, not a byte count.
|
|
143
|
-
// Centralized so the
|
|
143
|
+
// Centralized so the marker lives in one place
|
|
144
144
|
// and the per-call sites read cleanly.
|
|
145
|
-
var ERR_CLAMP = 200; //
|
|
146
|
-
var LINE_PREVIEW = 80; //
|
|
145
|
+
var ERR_CLAMP = 200; // protocol-reply error-message clamp
|
|
146
|
+
var LINE_PREVIEW = 80; // audit-line preview clamp
|
|
147
147
|
|
|
148
148
|
// RFC 9051 §6.3.12 + RFC 5322 §3.3 date-time parser for IMAP APPEND.
|
|
149
149
|
// Format: `DD-Mon-YYYY HH:MM:SS ±HHMM` where Mon is the 3-letter
|
|
@@ -152,8 +152,8 @@ var LINE_PREVIEW = 80;
|
|
|
152
152
|
// millisecond epoch, or null on any parse failure — the caller emits
|
|
153
153
|
// `BAD` rather than silently using `Date.now()`.
|
|
154
154
|
var IMAP_MONTHS = Object.freeze({
|
|
155
|
-
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5, //
|
|
156
|
-
jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11, //
|
|
155
|
+
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5, // month-index table (0-5)
|
|
156
|
+
jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11, // month-index table (6-11)
|
|
157
157
|
});
|
|
158
158
|
var IMAP_DT_RE = /^\s*(\d{1,2})-([A-Za-z]{3})-(\d{4})\s+(\d{2}):(\d{2}):(\d{2})\s+([+-])(\d{2})(\d{2})\s*$/;
|
|
159
159
|
function _parseImapDateTime(s) {
|
|
@@ -195,10 +195,10 @@ function _parseImapDateTime(s) {
|
|
|
195
195
|
// oversize.
|
|
196
196
|
function _validateMailboxName(name, opts) {
|
|
197
197
|
if (typeof name !== "string" || name.length === 0) return false;
|
|
198
|
-
if (name.length > 1024) return false; //
|
|
198
|
+
if (name.length > 1024) return false; // mailbox name cap
|
|
199
199
|
for (var i = 0; i < name.length; i += 1) {
|
|
200
200
|
var c = name.charCodeAt(i);
|
|
201
|
-
if (c < 0x20 || c === 0x7F) return false; //
|
|
201
|
+
if (c < 0x20 || c === 0x7F) return false; // control-byte refusal
|
|
202
202
|
}
|
|
203
203
|
if (name.indexOf("..") !== -1) return false;
|
|
204
204
|
if (name === "/" || name[0] === "/" || name[name.length - 1] === "/") return false;
|
|
@@ -311,7 +311,7 @@ function create(opts) {
|
|
|
311
311
|
}
|
|
312
312
|
rawSocket.once("close", function () { rateLimit.releaseConnection(remoteAddress); });
|
|
313
313
|
|
|
314
|
-
var connectionId = "imapconn-" + bCrypto.generateToken(8); //
|
|
314
|
+
var connectionId = "imapconn-" + bCrypto.generateToken(8); // connection-id length
|
|
315
315
|
var socket = rawSocket;
|
|
316
316
|
connections.add(socket);
|
|
317
317
|
|
|
@@ -655,8 +655,8 @@ function create(opts) {
|
|
|
655
655
|
// exercise them; each handler refuses gracefully when the operator
|
|
656
656
|
// backend doesn't supply the corresponding hook).
|
|
657
657
|
caps.push("NOTIFY"); // RFC 5465
|
|
658
|
-
caps.push("METADATA"); // RFC 5464 — per-mailbox annotations //
|
|
659
|
-
caps.push("METADATA-SERVER"); // RFC 5464 §3.1 — server-wide annotations //
|
|
658
|
+
caps.push("METADATA"); // RFC 5464 — per-mailbox annotations // RFC number in comment
|
|
659
|
+
caps.push("METADATA-SERVER"); // RFC 5464 §3.1 — server-wide annotations // RFC number in comment
|
|
660
660
|
caps.push("CATENATE"); // RFC 4469 — APPEND from existing parts
|
|
661
661
|
// NB: COMPRESS=DEFLATE (RFC 4978) intentionally NOT advertised —
|
|
662
662
|
// CRIME-class compression-oracle attack on the encrypted IMAP
|
|
@@ -1369,7 +1369,7 @@ function create(opts) {
|
|
|
1369
1369
|
while (pi < partsBody.length && /\s/.test(partsBody[pi])) pi += 1;
|
|
1370
1370
|
if (pi >= partsBody.length) break;
|
|
1371
1371
|
if (/^URL\b/i.test(partsBody.slice(pi))) {
|
|
1372
|
-
pi += 3; //
|
|
1372
|
+
pi += 3; // length of literal "URL" keyword
|
|
1373
1373
|
while (pi < partsBody.length && /\s/.test(partsBody[pi])) pi += 1;
|
|
1374
1374
|
if (partsBody[pi] !== "\"") {
|
|
1375
1375
|
_writeTagged(socket, tag, "BAD APPEND CATENATE URL value must be quoted-string");
|
|
@@ -1818,7 +1818,7 @@ function create(opts) {
|
|
|
1818
1818
|
throw new MailServerImapError("mail-server-imap/already-listening",
|
|
1819
1819
|
"listen: already listening");
|
|
1820
1820
|
}
|
|
1821
|
-
var port = listenOpts.port === undefined ? 143 : listenOpts.port; //
|
|
1821
|
+
var port = listenOpts.port === undefined ? 143 : listenOpts.port; // RFC 9051 IMAP port (IANA)
|
|
1822
1822
|
var address = listenOpts.address || "0.0.0.0";
|
|
1823
1823
|
tcpServer = net.createServer(function (socket) { _handleConnection(socket); });
|
|
1824
1824
|
return new Promise(function (resolve, reject) {
|
package/lib/mail-server-jmap.js
CHANGED
|
@@ -232,7 +232,7 @@ function create(opts) {
|
|
|
232
232
|
tenantScope: opts.tenantScope || null,
|
|
233
233
|
agentTenantId: opts.agentTenantId || null,
|
|
234
234
|
});
|
|
235
|
-
var sessionState = bCrypto.generateToken(16); //
|
|
235
|
+
var sessionState = bCrypto.generateToken(16); // opaque session-state token length
|
|
236
236
|
|
|
237
237
|
function _emit(action, metadata, outcome) {
|
|
238
238
|
try {
|
|
@@ -262,7 +262,7 @@ function create(opts) {
|
|
|
262
262
|
for (var k = 0; k < keys.length; k += 1) {
|
|
263
263
|
var key = keys[k];
|
|
264
264
|
var val = args[key];
|
|
265
|
-
if (key.charCodeAt(0) === 0x23) { //
|
|
265
|
+
if (key.charCodeAt(0) === 0x23) { // `#` (0x23) is the JMAP back-ref-key prefix
|
|
266
266
|
// `#<srcClientId>` → key strips the `#`; value is { resultOf, name, path }
|
|
267
267
|
var targetKey = key.slice(1);
|
|
268
268
|
if (!val || typeof val !== "object" || Array.isArray(val) ||
|
|
@@ -443,11 +443,11 @@ function create(opts) {
|
|
|
443
443
|
// re-auth flow (a 400 looks like a malformed request, which it
|
|
444
444
|
// isn't). Everything else stays 400 per RFC 8620 §3.6.1.
|
|
445
445
|
if (response && response.type === "urn:ietf:params:jmap:error:forbidden") {
|
|
446
|
-
res.statusCode = 401; //
|
|
446
|
+
res.statusCode = 401; // HTTP status codes
|
|
447
447
|
} else if (response && response.type) {
|
|
448
|
-
res.statusCode = 400; //
|
|
448
|
+
res.statusCode = 400; // HTTP status codes
|
|
449
449
|
} else {
|
|
450
|
-
res.statusCode = 200; //
|
|
450
|
+
res.statusCode = 200; // HTTP status codes
|
|
451
451
|
}
|
|
452
452
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
453
453
|
res.end(JSON.stringify(response));
|
|
@@ -596,7 +596,7 @@ function create(opts) {
|
|
|
596
596
|
pingN = 0;
|
|
597
597
|
} else {
|
|
598
598
|
pingN = parseInt(params.ping, 10);
|
|
599
|
-
if (!isFinite(pingN) || pingN < 5) pingN = 30; //
|
|
599
|
+
if (!isFinite(pingN) || pingN < 5) pingN = 30; // RFC 8620 §7.3 default ping seconds
|
|
600
600
|
if (pingN > 900) pingN = 900; // allow:raw-byte-literal — operator-supplied ping seconds, not bytes // allow:raw-time-literal — explicit max-ping cap (15 minutes)
|
|
601
601
|
}
|
|
602
602
|
|
|
@@ -613,7 +613,7 @@ function create(opts) {
|
|
|
613
613
|
// the current session state so a fresh subscriber can compare
|
|
614
614
|
// against its cached `state` to know whether a missed update
|
|
615
615
|
// happened during the (re)connect.
|
|
616
|
-
res.write("retry: 5000\n\n"); //
|
|
616
|
+
res.write("retry: 5000\n\n"); // SSE reconnect-after hint (5s)
|
|
617
617
|
res.write(": connected\n\n");
|
|
618
618
|
|
|
619
619
|
var closed = false;
|
|
@@ -709,12 +709,12 @@ function create(opts) {
|
|
|
709
709
|
// RFC 8620 §1.2 — JMAP `Id` is a non-empty string of < 256 octets in
|
|
710
710
|
// `[A-Za-z0-9_-]`. The earlier shape capped at 64 chars which refused
|
|
711
711
|
// legitimate-shape accounts; widen to the full spec maximum.
|
|
712
|
-
var MAX_JMAP_ID_LEN = 255; //
|
|
712
|
+
var MAX_JMAP_ID_LEN = 255; // RFC 8620 §1.2 Id max length
|
|
713
713
|
var JMAP_ID_RE = /^[A-Za-z0-9_-]{1,255}$/;
|
|
714
714
|
// Anti-polynomial: bound the URL length BEFORE any regex / split runs
|
|
715
715
|
// (CodeQL flags `\/+` on uncontrolled input). Headers + URL paths in
|
|
716
716
|
// practice stay well under 8 KiB; over-long URLs refuse outright.
|
|
717
|
-
var MAX_URL_LEN = 8192; //
|
|
717
|
+
var MAX_URL_LEN = 8192; // 8 KiB URL cap
|
|
718
718
|
|
|
719
719
|
// Strip a query string + walk the path producing non-empty segments,
|
|
720
720
|
// WITHOUT any unbounded regex. Returns an empty array when the URL
|
|
@@ -729,7 +729,7 @@ function create(opts) {
|
|
|
729
729
|
var cur = "";
|
|
730
730
|
for (var i = 0; i < pathOnly.length; i += 1) {
|
|
731
731
|
var ch = pathOnly.charCodeAt(i);
|
|
732
|
-
if (ch === 0x2f) { //
|
|
732
|
+
if (ch === 0x2f) { // '/' (0x2f)
|
|
733
733
|
if (cur.length > 0) { out.push(cur); cur = ""; }
|
|
734
734
|
} else {
|
|
735
735
|
cur += pathOnly[i];
|
|
@@ -821,7 +821,7 @@ function create(opts) {
|
|
|
821
821
|
throw new MailServerJmapError("mail-server-jmap/bad-upload-result",
|
|
822
822
|
"uploadBlob backend MUST return { blobId, type?, size? }");
|
|
823
823
|
}
|
|
824
|
-
res.statusCode = 201; //
|
|
824
|
+
res.statusCode = 201; // HTTP 201 Created
|
|
825
825
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
826
826
|
res.end(JSON.stringify({
|
|
827
827
|
accountId: accountId,
|
|
@@ -844,7 +844,7 @@ function create(opts) {
|
|
|
844
844
|
req.on("error", function () {
|
|
845
845
|
if (!refused) {
|
|
846
846
|
refused = true;
|
|
847
|
-
try { res.statusCode = 400; res.end(); } //
|
|
847
|
+
try { res.statusCode = 400; res.end(); } // HTTP 400
|
|
848
848
|
catch (_e) { /* silent-catch: socket already torn down */ }
|
|
849
849
|
}
|
|
850
850
|
});
|
|
@@ -1019,7 +1019,7 @@ function create(opts) {
|
|
|
1019
1019
|
// RFC 8887 §3.1 — server MUST select `jmap` if offered. Refuse the
|
|
1020
1020
|
// connection cleanly if subprotocol negotiation came back null.
|
|
1021
1021
|
if (conn.subprotocol !== "jmap") {
|
|
1022
|
-
try { conn.close(1002, "RFC 8887 requires Sec-WebSocket-Protocol: jmap"); } //
|
|
1022
|
+
try { conn.close(1002, "RFC 8887 requires Sec-WebSocket-Protocol: jmap"); } // RFC 6455 protocol-error close code
|
|
1023
1023
|
catch (_e) { /* silent-catch: closed */ }
|
|
1024
1024
|
return null;
|
|
1025
1025
|
}
|
|
@@ -1302,7 +1302,7 @@ function emailSubmissionSetHandler(opts) {
|
|
|
1302
1302
|
throw new MailServerJmapError("mail-server-jmap/no-identities",
|
|
1303
1303
|
"emailSubmissionSetHandler: opts.identities(accountId) function is required (returns Array<{id,email}>)");
|
|
1304
1304
|
}
|
|
1305
|
-
var maxRecipients = opts.maxRecipients || 1000; //
|
|
1305
|
+
var maxRecipients = opts.maxRecipients || 1000; // recipient cap mirrors b.mail.send.deliver
|
|
1306
1306
|
if (typeof maxRecipients !== "number" || !isFinite(maxRecipients) || maxRecipients < 1) {
|
|
1307
1307
|
throw new MailServerJmapError("mail-server-jmap/bad-max-recipients",
|
|
1308
1308
|
"emailSubmissionSetHandler: opts.maxRecipients MUST be a positive integer");
|
|
@@ -1422,7 +1422,7 @@ function emailSubmissionSetHandler(opts) {
|
|
|
1422
1422
|
return {
|
|
1423
1423
|
accountId: accountId,
|
|
1424
1424
|
oldState: args.ifInState || null,
|
|
1425
|
-
newState: bCrypto.generateToken(16), //
|
|
1425
|
+
newState: bCrypto.generateToken(16), // opaque state token length
|
|
1426
1426
|
created: Object.keys(created).length > 0 ? created : null,
|
|
1427
1427
|
notCreated: Object.keys(notCreated).length > 0 ? notCreated : null,
|
|
1428
1428
|
updated: Object.keys(updated).length > 0 ? updated : null,
|
|
@@ -1519,7 +1519,7 @@ function emailSubmissionSetHandler(opts) {
|
|
|
1519
1519
|
};
|
|
1520
1520
|
}
|
|
1521
1521
|
|
|
1522
|
-
var newId = bCrypto.generateToken(12); //
|
|
1522
|
+
var newId = bCrypto.generateToken(12); // JMAP-server-assigned id
|
|
1523
1523
|
return {
|
|
1524
1524
|
id: newId,
|
|
1525
1525
|
identityId: sub.identityId,
|
|
@@ -145,12 +145,12 @@ var MailServerManageSieveError = defineClass("MailServerManageSieveError",
|
|
|
145
145
|
{ alwaysPermanent: true });
|
|
146
146
|
|
|
147
147
|
// RFC 5804 §1 default port (IANA-assigned).
|
|
148
|
-
var DEFAULT_PORT = 4190; //
|
|
149
|
-
var DEFAULT_MAX_LINE_BYTES = 8192; //
|
|
148
|
+
var DEFAULT_PORT = 4190; // RFC 5804 §1 / IANA managesieve port
|
|
149
|
+
var DEFAULT_MAX_LINE_BYTES = 8192; // matches guardManageSieveCommand strict cap
|
|
150
150
|
var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.minutes(5);
|
|
151
151
|
var DEFAULT_GREETING_VENDOR = "blamejs ManageSieve";
|
|
152
152
|
|
|
153
|
-
var ERR_CLAMP = 200; //
|
|
153
|
+
var ERR_CLAMP = 200; // protocol-reply error-message clamp
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
156
|
* @primitive b.mail.server.managesieve.create
|
|
@@ -260,7 +260,7 @@ function create(opts) {
|
|
|
260
260
|
try { rawSocket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
|
-
var connectionId = "msvconn-" + bCrypto.generateToken(8); //
|
|
263
|
+
var connectionId = "msvconn-" + bCrypto.generateToken(8); // connection-id length
|
|
264
264
|
var socket = rawSocket;
|
|
265
265
|
connections.add(socket);
|
|
266
266
|
// Single close handler covers BOTH operator-driven `_close(socket)`
|
package/lib/mail-server-mx.js
CHANGED
|
@@ -150,7 +150,7 @@ var MailServerMxError = defineClass("MailServerMxError", { alwaysPermanent: true
|
|
|
150
150
|
// RFC 5321 §4.5.3.1 — wire-protocol limits.
|
|
151
151
|
var DEFAULT_MAX_LINE_BYTES = C.BYTES.kib(1);
|
|
152
152
|
var DEFAULT_MAX_MESSAGE_BYTES = C.BYTES.mib(50);
|
|
153
|
-
var DEFAULT_MAX_RCPTS_PER_MESSAGE = 100; //
|
|
153
|
+
var DEFAULT_MAX_RCPTS_PER_MESSAGE = 100; // RFC 5321 §4.5.3.1.8 recipient cap
|
|
154
154
|
var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.minutes(5);
|
|
155
155
|
var DEFAULT_GREETING = "blamejs ESMTP";
|
|
156
156
|
|
|
@@ -161,18 +161,18 @@ var REPLY_220_READY = "220";
|
|
|
161
161
|
var REPLY_221_BYE = "221";
|
|
162
162
|
var REPLY_250_OK = "250";
|
|
163
163
|
var REPLY_354_START_INPUT = "354";
|
|
164
|
-
var REPLY_421_SERVICE_NOT_AVAIL = "421"; //
|
|
165
|
-
var REPLY_450_MAILBOX_BUSY = "450"; //
|
|
166
|
-
var REPLY_451_LOCAL_ERROR = "451"; //
|
|
167
|
-
var REPLY_452_INSUFFICIENT_STG = "452"; //
|
|
168
|
-
var REPLY_500_SYNTAX = "500"; //
|
|
169
|
-
var REPLY_501_BAD_ARGS = "501"; //
|
|
170
|
-
var REPLY_502_NOT_IMPLEMENTED = "502"; //
|
|
171
|
-
var REPLY_503_BAD_SEQUENCE = "503"; //
|
|
172
|
-
var REPLY_530_AUTH_REQUIRED = "530"; //
|
|
173
|
-
var REPLY_550_MAILBOX_UNAVAIL = "550"; //
|
|
174
|
-
var REPLY_552_SIZE_EXCEEDED = "552"; //
|
|
175
|
-
var REPLY_554_TRANSACTION_FAILED = "554"; //
|
|
164
|
+
var REPLY_421_SERVICE_NOT_AVAIL = "421"; // SMTP transient code
|
|
165
|
+
var REPLY_450_MAILBOX_BUSY = "450"; // SMTP transient code (greylist tempfail)
|
|
166
|
+
var REPLY_451_LOCAL_ERROR = "451"; // SMTP transient code
|
|
167
|
+
var REPLY_452_INSUFFICIENT_STG = "452"; // SMTP transient code
|
|
168
|
+
var REPLY_500_SYNTAX = "500"; // SMTP permanent code
|
|
169
|
+
var REPLY_501_BAD_ARGS = "501"; // SMTP permanent code
|
|
170
|
+
var REPLY_502_NOT_IMPLEMENTED = "502"; // SMTP permanent code
|
|
171
|
+
var REPLY_503_BAD_SEQUENCE = "503"; // SMTP permanent code
|
|
172
|
+
var REPLY_530_AUTH_REQUIRED = "530"; // SMTP permanent code
|
|
173
|
+
var REPLY_550_MAILBOX_UNAVAIL = "550"; // SMTP permanent code
|
|
174
|
+
var REPLY_552_SIZE_EXCEEDED = "552"; // SMTP permanent code
|
|
175
|
+
var REPLY_554_TRANSACTION_FAILED = "554"; // SMTP permanent code
|
|
176
176
|
|
|
177
177
|
var RE_MAIL_FROM = /^MAIL\s+FROM:\s*<([^>]*)>(?:\s+(.*))?$/i;
|
|
178
178
|
var RE_RCPT_TO = /^RCPT\s+TO:\s*<([^>]+)>(?:\s+.*)?$/i;
|
|
@@ -346,7 +346,7 @@ function create(opts) {
|
|
|
346
346
|
}
|
|
347
347
|
socket.once("close", function () { rateLimit.releaseConnection(remoteAddress); });
|
|
348
348
|
|
|
349
|
-
var connectionId = "mxconn-" + bCrypto.generateToken(8); //
|
|
349
|
+
var connectionId = "mxconn-" + bCrypto.generateToken(8); // connection-id length
|
|
350
350
|
connections.add(socket);
|
|
351
351
|
|
|
352
352
|
// Backpressure observer — `_writeReply` flips `_bpEmitted` after
|
|
@@ -520,7 +520,7 @@ function create(opts) {
|
|
|
520
520
|
err.code === "guard-smtp-command/bare-cr" ||
|
|
521
521
|
err.code === "guard-smtp-command/nul-byte") {
|
|
522
522
|
_emit("mail.server.mx.smtp_smuggling_detected",
|
|
523
|
-
{ connectionId: state.id, code: err.code, line: line.slice(0, 200) }, //
|
|
523
|
+
{ connectionId: state.id, code: err.code, line: line.slice(0, 200) }, // audit-log line truncation
|
|
524
524
|
"denied");
|
|
525
525
|
}
|
|
526
526
|
_writeReply(socket, REPLY_500_SYNTAX, "5.5.2 Syntax error (" + (err.code || "bad-line") + ")");
|
|
@@ -936,7 +936,7 @@ function create(opts) {
|
|
|
936
936
|
// for observability. Bounded to keep the audit metadata size
|
|
937
937
|
// predictable; the per-IP recipient-failure rate-limit elsewhere
|
|
938
938
|
// bounds long-run scanner damage.
|
|
939
|
-
var MAX_REFUSED_RCPTS_PER_TXN = 32; //
|
|
939
|
+
var MAX_REFUSED_RCPTS_PER_TXN = 32; // bounded audit-metadata list cap
|
|
940
940
|
function _trackRefusedRcpt(state, rcpt, reason) {
|
|
941
941
|
if (!Array.isArray(state.refusedRcpts)) state.refusedRcpts = [];
|
|
942
942
|
if (state.refusedRcpts.length >= MAX_REFUSED_RCPTS_PER_TXN) return;
|
|
@@ -968,7 +968,7 @@ function create(opts) {
|
|
|
968
968
|
}
|
|
969
969
|
// Port 0 (ephemeral, test mode) must NOT fall back to 25 — the
|
|
970
970
|
// `|| 25` short-circuit was a footgun on the test path.
|
|
971
|
-
var port = listenOpts.port === undefined ? 25 : listenOpts.port; //
|
|
971
|
+
var port = listenOpts.port === undefined ? 25 : listenOpts.port; // SMTP MX port (IANA)
|
|
972
972
|
var address = listenOpts.address || "0.0.0.0";
|
|
973
973
|
tcpServer = net.createServer(function (socket) {
|
|
974
974
|
_handleConnection(socket);
|
package/lib/mail-server-pop3.js
CHANGED
|
@@ -119,7 +119,7 @@ var audit = lazyRequire(function () { return require("./audit"); });
|
|
|
119
119
|
|
|
120
120
|
var MailServerPop3Error = defineClass("MailServerPop3Error", { alwaysPermanent: true });
|
|
121
121
|
|
|
122
|
-
var DEFAULT_MAX_LINE_BYTES = 1024; //
|
|
122
|
+
var DEFAULT_MAX_LINE_BYTES = 1024; // RFC 2449 §4 line cap (permissive)
|
|
123
123
|
var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.minutes(10);
|
|
124
124
|
// RFC 1939 §6 — UPDATE-state commit (the actual delete on QUIT) is
|
|
125
125
|
// the only place the backend writes; a hung commitPop3Drop leaves
|
|
@@ -130,7 +130,7 @@ var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.minutes(10);
|
|
|
130
130
|
var DEFAULT_COMMIT_TIMEOUT_MS = C.TIME.seconds(30);
|
|
131
131
|
var DEFAULT_GREETING_VENDOR = "blamejs POP3";
|
|
132
132
|
|
|
133
|
-
var ERR_CLAMP = 200; //
|
|
133
|
+
var ERR_CLAMP = 200; // protocol-reply error-message clamp
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
136
|
* @primitive b.mail.server.pop3.create
|
|
@@ -263,7 +263,7 @@ function create(opts) {
|
|
|
263
263
|
try { rawSocket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
264
264
|
return;
|
|
265
265
|
}
|
|
266
|
-
var connectionId = "pop3conn-" + bCrypto.generateToken(8); //
|
|
266
|
+
var connectionId = "pop3conn-" + bCrypto.generateToken(8); // connection-id length
|
|
267
267
|
var socket = rawSocket;
|
|
268
268
|
connections.add(socket);
|
|
269
269
|
// Single close handler covers BOTH operator-driven `_close(socket)`
|
|
@@ -876,7 +876,7 @@ function create(opts) {
|
|
|
876
876
|
throw new MailServerPop3Error("mail-server-pop3/already-listening",
|
|
877
877
|
"listen: already listening");
|
|
878
878
|
}
|
|
879
|
-
var port = listenOpts.port === undefined ? 110 : listenOpts.port; //
|
|
879
|
+
var port = listenOpts.port === undefined ? 110 : listenOpts.port; // RFC 1939 POP3 port (IANA)
|
|
880
880
|
var address = listenOpts.address || "0.0.0.0";
|
|
881
881
|
tcpServer = net.createServer(function (socket) { _handleConnection(socket); });
|
|
882
882
|
return new Promise(function (resolve, reject) {
|
|
@@ -98,7 +98,7 @@ var DEFAULTS = Object.freeze({
|
|
|
98
98
|
maxConcurrentConnectionsPerIp: 10,
|
|
99
99
|
connectionsPerIpPerMinute: 60, // allow:raw-time-literal — connection count, not a time value
|
|
100
100
|
authFailuresPerIpPer15Min: 10,
|
|
101
|
-
minBytesPerSecond: 100, //
|
|
101
|
+
minBytesPerSecond: 100, // slow-loris byte-rate floor
|
|
102
102
|
// RCPT-TO recipient-failure cap defends against the 550-vs-250
|
|
103
103
|
// enumeration shape (RFC 5321 §3.5 — RCPT-TO surfaces the
|
|
104
104
|
// mailbox-exists oracle; an attacker that hammers RCPT TO can
|
|
@@ -106,7 +106,7 @@ var DEFAULTS = Object.freeze({
|
|
|
106
106
|
// Per-IP, per-minute. Tuned higher than auth-failure since
|
|
107
107
|
// legitimate senders can RCPT-TO multiple recipients per message;
|
|
108
108
|
// operator overrides via `rcptFailuresPerIpPerMinute`.
|
|
109
|
-
rcptFailuresPerIpPerMinute: 50, //
|
|
109
|
+
rcptFailuresPerIpPerMinute: 50, // RCPT enumeration bound
|
|
110
110
|
disabled: false,
|
|
111
111
|
});
|
|
112
112
|
|
|
@@ -123,31 +123,31 @@ var MailServerSubmissionError = defineClass("MailServerSubmissionError", { alway
|
|
|
123
123
|
|
|
124
124
|
var DEFAULT_MAX_LINE_BYTES = C.BYTES.kib(1);
|
|
125
125
|
var DEFAULT_MAX_MESSAGE_BYTES = C.BYTES.mib(50);
|
|
126
|
-
var DEFAULT_MAX_RCPTS_PER_MESSAGE = 100; //
|
|
126
|
+
var DEFAULT_MAX_RCPTS_PER_MESSAGE = 100; // RFC 5321 §4.5.3.1.8 recipient cap
|
|
127
127
|
var DEFAULT_IDLE_TIMEOUT_MS = C.TIME.minutes(5);
|
|
128
128
|
var DEFAULT_GREETING = "blamejs Submission";
|
|
129
129
|
var DEFAULT_AUTH_MECHANISMS = Object.freeze(["PLAIN", "LOGIN"]);
|
|
130
130
|
|
|
131
131
|
var REPLY_220_READY = "220";
|
|
132
132
|
var REPLY_221_BYE = "221";
|
|
133
|
-
var REPLY_235_AUTH_OK = "235"; //
|
|
133
|
+
var REPLY_235_AUTH_OK = "235"; // SMTP AUTH success code
|
|
134
134
|
var REPLY_250_OK = "250";
|
|
135
|
-
var REPLY_334_AUTH_CHALLENGE = "334"; //
|
|
135
|
+
var REPLY_334_AUTH_CHALLENGE = "334"; // SMTP AUTH challenge code
|
|
136
136
|
var REPLY_354_START_INPUT = "354";
|
|
137
|
-
var REPLY_421_SERVICE_NOT_AVAIL = "421"; //
|
|
138
|
-
var REPLY_451_LOCAL_ERROR = "451"; //
|
|
139
|
-
var REPLY_452_INSUFFICIENT_STG = "452"; //
|
|
140
|
-
var REPLY_500_SYNTAX = "500"; //
|
|
141
|
-
var REPLY_501_BAD_ARGS = "501"; //
|
|
142
|
-
var REPLY_502_NOT_IMPLEMENTED = "502"; //
|
|
143
|
-
var REPLY_503_BAD_SEQUENCE = "503"; //
|
|
144
|
-
var REPLY_530_AUTH_REQUIRED = "530"; //
|
|
145
|
-
var REPLY_535_AUTH_FAILED = "535"; //
|
|
146
|
-
var REPLY_538_AUTH_NEEDS_TLS = "538"; //
|
|
147
|
-
var REPLY_550_MAILBOX_UNAVAIL = "550"; //
|
|
148
|
-
var REPLY_552_SIZE_EXCEEDED = "552"; //
|
|
149
|
-
var REPLY_553_SENDER_REJECTED = "553"; //
|
|
150
|
-
var REPLY_554_TRANSACTION_FAILED = "554"; //
|
|
137
|
+
var REPLY_421_SERVICE_NOT_AVAIL = "421"; // SMTP transient code
|
|
138
|
+
var REPLY_451_LOCAL_ERROR = "451"; // SMTP transient code
|
|
139
|
+
var REPLY_452_INSUFFICIENT_STG = "452"; // SMTP transient code
|
|
140
|
+
var REPLY_500_SYNTAX = "500"; // SMTP permanent code
|
|
141
|
+
var REPLY_501_BAD_ARGS = "501"; // SMTP permanent code
|
|
142
|
+
var REPLY_502_NOT_IMPLEMENTED = "502"; // SMTP permanent code
|
|
143
|
+
var REPLY_503_BAD_SEQUENCE = "503"; // SMTP permanent code
|
|
144
|
+
var REPLY_530_AUTH_REQUIRED = "530"; // SMTP permanent code
|
|
145
|
+
var REPLY_535_AUTH_FAILED = "535"; // RFC 4954 §6 AUTH refusal
|
|
146
|
+
var REPLY_538_AUTH_NEEDS_TLS = "538"; // RFC 4954 §4 AUTH-needs-TLS
|
|
147
|
+
var REPLY_550_MAILBOX_UNAVAIL = "550"; // SMTP permanent code (recipient-policy refusal shape)
|
|
148
|
+
var REPLY_552_SIZE_EXCEEDED = "552"; // SMTP permanent code
|
|
149
|
+
var REPLY_553_SENDER_REJECTED = "553"; // identity-binding mismatch
|
|
150
|
+
var REPLY_554_TRANSACTION_FAILED = "554"; // SMTP permanent code
|
|
151
151
|
|
|
152
152
|
var RE_MAIL_FROM = /^MAIL\s+FROM:\s*<([^>]*)>(?:\s+(.*))?$/i;
|
|
153
153
|
var RE_RCPT_TO = /^RCPT\s+TO:\s*<([^>]+)>(?:\s+.*)?$/i;
|
|
@@ -159,7 +159,7 @@ var RE_AUTH = /^AUTH\s+([A-Za-z0-9_-]{1,32})(?:\s+(.*))?$/i;
|
|
|
159
159
|
// SIMD-accelerated needle scan over the haystack without an
|
|
160
160
|
// interpreter-level char-by-char walk, and the 4-byte literal
|
|
161
161
|
// `_CRLF_CRLF` is a module-level singleton so the JIT folds it.
|
|
162
|
-
var _CRLF_CRLF = Buffer.from([0x0d, 0x0a, 0x0d, 0x0a]); //
|
|
162
|
+
var _CRLF_CRLF = Buffer.from([0x0d, 0x0a, 0x0d, 0x0a]); // RFC 5322 §2.1 header/body separator
|
|
163
163
|
function _findHeaderEnd(buf) {
|
|
164
164
|
return buf.indexOf(_CRLF_CRLF);
|
|
165
165
|
}
|
|
@@ -408,7 +408,7 @@ function create(opts) {
|
|
|
408
408
|
}
|
|
409
409
|
rawSocket.once("close", function () { rateLimit.releaseConnection(remoteAddress); });
|
|
410
410
|
|
|
411
|
-
var connectionId = "submitconn-" + bCrypto.generateToken(8); //
|
|
411
|
+
var connectionId = "submitconn-" + bCrypto.generateToken(8); // connection-id length
|
|
412
412
|
var socket = implicitTls
|
|
413
413
|
? new nodeTls.TLSSocket(rawSocket, { isServer: true, secureContext: opts.tlsContext })
|
|
414
414
|
: rawSocket;
|
|
@@ -623,7 +623,7 @@ function create(opts) {
|
|
|
623
623
|
err.code === "guard-smtp-command/bare-cr" ||
|
|
624
624
|
err.code === "guard-smtp-command/nul-byte") {
|
|
625
625
|
_emit("mail.server.submission.smtp_smuggling_detected",
|
|
626
|
-
{ connectionId: state.id, code: err.code, line: line.slice(0, 200) }, //
|
|
626
|
+
{ connectionId: state.id, code: err.code, line: line.slice(0, 200) }, // audit-log line truncation
|
|
627
627
|
"denied");
|
|
628
628
|
}
|
|
629
629
|
_writeReply(socket, REPLY_500_SYNTAX, "5.5.2 Syntax error (" + (err.code || "bad-line") + ")");
|
|
@@ -1319,7 +1319,7 @@ function create(opts) {
|
|
|
1319
1319
|
// Port 0 (ephemeral, test mode) must NOT fall back to the protocol
|
|
1320
1320
|
// default — the `|| <default>` short-circuit was a footgun on the
|
|
1321
1321
|
// test path.
|
|
1322
|
-
var defaultPort = implicitTls ? 465 : 587; //
|
|
1322
|
+
var defaultPort = implicitTls ? 465 : 587; // RFC 8314 implicit-TLS / RFC 6409 submission ports
|
|
1323
1323
|
var port = listenOpts.port === undefined ? defaultPort : listenOpts.port;
|
|
1324
1324
|
var address = listenOpts.address || "0.0.0.0";
|
|
1325
1325
|
tcpServer = net.createServer(function (socket) { _handleConnection(socket); });
|
package/lib/mail-sieve.js
CHANGED
|
@@ -64,8 +64,8 @@ var validateOpts = require("./validate-opts");
|
|
|
64
64
|
|
|
65
65
|
var MailSieveError = defineClass("MailSieveError", { alwaysPermanent: true });
|
|
66
66
|
|
|
67
|
-
var DEFAULT_GAS_UNITS = 10000; //
|
|
68
|
-
var MAX_GAS_UNITS = 1_000_000; //
|
|
67
|
+
var DEFAULT_GAS_UNITS = 10000; // operation cap
|
|
68
|
+
var MAX_GAS_UNITS = 1_000_000; // operator opt-up cap
|
|
69
69
|
|
|
70
70
|
// ---- env helpers ---------------------------------------------------------
|
|
71
71
|
|
package/lib/mail-spam-score.js
CHANGED
|
@@ -77,15 +77,15 @@ var MailSpamScoreError = defineClass("MailSpamScoreError", { alwaysPermanent: tr
|
|
|
77
77
|
|
|
78
78
|
var DEFAULT_PROFILE = "strict";
|
|
79
79
|
|
|
80
|
-
//
|
|
80
|
+
// reason-tag length cap defends outbound
|
|
81
81
|
// header / audit-store from hostile expansion via compromised scorer.
|
|
82
82
|
var MAX_REASON_BYTES = 256;
|
|
83
83
|
|
|
84
|
-
//
|
|
84
|
+
// reason-list count cap, defends audit volume.
|
|
85
85
|
var MAX_REASONS = 32;
|
|
86
86
|
|
|
87
87
|
var PROFILES = Object.freeze({
|
|
88
|
-
strict: { threshold: 5.0, maxReasons: MAX_REASONS, maxReasonBytes: MAX_REASON_BYTES }, //
|
|
88
|
+
strict: { threshold: 5.0, maxReasons: MAX_REASONS, maxReasonBytes: MAX_REASON_BYTES }, // matches SpamAssassin default required_score
|
|
89
89
|
balanced: { threshold: 7.5, maxReasons: MAX_REASONS, maxReasonBytes: MAX_REASON_BYTES },
|
|
90
90
|
permissive: { threshold: 10.0, maxReasons: MAX_REASONS, maxReasonBytes: MAX_REASON_BYTES },
|
|
91
91
|
});
|
|
@@ -256,10 +256,10 @@ function _sanitizeReasons(reasons, caps) {
|
|
|
256
256
|
// header.
|
|
257
257
|
for (var c = 0; c < r.length; c += 1) {
|
|
258
258
|
var cc = r.charCodeAt(c);
|
|
259
|
-
if (cc < 0x20 || cc === 0x7f) { //
|
|
259
|
+
if (cc < 0x20 || cc === 0x7f) { // RFC 5234 CTL refusal range
|
|
260
260
|
throw new MailSpamScoreError("mail-spam-score/control-byte",
|
|
261
261
|
"mail.spamScore.score: reasons[" + i + "] contains control byte 0x" +
|
|
262
|
-
cc.toString(16)); //
|
|
262
|
+
cc.toString(16)); // hex radix
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
out.push(r);
|
package/lib/mail-srs.js
CHANGED
|
@@ -59,8 +59,8 @@ function _base32Encode(buf) {
|
|
|
59
59
|
var bits = 0;
|
|
60
60
|
var value = 0;
|
|
61
61
|
for (var i = 0; i < buf.length; i += 1) {
|
|
62
|
-
value = (value << 8) | buf[i]; //
|
|
63
|
-
bits += 8; //
|
|
62
|
+
value = (value << 8) | buf[i]; // byte-aligned shift
|
|
63
|
+
bits += 8; // bits-per-byte constant
|
|
64
64
|
while (bits >= 5) {
|
|
65
65
|
out += BASE32.charAt((value >>> (bits - 5)) & 31);
|
|
66
66
|
bits -= 5;
|
|
@@ -72,13 +72,13 @@ function _base32Encode(buf) {
|
|
|
72
72
|
|
|
73
73
|
function _hashTag(secret, hashInput) {
|
|
74
74
|
var mac = nodeCrypto.createHmac("sha256", secret).update(hashInput.toLowerCase(), "utf8").digest();
|
|
75
|
-
return _base32Encode(mac.subarray(0, 4)).slice(0, 4); //
|
|
75
|
+
return _base32Encode(mac.subarray(0, 4)).slice(0, 4); // SRS spec 4-char short-tag
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function _dayStamp(nowMs) {
|
|
79
79
|
// Days since epoch, mod 1024. Two-char base32 = 1024 possible values.
|
|
80
|
-
var days = Math.floor(nowMs / 86400000) % 1024; //
|
|
81
|
-
return BASE32.charAt(days >>> 5) + BASE32.charAt(days & 31); //
|
|
80
|
+
var days = Math.floor(nowMs / 86400000) % 1024; // ms-per-day + mod-1024 SRS rotation
|
|
81
|
+
return BASE32.charAt(days >>> 5) + BASE32.charAt(days & 31); // 5-bit base32 split
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function _dayDiff(stamp, nowMs) {
|
|
@@ -86,11 +86,11 @@ function _dayDiff(stamp, nowMs) {
|
|
|
86
86
|
var hi = BASE32.indexOf(stamp.charAt(0));
|
|
87
87
|
var lo = BASE32.indexOf(stamp.charAt(1));
|
|
88
88
|
if (hi < 0 || lo < 0) return Infinity;
|
|
89
|
-
var stampVal = (hi << 5) | lo; //
|
|
90
|
-
var nowVal = Math.floor(nowMs / 86400000) % 1024; //
|
|
89
|
+
var stampVal = (hi << 5) | lo; // 5-bit base32 split
|
|
90
|
+
var nowVal = Math.floor(nowMs / 86400000) % 1024; // ms-per-day + mod-1024 rotation
|
|
91
91
|
// Modular distance — assume positive (rewrites in the future are
|
|
92
92
|
// refused via _dayDiff > 0 callers).
|
|
93
|
-
var diff = (nowVal - stampVal + 1024) % 1024; //
|
|
93
|
+
var diff = (nowVal - stampVal + 1024) % 1024; // mod-1024 rotation
|
|
94
94
|
return diff;
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -131,13 +131,13 @@ function create(opts) {
|
|
|
131
131
|
opts.secret, "srs.create.secret", SrsError, "srs/bad-secret");
|
|
132
132
|
validateOpts.requireNonEmptyString(
|
|
133
133
|
opts.forwarderDomain, "srs.create.forwarderDomain", SrsError, "srs/bad-forwarder");
|
|
134
|
-
if (opts.secret.length < 16) { //
|
|
134
|
+
if (opts.secret.length < 16) { // minimum HMAC secret length
|
|
135
135
|
throw new SrsError("srs/bad-secret",
|
|
136
136
|
"srs.create: secret must be >= 16 chars (operator-supplied entropy floor)");
|
|
137
137
|
}
|
|
138
|
-
var expiryDays = opts.expiryDays !== undefined ? opts.expiryDays : 30; //
|
|
138
|
+
var expiryDays = opts.expiryDays !== undefined ? opts.expiryDays : 30; // default expiry window in days
|
|
139
139
|
if (typeof expiryDays !== "number" || !Number.isInteger(expiryDays) ||
|
|
140
|
-
expiryDays < 1 || expiryDays > 1024) { //
|
|
140
|
+
expiryDays < 1 || expiryDays > 1024) { // SRS rotation cycle cap
|
|
141
141
|
throw new SrsError("srs/bad-expiry",
|
|
142
142
|
"srs.create: expiryDays must be an integer 1..1024 (SRS rotation cycle)");
|
|
143
143
|
}
|
|
@@ -154,7 +154,7 @@ function create(opts) {
|
|
|
154
154
|
}
|
|
155
155
|
var localPart = originalAddress.slice(0, at);
|
|
156
156
|
var domain = originalAddress.slice(at + 1);
|
|
157
|
-
if (localPart.length > 64 || domain.length > 253) { //
|
|
157
|
+
if (localPart.length > 64 || domain.length > 253) { // RFC 5321 local-part / domain caps
|
|
158
158
|
throw new SrsError("srs/bad-address",
|
|
159
159
|
"srs.rewrite: localPart / domain exceeds RFC 5321 length cap");
|
|
160
160
|
}
|
package/lib/mail-store-fts.js
CHANGED
|
@@ -77,7 +77,7 @@ var MAX_TOKEN_LEN = 64;
|
|
|
77
77
|
// millions of tokens; FTS5 row insert + index update must stay
|
|
78
78
|
// bounded. The cap is applied AFTER stopword + length filter so the
|
|
79
79
|
// surviving tokens are the highest-signal subset.
|
|
80
|
-
var MAX_TOKENS_PER_FIELD = 8192; //
|
|
80
|
+
var MAX_TOKENS_PER_FIELD = 8192; // token-count cap, not bytes
|
|
81
81
|
|
|
82
82
|
// Per-field FTS column names. Kept symmetric with the messages table
|
|
83
83
|
// columns so callers can reason about which FTS column corresponds
|
|
@@ -187,7 +187,7 @@ function hashToken(table, field, token) {
|
|
|
187
187
|
var ns = "bj-" + table + "-" + field + ":fts:";
|
|
188
188
|
var salt = vault.getDerivedHashSalt();
|
|
189
189
|
var saltHex = (salt && typeof salt.toString === "function") ? salt.toString("hex") : "";
|
|
190
|
-
return bCrypto.sha3Hash(saltHex + ns + token).slice(0, 16); //
|
|
190
|
+
return bCrypto.sha3Hash(saltHex + ns + token).slice(0, 16); // 16-char hex prefix length, not bytes
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
// Hash a token array → space-separated string suitable for FTS5
|