@blamejs/blamejs-shop 0.4.56 → 0.4.58
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/affiliates.js +35 -4
- package/lib/api-keys.js +17 -2
- package/lib/asset-manifest.json +1 -1
- package/lib/backorder.js +21 -4
- package/lib/click-and-collect.js +11 -2
- package/lib/credit-limits.js +132 -84
- package/lib/vendor/MANIFEST.json +426 -366
- package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +1381 -4
- package/lib/vendor/blamejs/eslint.config.mjs +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
- package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
- package/lib/vendor/blamejs/lib/acme.js +6 -5
- package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
- package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
- package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
- package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
- package/lib/vendor/blamejs/lib/ai-input.js +2 -2
- package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
- package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
- package/lib/vendor/blamejs/lib/api-key.js +37 -28
- package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
- package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
- package/lib/vendor/blamejs/lib/archive-read.js +5 -17
- package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
- package/lib/vendor/blamejs/lib/archive.js +2 -10
- package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
- package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
- package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
- package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
- package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
- package/lib/vendor/blamejs/lib/audit.js +84 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
- package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
- package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
- package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
- package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
- package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
- package/lib/vendor/blamejs/lib/auth/password.js +7 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
- package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
- package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
- package/lib/vendor/blamejs/lib/backup/index.js +14 -47
- package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
- package/lib/vendor/blamejs/lib/cache.js +7 -18
- package/lib/vendor/blamejs/lib/cbor.js +2 -1
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
- package/lib/vendor/blamejs/lib/cert.js +3 -10
- package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/client-hints.js +7 -9
- package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
- package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
- package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
- package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
- package/lib/vendor/blamejs/lib/compliance.js +2 -9
- package/lib/vendor/blamejs/lib/config-drift.js +2 -12
- package/lib/vendor/blamejs/lib/content-digest.js +10 -8
- package/lib/vendor/blamejs/lib/cookies.js +5 -11
- package/lib/vendor/blamejs/lib/cose.js +19 -11
- package/lib/vendor/blamejs/lib/cra-report.js +1 -11
- package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
- package/lib/vendor/blamejs/lib/crypto.js +120 -3
- package/lib/vendor/blamejs/lib/csp.js +235 -3
- package/lib/vendor/blamejs/lib/daemon.js +42 -41
- package/lib/vendor/blamejs/lib/data-act.js +19 -9
- package/lib/vendor/blamejs/lib/db-query.js +6 -40
- package/lib/vendor/blamejs/lib/db.js +34 -12
- package/lib/vendor/blamejs/lib/dbsc.js +5 -6
- package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
- package/lib/vendor/blamejs/lib/deprecate.js +4 -5
- package/lib/vendor/blamejs/lib/did.js +6 -2
- package/lib/vendor/blamejs/lib/dsr.js +8 -12
- package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
- package/lib/vendor/blamejs/lib/external-db.js +14 -26
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
- package/lib/vendor/blamejs/lib/fdx.js +22 -18
- package/lib/vendor/blamejs/lib/file-upload.js +80 -66
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
- package/lib/vendor/blamejs/lib/framework-error.js +12 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
- package/lib/vendor/blamejs/lib/fsm.js +7 -12
- package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
- package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
- package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
- package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
- package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
- package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
- package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
- package/lib/vendor/blamejs/lib/guard-email.js +46 -53
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
- package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
- package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
- package/lib/vendor/blamejs/lib/guard-html.js +65 -117
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
- package/lib/vendor/blamejs/lib/guard-image.js +280 -77
- package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
- package/lib/vendor/blamejs/lib/guard-json.js +87 -103
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
- package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
- package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
- package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
- package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
- package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
- package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
- package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
- package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
- package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
- package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
- package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
- package/lib/vendor/blamejs/lib/guard-template.js +23 -80
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
- package/lib/vendor/blamejs/lib/guard-text.js +592 -0
- package/lib/vendor/blamejs/lib/guard-time.js +27 -95
- package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
- package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
- package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
- package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
- package/lib/vendor/blamejs/lib/http-client.js +8 -21
- package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
- package/lib/vendor/blamejs/lib/i18n.js +83 -26
- package/lib/vendor/blamejs/lib/inbox.js +8 -8
- package/lib/vendor/blamejs/lib/incident-report.js +3 -21
- package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
- package/lib/vendor/blamejs/lib/jobs.js +3 -2
- package/lib/vendor/blamejs/lib/keychain.js +6 -18
- package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
- package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
- package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
- package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
- package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
- package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
- package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
- package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
- package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
- package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
- package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
- package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
- package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
- package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
- package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mail.js +6 -11
- package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/mdoc.js +11 -12
- package/lib/vendor/blamejs/lib/metrics.js +32 -30
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
- package/lib/vendor/blamejs/lib/migrations.js +4 -13
- package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
- package/lib/vendor/blamejs/lib/module-loader.js +44 -0
- package/lib/vendor/blamejs/lib/money.js +105 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
- package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
- package/lib/vendor/blamejs/lib/network-dane.js +8 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
- package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
- package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
- package/lib/vendor/blamejs/lib/network-tls.js +40 -42
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
- package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
- package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
- package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
- package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
- package/lib/vendor/blamejs/lib/observability.js +95 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
- package/lib/vendor/blamejs/lib/otel-export.js +7 -10
- package/lib/vendor/blamejs/lib/outbox.js +43 -37
- package/lib/vendor/blamejs/lib/pagination.js +11 -15
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
- package/lib/vendor/blamejs/lib/pick.js +63 -5
- package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
- package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
- package/lib/vendor/blamejs/lib/problem-details.js +2 -5
- package/lib/vendor/blamejs/lib/pubsub.js +4 -8
- package/lib/vendor/blamejs/lib/redact.js +2 -1
- package/lib/vendor/blamejs/lib/render.js +4 -2
- package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
- package/lib/vendor/blamejs/lib/restore.js +5 -22
- package/lib/vendor/blamejs/lib/retention.js +3 -5
- package/lib/vendor/blamejs/lib/safe-async.js +457 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
- package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
- package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
- package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
- package/lib/vendor/blamejs/lib/safe-json.js +7 -8
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
- package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
- package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
- package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
- package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
- package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
- package/lib/vendor/blamejs/lib/sandbox.js +3 -2
- package/lib/vendor/blamejs/lib/scheduler.js +5 -12
- package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
- package/lib/vendor/blamejs/lib/seeders.js +4 -11
- package/lib/vendor/blamejs/lib/self-update.js +92 -69
- package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
- package/lib/vendor/blamejs/lib/session.js +194 -6
- package/lib/vendor/blamejs/lib/sql.js +225 -78
- package/lib/vendor/blamejs/lib/sse.js +6 -10
- package/lib/vendor/blamejs/lib/static.js +136 -98
- package/lib/vendor/blamejs/lib/storage.js +4 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
- package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
- package/lib/vendor/blamejs/lib/tsa.js +11 -15
- package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
- package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
- package/lib/vendor/blamejs/lib/vc.js +2 -7
- package/lib/vendor/blamejs/lib/vex.js +35 -13
- package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
- package/lib/vendor/blamejs/lib/webhook.js +43 -18
- package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
- package/lib/vendor/blamejs/lib/websocket.js +7 -3
- package/lib/vendor/blamejs/lib/worm.js +2 -3
- package/lib/vendor/blamejs/lib/ws-client.js +8 -10
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
- package/lib/vendor/blamejs/test/00-primitives.js +136 -7
- package/lib/vendor/blamejs/test/10-state.js +9 -3
- package/lib/vendor/blamejs/test/30-chain.js +40 -0
- package/lib/vendor/blamejs/test/helpers/check.js +18 -0
- package/lib/vendor/blamejs/test/helpers/db.js +4 -0
- package/lib/vendor/blamejs/test/helpers/index.js +1 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
- package/package.json +1 -1
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
*/
|
|
104
104
|
|
|
105
105
|
var net = require("node:net");
|
|
106
|
-
var
|
|
106
|
+
var safeBuffer = require("./safe-buffer");
|
|
107
107
|
var C = require("./constants");
|
|
108
108
|
var bCrypto = require("./crypto");
|
|
109
109
|
var numericBounds = require("./numeric-bounds");
|
|
@@ -111,11 +111,12 @@ var validateOpts = require("./validate-opts");
|
|
|
111
111
|
var guardPop3Command = require("./guard-pop3-command");
|
|
112
112
|
var mailServerRateLimit = require("./mail-server-rate-limit");
|
|
113
113
|
var mailServerTls = require("./mail-server-tls");
|
|
114
|
+
var mailServerNet = require("./mail-server-net");
|
|
114
115
|
var safeSmtp = require("./safe-smtp");
|
|
115
116
|
var safeAsync = require("./safe-async");
|
|
116
117
|
var { defineClass } = require("./framework-error");
|
|
117
118
|
|
|
118
|
-
var
|
|
119
|
+
var auditEmit = require("./audit-emit");
|
|
119
120
|
|
|
120
121
|
var MailServerPop3Error = defineClass("MailServerPop3Error", { alwaysPermanent: true });
|
|
121
122
|
|
|
@@ -229,40 +230,18 @@ function create(opts) {
|
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
|
|
232
|
-
var rateLimit;
|
|
233
|
-
if (opts.rateLimit === false) {
|
|
234
|
-
rateLimit = mailServerRateLimit.create({ disabled: true });
|
|
235
|
-
} else if (opts.rateLimit && typeof opts.rateLimit.admitConnection === "function") {
|
|
236
|
-
rateLimit = opts.rateLimit;
|
|
237
|
-
} else {
|
|
238
|
-
rateLimit = mailServerRateLimit.create(opts.rateLimit || {});
|
|
239
|
-
}
|
|
233
|
+
var rateLimit = mailServerRateLimit.resolve(opts.rateLimit);
|
|
240
234
|
|
|
241
|
-
var tcpServer = null;
|
|
242
|
-
var listening = false;
|
|
243
235
|
var connections = new Set();
|
|
244
236
|
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
audit().safeEmit({
|
|
248
|
-
action: action,
|
|
249
|
-
outcome: outcome || "success",
|
|
250
|
-
metadata: metadata || {},
|
|
251
|
-
});
|
|
252
|
-
} catch (_e) { /* drop-silent */ }
|
|
253
|
-
}
|
|
237
|
+
var _emit = auditEmit.emit;
|
|
254
238
|
|
|
255
239
|
function _handleConnection(rawSocket) {
|
|
256
|
-
var remoteAddress = rawSocket
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
try { rawSocket.write("-ERR Too many connections from your IP\r\n"); }
|
|
262
|
-
catch (_e) { /* socket may be down */ }
|
|
263
|
-
try { rawSocket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
240
|
+
var remoteAddress = mailServerNet.admitConnection(rawSocket, rateLimit, _emit, {
|
|
241
|
+
refusedEvent: "mail.server.pop3.rate_limit_refused",
|
|
242
|
+
refusalLine: "-ERR Too many connections from your IP\r\n",
|
|
243
|
+
});
|
|
244
|
+
if (remoteAddress === null) return;
|
|
266
245
|
var connectionId = "pop3conn-" + bCrypto.generateToken(8); // connection-id length
|
|
267
246
|
var socket = rawSocket;
|
|
268
247
|
connections.add(socket);
|
|
@@ -312,7 +291,7 @@ function create(opts) {
|
|
|
312
291
|
while (true) {
|
|
313
292
|
var crlf = state.lineBuffer.indexOf("\r\n");
|
|
314
293
|
if (crlf === -1) {
|
|
315
|
-
if (state.lineBuffer
|
|
294
|
+
if (safeBuffer.byteLengthOf(state.lineBuffer) > maxLineBytes) {
|
|
316
295
|
_writeErr(socket, "Line too long (cap " + maxLineBytes + ")");
|
|
317
296
|
_close(socket);
|
|
318
297
|
}
|
|
@@ -398,22 +377,18 @@ function create(opts) {
|
|
|
398
377
|
// Drain pre-handshake buffer (RFC 2595 §4 + CVE-2021-33515 class
|
|
399
378
|
// STLS-injection defense — any pipelined commands the client
|
|
400
379
|
// queued before the upgrade are discarded; post-TLS reads fresh).
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
|
|
404
|
-
//
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
plainSocket: socket,
|
|
380
|
+
// POP3 has no authPending shape (SASL state is local to
|
|
381
|
+
// _handleAuth), but tentativeUser is reset so a USER pipelined
|
|
382
|
+
// pre-handshake cannot bind a post-handshake PASS. The shared
|
|
383
|
+
// upgradeLineProtocol helper owns the lineBuffer drain + listener-
|
|
384
|
+
// strip + idle re-arm + read-pump.
|
|
385
|
+
mailServerTls.upgradeLineProtocol({
|
|
386
|
+
state: state,
|
|
387
|
+
socket: socket,
|
|
410
388
|
secureContext: opts.tlsContext,
|
|
411
389
|
idleTimeoutMs: idleTimeoutMs,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
state.lineBuffer = Buffer.concat([state.lineBuffer, chunk]);
|
|
415
|
-
_drainBuffer(state, tlsSocket);
|
|
416
|
-
},
|
|
390
|
+
clearFields: ["tentativeUser"],
|
|
391
|
+
drain: _drainBuffer,
|
|
417
392
|
onError: function (err) {
|
|
418
393
|
_emit("mail.server.pop3.tls_handshake_failed",
|
|
419
394
|
{ connectionId: state.id, error: (err && err.message) || String(err) }, "failure");
|
|
@@ -870,43 +845,15 @@ function create(opts) {
|
|
|
870
845
|
}
|
|
871
846
|
|
|
872
847
|
// ---- Lifecycle ----------------------------------------------------------
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return new Promise(function (resolve, reject) {
|
|
883
|
-
tcpServer.once("error", reject);
|
|
884
|
-
tcpServer.listen(port, address, function () {
|
|
885
|
-
listening = true;
|
|
886
|
-
tcpServer.removeListener("error", reject);
|
|
887
|
-
_emit("mail.server.pop3.listening", { port: port, address: address });
|
|
888
|
-
resolve({ port: tcpServer.address().port, address: address });
|
|
889
|
-
});
|
|
890
|
-
});
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
async function close() {
|
|
894
|
-
if (!listening) return;
|
|
895
|
-
listening = false;
|
|
896
|
-
for (var s of connections) { try { s.destroy(); } catch (_e) { /* idempotent */ } }
|
|
897
|
-
connections.clear();
|
|
898
|
-
return new Promise(function (resolve) {
|
|
899
|
-
tcpServer.close(function () {
|
|
900
|
-
_emit("mail.server.pop3.closed", {});
|
|
901
|
-
resolve();
|
|
902
|
-
});
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
return {
|
|
907
|
-
listen: listen,
|
|
908
|
-
close: close,
|
|
909
|
-
};
|
|
848
|
+
return mailServerNet.createStoreServer(net, {
|
|
849
|
+
defaultPort: 110, // RFC 1939 POP3 port (IANA)
|
|
850
|
+
handleConnection: _handleConnection,
|
|
851
|
+
errorClass: MailServerPop3Error,
|
|
852
|
+
errorCodePrefix: "mail-server-pop3/",
|
|
853
|
+
emit: _emit,
|
|
854
|
+
connections: connections,
|
|
855
|
+
eventBase: "mail.server.pop3",
|
|
856
|
+
});
|
|
910
857
|
}
|
|
911
858
|
|
|
912
859
|
module.exports = {
|
|
@@ -88,6 +88,7 @@ var C = require("./constants");
|
|
|
88
88
|
var lazyRequire = require("./lazy-require");
|
|
89
89
|
var numericBounds = require("./numeric-bounds");
|
|
90
90
|
var validateOpts = require("./validate-opts");
|
|
91
|
+
var boundedMap = require("./bounded-map");
|
|
91
92
|
var { defineClass } = require("./framework-error");
|
|
92
93
|
|
|
93
94
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
@@ -206,8 +207,7 @@ function create(opts) {
|
|
|
206
207
|
{ reason: "concurrent-per-ip", ip: ip, cap: cfg.maxConcurrentConnectionsPerIp });
|
|
207
208
|
return { ok: false, reason: "concurrent-per-ip" };
|
|
208
209
|
}
|
|
209
|
-
var times =
|
|
210
|
-
if (!times) { times = []; connectionTimes.set(ip, times); }
|
|
210
|
+
var times = boundedMap.getOrInsert(connectionTimes, ip, function () { return []; });
|
|
211
211
|
_pruneWindow(times, CONNECTION_RATE_WINDOW_MS);
|
|
212
212
|
if (times.length >= cfg.connectionsPerIpPerMinute) {
|
|
213
213
|
_audit("mail.server.rate_limit.refused", "denied",
|
|
@@ -258,8 +258,7 @@ function create(opts) {
|
|
|
258
258
|
|
|
259
259
|
function noteAuthFailure(ip) {
|
|
260
260
|
if (cfg.disabled) return;
|
|
261
|
-
var times =
|
|
262
|
-
if (!times) { times = []; authFailureTimes.set(ip, times); }
|
|
261
|
+
var times = boundedMap.getOrInsert(authFailureTimes, ip, function () { return []; });
|
|
263
262
|
times.push(Date.now());
|
|
264
263
|
}
|
|
265
264
|
|
|
@@ -288,8 +287,7 @@ function create(opts) {
|
|
|
288
287
|
|
|
289
288
|
function noteRcptFailure(ip) {
|
|
290
289
|
if (cfg.disabled) return;
|
|
291
|
-
var times =
|
|
292
|
-
if (!times) { times = []; rcptFailureTimes.set(ip, times); }
|
|
290
|
+
var times = boundedMap.getOrInsert(rcptFailureTimes, ip, function () { return []; });
|
|
293
291
|
times.push(Date.now());
|
|
294
292
|
}
|
|
295
293
|
|
|
@@ -308,8 +306,34 @@ function create(opts) {
|
|
|
308
306
|
};
|
|
309
307
|
}
|
|
310
308
|
|
|
309
|
+
/**
|
|
310
|
+
* @primitive b.mail.server.rateLimit.resolve
|
|
311
|
+
* @signature b.mail.server.rateLimit.resolve(spec)
|
|
312
|
+
* @since 0.15.13
|
|
313
|
+
* @status stable
|
|
314
|
+
* @related b.mail.server.rateLimit.create
|
|
315
|
+
*
|
|
316
|
+
* Resolve a rate-limit `spec` into a limiter. `false` disables limiting
|
|
317
|
+
* (a disabled limiter that always admits), an already-built limiter — one
|
|
318
|
+
* exposing `admitConnection` — passes through unchanged, and anything else
|
|
319
|
+
* is treated as `create()` options. Every mail server (IMAP / POP3 / SMTP
|
|
320
|
+
* MX / Submission / ManageSieve) composes this at the top of its `create()`
|
|
321
|
+
* so the spec contract is identical across protocols.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* var b = require("blamejs");
|
|
325
|
+
* var rl = b.mail.server.rateLimit.resolve(false); // disabled
|
|
326
|
+
* // → a limiter whose admitConnection always admits
|
|
327
|
+
*/
|
|
328
|
+
function resolve(spec) {
|
|
329
|
+
if (spec === false) return create({ disabled: true });
|
|
330
|
+
if (spec && typeof spec.admitConnection === "function") return spec;
|
|
331
|
+
return create(spec || {});
|
|
332
|
+
}
|
|
333
|
+
|
|
311
334
|
module.exports = {
|
|
312
335
|
create: create,
|
|
336
|
+
resolve: resolve,
|
|
313
337
|
MailServerRateLimitError: MailServerRateLimitError,
|
|
314
338
|
DEFAULTS: DEFAULTS,
|
|
315
339
|
};
|
|
@@ -103,7 +103,6 @@
|
|
|
103
103
|
|
|
104
104
|
var net = require("node:net");
|
|
105
105
|
var nodeTls = require("node:tls");
|
|
106
|
-
var lazyRequire = require("./lazy-require");
|
|
107
106
|
var C = require("./constants");
|
|
108
107
|
var bCrypto = require("./crypto");
|
|
109
108
|
var numericBounds = require("./numeric-bounds");
|
|
@@ -115,9 +114,10 @@ var guardSmtpCommand = require("./guard-smtp-command");
|
|
|
115
114
|
var guardDomain = require("./guard-domain");
|
|
116
115
|
var mailServerRateLimit = require("./mail-server-rate-limit");
|
|
117
116
|
var mailServerTls = require("./mail-server-tls");
|
|
117
|
+
var mailServerNet = require("./mail-server-net");
|
|
118
118
|
var { defineClass } = require("./framework-error");
|
|
119
119
|
|
|
120
|
-
var
|
|
120
|
+
var auditEmit = require("./audit-emit");
|
|
121
121
|
|
|
122
122
|
var MailServerSubmissionError = defineClass("MailServerSubmissionError", { alwaysPermanent: true });
|
|
123
123
|
|
|
@@ -341,14 +341,7 @@ function create(opts) {
|
|
|
341
341
|
// Default-on per-IP rate limit (see lib/mail-server-rate-limit.js).
|
|
342
342
|
// Operators pass `rateLimit: false` to disable, a rate-limit handle
|
|
343
343
|
// to share across listeners, or an opts object to override defaults.
|
|
344
|
-
var rateLimit;
|
|
345
|
-
if (opts.rateLimit === false) {
|
|
346
|
-
rateLimit = mailServerRateLimit.create({ disabled: true });
|
|
347
|
-
} else if (opts.rateLimit && typeof opts.rateLimit.admitConnection === "function") {
|
|
348
|
-
rateLimit = opts.rateLimit;
|
|
349
|
-
} else {
|
|
350
|
-
rateLimit = mailServerRateLimit.create(opts.rateLimit || {});
|
|
351
|
-
}
|
|
344
|
+
var rateLimit = mailServerRateLimit.resolve(opts.rateLimit);
|
|
352
345
|
|
|
353
346
|
// Default-on guardDomain hardening for HELO / MAIL FROM / RCPT TO.
|
|
354
347
|
// Same posture as mail-server-mx — IDN homograph / Punycode-spoof
|
|
@@ -367,45 +360,25 @@ function create(opts) {
|
|
|
367
360
|
});
|
|
368
361
|
}
|
|
369
362
|
function _validateDomainHardened(d, label) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
_emit
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
label: label,
|
|
377
|
-
}, "denied");
|
|
378
|
-
}
|
|
379
|
-
return verdict;
|
|
363
|
+
return mailServerNet.validateDomainHardened(d, label, {
|
|
364
|
+
guardDomainProfile: guardDomainProfile,
|
|
365
|
+
guardDomain: guardDomain,
|
|
366
|
+
emit: _emit,
|
|
367
|
+
refusedEvent: "mail.server.submission.domain_refused",
|
|
368
|
+
});
|
|
380
369
|
}
|
|
381
370
|
|
|
382
|
-
var tcpServer = null;
|
|
383
|
-
var listening = false;
|
|
384
371
|
var connections = new Set();
|
|
385
372
|
|
|
386
|
-
|
|
387
|
-
try {
|
|
388
|
-
audit().safeEmit({
|
|
389
|
-
action: action,
|
|
390
|
-
outcome: outcome || "success",
|
|
391
|
-
metadata: metadata || {},
|
|
392
|
-
});
|
|
393
|
-
} catch (_e) { /* drop-silent */ }
|
|
394
|
-
}
|
|
373
|
+
var _emit = auditEmit.emit;
|
|
395
374
|
|
|
396
375
|
function _handleConnection(rawSocket) {
|
|
397
|
-
|
|
398
|
-
var
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
rawSocket.write("421 4.7.0 Too many connections from your IP\r\n");
|
|
405
|
-
} catch (_e) { /* socket may already be torn down */ }
|
|
406
|
-
try { rawSocket.destroy(); } catch (_e2) { /* idempotent */ }
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
376
|
+
// 421 4.7.0 — transient; sender retries elsewhere.
|
|
377
|
+
var remoteAddress = mailServerNet.admitConnection(rawSocket, rateLimit, _emit, {
|
|
378
|
+
refusedEvent: "mail.server.submission.rate_limit_refused",
|
|
379
|
+
refusalLine: "421 4.7.0 Too many connections from your IP\r\n",
|
|
380
|
+
});
|
|
381
|
+
if (remoteAddress === null) return;
|
|
409
382
|
rawSocket.once("close", function () { rateLimit.releaseConnection(remoteAddress); });
|
|
410
383
|
|
|
411
384
|
var connectionId = "submitconn-" + bCrypto.generateToken(8); // connection-id length
|
|
@@ -570,7 +543,7 @@ function create(opts) {
|
|
|
570
543
|
}
|
|
571
544
|
|
|
572
545
|
lineBuffer = lineBuffer.length === 0 ? chunk : Buffer.concat([lineBuffer, chunk]);
|
|
573
|
-
if (lineBuffer
|
|
546
|
+
if (safeBuffer.byteLengthOf(lineBuffer) > maxLineBytes * 4) {
|
|
574
547
|
_writeReply(socket, REPLY_500_SYNTAX,
|
|
575
548
|
"5.5.6 Line too long (>" + maxLineBytes + " bytes)");
|
|
576
549
|
_closeConnection(socket);
|
|
@@ -1310,37 +1283,25 @@ function create(opts) {
|
|
|
1310
1283
|
}
|
|
1311
1284
|
}
|
|
1312
1285
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
tcpServer = net.createServer(function (socket) { _handleConnection(socket); });
|
|
1326
|
-
return new Promise(function (resolve, reject) {
|
|
1327
|
-
tcpServer.once("error", reject);
|
|
1328
|
-
tcpServer.listen(port, address, function () {
|
|
1329
|
-
listening = true;
|
|
1330
|
-
tcpServer.removeListener("error", reject);
|
|
1331
|
-
_emit("mail.server.submission.listening",
|
|
1332
|
-
{ port: port, address: address, implicitTls: implicitTls });
|
|
1333
|
-
resolve({ port: tcpServer.address().port, address: address });
|
|
1334
|
-
});
|
|
1335
|
-
});
|
|
1336
|
-
}
|
|
1286
|
+
// Port 0 (ephemeral, test mode) must NOT fall back to the protocol default —
|
|
1287
|
+
// the `|| <default>` short-circuit was a footgun on the test path;
|
|
1288
|
+
// createTcpListener honors an explicit 0 (only an OMITTED port defaults). The
|
|
1289
|
+
// listening event reports implicitTls so an operator can confirm the wire mode.
|
|
1290
|
+
var _tcpListener = mailServerNet.createTcpListener(net, {
|
|
1291
|
+
defaultPort: implicitTls ? 465 : 587, // RFC 8314 implicit-TLS / RFC 6409 submission ports
|
|
1292
|
+
handleConnection: _handleConnection,
|
|
1293
|
+
errorFactory: function (code, message) { return new MailServerSubmissionError("mail-server-submission/" + code, message); },
|
|
1294
|
+
emit: _emit,
|
|
1295
|
+
listeningEvent: "mail.server.submission.listening",
|
|
1296
|
+
listeningExtra: function () { return { implicitTls: implicitTls }; },
|
|
1297
|
+
});
|
|
1337
1298
|
|
|
1338
1299
|
async function close(closeOpts) {
|
|
1339
1300
|
closeOpts = closeOpts || {};
|
|
1340
|
-
if (!
|
|
1301
|
+
if (!_tcpListener.isListening()) return;
|
|
1341
1302
|
var timeoutMs = closeOpts.timeoutMs || C.TIME.seconds(30);
|
|
1342
|
-
|
|
1343
|
-
|
|
1303
|
+
_tcpListener.markClosed();
|
|
1304
|
+
_tcpListener.getServer().close();
|
|
1344
1305
|
connections.forEach(function (sock) {
|
|
1345
1306
|
try { _writeReply(sock, REPLY_421_SERVICE_NOT_AVAIL, "4.3.0 Server shutting down"); }
|
|
1346
1307
|
catch (_e) { /* socket already gone */ }
|
|
@@ -1359,10 +1320,10 @@ function create(opts) {
|
|
|
1359
1320
|
function connectionCount() { return connections.size; }
|
|
1360
1321
|
|
|
1361
1322
|
return {
|
|
1362
|
-
listen: listen,
|
|
1323
|
+
listen: _tcpListener.listen,
|
|
1363
1324
|
close: close,
|
|
1364
1325
|
connectionCount: connectionCount,
|
|
1365
|
-
_portForTest: function () { return
|
|
1326
|
+
_portForTest: function () { var s = _tcpListener.getServer(); return s ? s.address().port : null; },
|
|
1366
1327
|
};
|
|
1367
1328
|
}
|
|
1368
1329
|
|
|
@@ -438,8 +438,97 @@ function upgradeSocket(opts) {
|
|
|
438
438
|
return tlsSocket;
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
/**
|
|
442
|
+
* @primitive b.mail.server.tls.upgradeLineProtocol
|
|
443
|
+
* @signature b.mail.server.tls.upgradeLineProtocol(opts)
|
|
444
|
+
* @since 0.15.13
|
|
445
|
+
* @status stable
|
|
446
|
+
* @related b.mail.server.tls.upgradeSocket
|
|
447
|
+
*
|
|
448
|
+
* STARTTLS / STLS completion for the line-buffered store listeners
|
|
449
|
+
* (IMAP / POP3 / ManageSieve), layered over `upgradeSocket`. The
|
|
450
|
+
* caller has already validated protocol state and written its
|
|
451
|
+
* "begin TLS" response; this owns the steps that recur identically
|
|
452
|
+
* across the three:
|
|
453
|
+
*
|
|
454
|
+
* 1. Drop the pre-handshake `state.lineBuffer` (always) plus any
|
|
455
|
+
* protocol-specific half-parsed command / literal / auth fields
|
|
456
|
+
* (`clearFields`) so bytes the peer pipelined before the upgrade
|
|
457
|
+
* cannot survive into the post-TLS session (CVE-2021-33515 /
|
|
458
|
+
* CVE-2021-38371 STARTTLS-injection class). Centralizing the
|
|
459
|
+
* `lineBuffer` reset makes it impossible for a listener to forget.
|
|
460
|
+
* 2. Mark `state.tls = true` on the secure event, then run the
|
|
461
|
+
* caller's optional `onSecure` for protocol-specific work (e.g.
|
|
462
|
+
* ManageSieve re-emitting its capability banner per RFC 5804).
|
|
463
|
+
* 3. Feed every post-handshake chunk through the caller's `drain`
|
|
464
|
+
* via the standard `state.lineBuffer` append.
|
|
465
|
+
*
|
|
466
|
+
* The transfer listeners (MX / submission) ingest via a serialized
|
|
467
|
+
* feed pump, not the line buffer, so they call `upgradeSocket`
|
|
468
|
+
* directly.
|
|
469
|
+
*
|
|
470
|
+
* @opts
|
|
471
|
+
* state: object, // connection state ({ lineBuffer, tls, … })
|
|
472
|
+
* socket: net.Socket, // pre-upgrade plain socket
|
|
473
|
+
* secureContext: tls.SecureContext, // from b.mail.server.tls.context
|
|
474
|
+
* idleTimeoutMs: number, // re-armed post-handshake
|
|
475
|
+
* clearFields: Array<string>, // extra state fields to null pre-upgrade
|
|
476
|
+
* drain: function(state, tlsSocket), // the protocol line drainer
|
|
477
|
+
* onSecure: function(tlsSocket), // optional post-secure work
|
|
478
|
+
* onError: function(err), // handshake / runtime error
|
|
479
|
+
* onTimeout: function(tlsSocket), // optional idle-timeout handler
|
|
480
|
+
*
|
|
481
|
+
* @example
|
|
482
|
+
* b.mail.server.tls.upgradeLineProtocol({
|
|
483
|
+
* state: state, socket: socket, secureContext: opts.tlsContext,
|
|
484
|
+
* idleTimeoutMs: idleTimeoutMs, clearFields: ["pendingLiteral"],
|
|
485
|
+
* drain: _drainBuffer,
|
|
486
|
+
* onError: function (err) { _emit("imap.tls_failed", { err: err.message }); _close(socket, state); },
|
|
487
|
+
* });
|
|
488
|
+
*/
|
|
489
|
+
function upgradeLineProtocol(opts) {
|
|
490
|
+
if (!opts || typeof opts !== "object") {
|
|
491
|
+
throw new MailServerTlsError("mail-server-tls/bad-upgrade-line-opts",
|
|
492
|
+
"upgradeLineProtocol: opts required");
|
|
493
|
+
}
|
|
494
|
+
var state = opts.state;
|
|
495
|
+
if (!state || typeof state !== "object") {
|
|
496
|
+
throw new MailServerTlsError("mail-server-tls/bad-upgrade-line-state",
|
|
497
|
+
"upgradeLineProtocol: opts.state object required");
|
|
498
|
+
}
|
|
499
|
+
if (typeof opts.drain !== "function") {
|
|
500
|
+
throw new MailServerTlsError("mail-server-tls/bad-upgrade-line-drain",
|
|
501
|
+
"upgradeLineProtocol: opts.drain(state, tlsSocket) required");
|
|
502
|
+
}
|
|
503
|
+
// CVE-2021-33515 / CVE-2021-38371 injection defense: discard the
|
|
504
|
+
// pre-handshake line buffer plus every protocol-specific half-parsed
|
|
505
|
+
// field so nothing the peer pipelined pre-upgrade survives the TLS
|
|
506
|
+
// boundary.
|
|
507
|
+
state.lineBuffer = Buffer.alloc(0);
|
|
508
|
+
var clearFields = opts.clearFields;
|
|
509
|
+
if (clearFields) {
|
|
510
|
+
for (var i = 0; i < clearFields.length; i += 1) state[clearFields[i]] = null;
|
|
511
|
+
}
|
|
512
|
+
return upgradeSocket({
|
|
513
|
+
plainSocket: opts.socket,
|
|
514
|
+
secureContext: opts.secureContext,
|
|
515
|
+
idleTimeoutMs: opts.idleTimeoutMs,
|
|
516
|
+
onSecure: function (tlsSocket) {
|
|
517
|
+
state.tls = true;
|
|
518
|
+
if (typeof opts.onSecure === "function") opts.onSecure(tlsSocket);
|
|
519
|
+
},
|
|
520
|
+
onData: function (tlsSocket, chunk) {
|
|
521
|
+
state.lineBuffer = Buffer.concat([state.lineBuffer, chunk]);
|
|
522
|
+
opts.drain(state, tlsSocket);
|
|
523
|
+
},
|
|
524
|
+
onError: opts.onError,
|
|
525
|
+
onTimeout: opts.onTimeout,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
441
529
|
module.exports = {
|
|
442
530
|
context: context,
|
|
443
531
|
upgradeSocket: upgradeSocket,
|
|
532
|
+
upgradeLineProtocol: upgradeLineProtocol,
|
|
444
533
|
MailServerTlsError: MailServerTlsError,
|
|
445
534
|
};
|
|
@@ -71,6 +71,7 @@ var { defineClass } = require("./framework-error");
|
|
|
71
71
|
var lazyRequire = require("./lazy-require");
|
|
72
72
|
var validateOpts = require("./validate-opts");
|
|
73
73
|
var gateContract = require("./gate-contract");
|
|
74
|
+
var codepointClass = require("./codepoint-class");
|
|
74
75
|
|
|
75
76
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
76
77
|
|
|
@@ -131,7 +132,7 @@ function create(opts) {
|
|
|
131
132
|
throw new MailSpamScoreError("mail-spam-score/bad-scorer",
|
|
132
133
|
"mail.spamScore.create.scorer must be a function; got " + (typeof opts.scorer));
|
|
133
134
|
}
|
|
134
|
-
var profile =
|
|
135
|
+
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
135
136
|
if (!PROFILES[profile]) {
|
|
136
137
|
throw new MailSpamScoreError("mail-spam-score/bad-profile",
|
|
137
138
|
"mail.spamScore.create.profile: unknown '" + profile +
|
|
@@ -250,13 +251,11 @@ function _sanitizeReasons(reasons, caps) {
|
|
|
250
251
|
// Refuse control bytes (CR / LF / NUL / etc.) — a compromised
|
|
251
252
|
// scorer could try to smuggle CRLF into an outbound X-Spam-Status
|
|
252
253
|
// header.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
cc.toString(16)); // hex radix
|
|
259
|
-
}
|
|
254
|
+
var _ctlOff = codepointClass.firstControlCharOffset(r, { forbidTab: true });
|
|
255
|
+
if (_ctlOff !== -1) {
|
|
256
|
+
throw new MailSpamScoreError("mail-spam-score/control-byte",
|
|
257
|
+
"mail.spamScore.score: reasons[" + i + "] contains control byte 0x" +
|
|
258
|
+
r.charCodeAt(_ctlOff).toString(16)); // hex radix
|
|
260
259
|
}
|
|
261
260
|
out.push(r);
|
|
262
261
|
}
|
|
@@ -61,6 +61,7 @@ var C = require("./constants");
|
|
|
61
61
|
var bCrypto = require("./crypto");
|
|
62
62
|
var cryptoField = require("./crypto-field");
|
|
63
63
|
var vault = require("./vault");
|
|
64
|
+
var safeBuffer = require("./safe-buffer");
|
|
64
65
|
var safeMime = require("./safe-mime");
|
|
65
66
|
var safeSql = require("./safe-sql");
|
|
66
67
|
var sql = require("./sql");
|
|
@@ -798,7 +799,7 @@ function _appendMessage(args) {
|
|
|
798
799
|
"appendMessage: rawBytes must be Buffer or string");
|
|
799
800
|
}
|
|
800
801
|
var buf = Buffer.isBuffer(rawBytes) ? rawBytes : Buffer.from(rawBytes, "utf8");
|
|
801
|
-
if (buf
|
|
802
|
+
if (safeBuffer.byteLengthOf(buf) > args.maxMessageBytes) {
|
|
802
803
|
throw new MailStoreError("mail-store/oversize-message",
|
|
803
804
|
"appendMessage: " + buf.length + " bytes exceeds maxMessageBytes=" + args.maxMessageBytes);
|
|
804
805
|
}
|
|
@@ -854,7 +855,7 @@ function _appendMessage(args) {
|
|
|
854
855
|
var bodyText = textPart ? textPart.body : "";
|
|
855
856
|
var bodyHtml = htmlPart && htmlPart.contentType === "text/html" ? htmlPart.body : "";
|
|
856
857
|
|
|
857
|
-
if (bodyText
|
|
858
|
+
if (safeBuffer.byteLengthOf(bodyText) > args.maxBodyBytes || safeBuffer.byteLengthOf(bodyHtml) > args.maxBodyBytes) {
|
|
858
859
|
throw new MailStoreError("mail-store/oversize-body",
|
|
859
860
|
"appendMessage: body exceeds maxBodyBytes=" + args.maxBodyBytes);
|
|
860
861
|
}
|
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
*/
|
|
58
58
|
var C = require("./constants");
|
|
59
59
|
var bCrypto = require("./crypto");
|
|
60
|
+
var codepointClass = require("./codepoint-class");
|
|
61
|
+
var markupEscape = require("./markup-escape").markupEscape;
|
|
60
62
|
var lazyRequire = require("./lazy-require");
|
|
61
63
|
var safeBuffer = require("./safe-buffer");
|
|
62
64
|
var guardDomain = require("./guard-domain");
|
|
@@ -388,11 +390,7 @@ function _renderPostalAddressHtml(addr) {
|
|
|
388
390
|
}
|
|
389
391
|
|
|
390
392
|
function _htmlEscape(s) {
|
|
391
|
-
return
|
|
392
|
-
.replace(/&/g, "&")
|
|
393
|
-
.replace(/</g, "<")
|
|
394
|
-
.replace(/>/g, ">")
|
|
395
|
-
.replace(/"/g, """);
|
|
393
|
+
return markupEscape(s);
|
|
396
394
|
}
|
|
397
395
|
|
|
398
396
|
function _hasUnsubscribe(message) {
|
|
@@ -1920,12 +1918,9 @@ function feedbackId(opts) {
|
|
|
1920
1918
|
// Refuse CR/LF (header-injection) + control chars. Walk codepoints
|
|
1921
1919
|
// manually because eslint's no-control-regex refuses control-char
|
|
1922
1920
|
// ranges in regex literals regardless of escape form.
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
throw new MailError("mail/bad-feedback-id-field",
|
|
1927
|
-
"feedbackId: " + f.key + " contains control characters");
|
|
1928
|
-
}
|
|
1921
|
+
if (codepointClass.firstControlCharOffset(f.value, { forbidTab: true }) !== -1) { // C0 + DEL codepoint range
|
|
1922
|
+
throw new MailError("mail/bad-feedback-id-field",
|
|
1923
|
+
"feedbackId: " + f.key + " contains control characters");
|
|
1929
1924
|
}
|
|
1930
1925
|
parts.push(f.value);
|
|
1931
1926
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// markup-escape — the shared XML/HTML text + attribute escaper used wherever
|
|
4
|
+
// the framework SERIALIZES a value into markup (mail report / DAV / autoconfig
|
|
5
|
+
// XML, the Azure blob XML API, and — once routed — the b.guardHtml / b.guardSvg
|
|
6
|
+
// sanitizer output). Distinct from markup-tokenizer (which LEXES markup for the
|
|
7
|
+
// sanitizers) and xml-c14n (which canonicalizes for XMLDSig with a different
|
|
8
|
+
// escape set, e.g. \r\n\t and NO ">").
|
|
9
|
+
//
|
|
10
|
+
// markupEscape(str, opts) escapes the four always-dangerous markup
|
|
11
|
+
// metacharacters — & < > " — to their entity forms, with "&" first so the
|
|
12
|
+
// entities it emits are not double-escaped. The one axis that genuinely varies
|
|
13
|
+
// across callers is the apostrophe, so it is a parameter:
|
|
14
|
+
// opts.apos omitted / falsy → "'" is left as-is (element content and
|
|
15
|
+
// double-quoted attributes don't require it escaped)
|
|
16
|
+
// opts.apos === "'" → HTML numeric form
|
|
17
|
+
// opts.apos === "'" → XML named form
|
|
18
|
+
// Input COERCION stays with the caller (some map null/undefined or any
|
|
19
|
+
// non-string to "" before serializing); markupEscape String()s defensively so
|
|
20
|
+
// a stray number/boolean still escapes rather than throwing.
|
|
21
|
+
function markupEscape(str, opts) {
|
|
22
|
+
var s = String(str)
|
|
23
|
+
.replace(/&/g, "&")
|
|
24
|
+
.replace(/</g, "<")
|
|
25
|
+
.replace(/>/g, ">")
|
|
26
|
+
.replace(/"/g, """);
|
|
27
|
+
var apos = opts && opts.apos;
|
|
28
|
+
return apos ? s.replace(/'/g, apos) : s;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { markupEscape: markupEscape };
|