@blamejs/blamejs-shop 0.4.68 → 0.4.70
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/admin.js +8 -6
- package/lib/asset-manifest.json +1 -1
- package/lib/giftcards.js +29 -5
- package/lib/security-middleware.js +65 -23
- package/lib/storefront.js +10 -7
- package/lib/vendor/MANIFEST.json +319 -267
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +58 -5
- package/lib/vendor/blamejs/examples/wiki/README.md +1 -1
- package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +9 -8
- package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +10 -9
- package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +4 -3
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +33 -17
- package/lib/vendor/blamejs/examples/wiki/routes/admin.js +7 -10
- package/lib/vendor/blamejs/examples/wiki/server.js +5 -4
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +5 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +38 -6
- package/lib/vendor/blamejs/lib/agent-event-bus.js +13 -0
- package/lib/vendor/blamejs/lib/agent-idempotency.js +5 -1
- package/lib/vendor/blamejs/lib/agent-snapshot.js +32 -2
- package/lib/vendor/blamejs/lib/ai-aedt-bias-audit.js +2 -1
- package/lib/vendor/blamejs/lib/ai-content-detect.js +1 -3
- package/lib/vendor/blamejs/lib/ai-frontier-protocol.js +1 -1
- package/lib/vendor/blamejs/lib/ai-model-manifest.js +1 -1
- package/lib/vendor/blamejs/lib/ai-output.js +16 -7
- package/lib/vendor/blamejs/lib/api-snapshot.js +4 -1
- package/lib/vendor/blamejs/lib/app-shutdown.js +7 -1
- package/lib/vendor/blamejs/lib/archive-gz.js +9 -0
- package/lib/vendor/blamejs/lib/archive-read.js +9 -7
- package/lib/vendor/blamejs/lib/archive-tar-read.js +51 -8
- package/lib/vendor/blamejs/lib/archive.js +4 -2
- package/lib/vendor/blamejs/lib/asn1-der.js +70 -22
- package/lib/vendor/blamejs/lib/atomic-file.js +204 -2
- package/lib/vendor/blamejs/lib/audit-chain.js +54 -5
- package/lib/vendor/blamejs/lib/audit-daily-review.js +12 -2
- package/lib/vendor/blamejs/lib/audit-sign.js +2 -1
- package/lib/vendor/blamejs/lib/audit-tools.js +108 -23
- package/lib/vendor/blamejs/lib/audit.js +7 -2
- package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -2
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +1 -1
- package/lib/vendor/blamejs/lib/auth/ciba.js +43 -4
- package/lib/vendor/blamejs/lib/auth/dpop.js +6 -1
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +5 -1
- package/lib/vendor/blamejs/lib/auth/jwt.js +2 -2
- package/lib/vendor/blamejs/lib/auth/lockout.js +18 -2
- package/lib/vendor/blamejs/lib/auth/passkey.js +1 -1
- package/lib/vendor/blamejs/lib/auth/password.js +1 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +33 -13
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +24 -4
- package/lib/vendor/blamejs/lib/auth/status-list.js +14 -2
- package/lib/vendor/blamejs/lib/auth/step-up.js +9 -1
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +21 -2
- package/lib/vendor/blamejs/lib/backup/bundle.js +7 -2
- package/lib/vendor/blamejs/lib/backup/crypto.js +23 -8
- package/lib/vendor/blamejs/lib/backup/index.js +41 -20
- package/lib/vendor/blamejs/lib/backup/manifest.js +7 -1
- package/lib/vendor/blamejs/lib/break-glass.js +41 -22
- package/lib/vendor/blamejs/lib/cbor.js +34 -11
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +7 -3
- package/lib/vendor/blamejs/lib/cert.js +5 -3
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/cloud-events.js +3 -2
- package/lib/vendor/blamejs/lib/cluster-storage.js +7 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +17 -0
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -1
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +9 -7
- package/lib/vendor/blamejs/lib/compliance.js +1 -1
- package/lib/vendor/blamejs/lib/config-drift.js +22 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +11 -8
- package/lib/vendor/blamejs/lib/content-digest.js +11 -4
- package/lib/vendor/blamejs/lib/cookies.js +10 -2
- package/lib/vendor/blamejs/lib/cose.js +20 -0
- package/lib/vendor/blamejs/lib/crdt.js +2 -1
- package/lib/vendor/blamejs/lib/crypto-field.js +29 -23
- package/lib/vendor/blamejs/lib/crypto.js +18 -4
- package/lib/vendor/blamejs/lib/csp.js +4 -0
- package/lib/vendor/blamejs/lib/daemon.js +4 -1
- package/lib/vendor/blamejs/lib/data-act.js +27 -4
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +14 -6
- package/lib/vendor/blamejs/lib/db-query.js +69 -9
- package/lib/vendor/blamejs/lib/db.js +32 -15
- package/lib/vendor/blamejs/lib/dora.js +43 -13
- package/lib/vendor/blamejs/lib/dr-runbook.js +1 -1
- package/lib/vendor/blamejs/lib/dsa.js +2 -1
- package/lib/vendor/blamejs/lib/dsr.js +22 -8
- package/lib/vendor/blamejs/lib/early-hints.js +19 -0
- package/lib/vendor/blamejs/lib/eat.js +5 -1
- package/lib/vendor/blamejs/lib/external-db.js +60 -4
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +30 -5
- package/lib/vendor/blamejs/lib/flag-providers.js +6 -2
- package/lib/vendor/blamejs/lib/forms.js +1 -1
- package/lib/vendor/blamejs/lib/gate-contract.js +46 -5
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +18 -9
- package/lib/vendor/blamejs/lib/graphql-federation.js +17 -4
- package/lib/vendor/blamejs/lib/guard-all.js +2 -2
- package/lib/vendor/blamejs/lib/guard-dsn.js +1 -1
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-html.js +9 -11
- package/lib/vendor/blamejs/lib/guard-imap-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-jmap.js +1 -1
- package/lib/vendor/blamejs/lib/guard-json.js +14 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +1 -1
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +8 -9
- package/lib/vendor/blamejs/lib/html-balance.js +7 -3
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +33 -12
- package/lib/vendor/blamejs/lib/http-client.js +225 -53
- package/lib/vendor/blamejs/lib/iab-tcf.js +3 -2
- package/lib/vendor/blamejs/lib/importmap-integrity.js +41 -1
- package/lib/vendor/blamejs/lib/incident-report.js +9 -6
- package/lib/vendor/blamejs/lib/json-patch.js +1 -1
- package/lib/vendor/blamejs/lib/json-path.js +24 -3
- package/lib/vendor/blamejs/lib/jtd.js +2 -2
- package/lib/vendor/blamejs/lib/legal-hold.js +24 -8
- package/lib/vendor/blamejs/lib/log.js +2 -2
- package/lib/vendor/blamejs/lib/mail-agent.js +2 -2
- package/lib/vendor/blamejs/lib/mail-arf.js +1 -1
- package/lib/vendor/blamejs/lib/mail-auth.js +3 -3
- package/lib/vendor/blamejs/lib/mail-bimi.js +16 -16
- package/lib/vendor/blamejs/lib/mail-bounce.js +3 -3
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +71 -6
- package/lib/vendor/blamejs/lib/mail-deploy.js +9 -5
- package/lib/vendor/blamejs/lib/mail-greylist.js +2 -4
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -4
- package/lib/vendor/blamejs/lib/mail-journal.js +11 -8
- package/lib/vendor/blamejs/lib/mail-mdn.js +8 -4
- package/lib/vendor/blamejs/lib/mail-rbl.js +2 -4
- package/lib/vendor/blamejs/lib/mail-scan.js +3 -5
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +4 -1
- package/lib/vendor/blamejs/lib/mail-server-registry.js +1 -1
- package/lib/vendor/blamejs/lib/mail-server-tls.js +9 -2
- package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -4
- package/lib/vendor/blamejs/lib/mail-store-fts.js +1 -1
- package/lib/vendor/blamejs/lib/mail.js +22 -2
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +24 -0
- package/lib/vendor/blamejs/lib/mcp.js +6 -4
- package/lib/vendor/blamejs/lib/mdoc.js +26 -3
- package/lib/vendor/blamejs/lib/metrics.js +14 -3
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +10 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +26 -18
- package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +5 -1
- package/lib/vendor/blamejs/lib/middleware/compression.js +9 -0
- package/lib/vendor/blamejs/lib/middleware/cors.js +32 -23
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +60 -21
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -4
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +28 -4
- package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +61 -30
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +25 -16
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +24 -6
- package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +6 -3
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +2 -2
- package/lib/vendor/blamejs/lib/money.js +1 -1
- package/lib/vendor/blamejs/lib/mtls-ca.js +10 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
- package/lib/vendor/blamejs/lib/network-dns.js +9 -2
- package/lib/vendor/blamejs/lib/network-dnssec.js +2 -1
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +23 -5
- package/lib/vendor/blamejs/lib/network-tls.js +27 -5
- package/lib/vendor/blamejs/lib/network-tsig.js +2 -2
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -1
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +1 -1
- package/lib/vendor/blamejs/lib/ntp-check.js +28 -0
- package/lib/vendor/blamejs/lib/numeric-bounds.js +9 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -2
- package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +4 -2
- package/lib/vendor/blamejs/lib/object-store/gcs.js +6 -4
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -2
- package/lib/vendor/blamejs/lib/object-store/http-request.js +30 -1
- package/lib/vendor/blamejs/lib/object-store/local.js +37 -17
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +1 -2
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +20 -4
- package/lib/vendor/blamejs/lib/outbox.js +11 -4
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +21 -3
- package/lib/vendor/blamejs/lib/queue-local.js +10 -3
- package/lib/vendor/blamejs/lib/redact.js +7 -3
- package/lib/vendor/blamejs/lib/request-helpers.js +201 -23
- package/lib/vendor/blamejs/lib/resource-access-lock.js +3 -3
- package/lib/vendor/blamejs/lib/restore-bundle.js +46 -18
- package/lib/vendor/blamejs/lib/restore-rollback.js +10 -4
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +20 -4
- package/lib/vendor/blamejs/lib/router.js +17 -4
- package/lib/vendor/blamejs/lib/safe-ical.js +2 -2
- package/lib/vendor/blamejs/lib/safe-icap.js +1 -1
- package/lib/vendor/blamejs/lib/safe-json.js +44 -0
- package/lib/vendor/blamejs/lib/safe-sieve.js +1 -1
- package/lib/vendor/blamejs/lib/safe-vcard.js +1 -1
- package/lib/vendor/blamejs/lib/sandbox-worker.js +6 -0
- package/lib/vendor/blamejs/lib/sandbox.js +1 -1
- package/lib/vendor/blamejs/lib/scheduler.js +17 -1
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +16 -0
- package/lib/vendor/blamejs/lib/session.js +27 -3
- package/lib/vendor/blamejs/lib/sql.js +3 -3
- package/lib/vendor/blamejs/lib/static.js +65 -13
- package/lib/vendor/blamejs/lib/template.js +7 -5
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -19
- package/lib/vendor/blamejs/lib/tsa.js +5 -2
- package/lib/vendor/blamejs/lib/vault/index.js +5 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +22 -26
- package/lib/vendor/blamejs/lib/vault/passphrase-source.js +8 -3
- package/lib/vendor/blamejs/lib/vault/rotate.js +13 -18
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +4 -1
- package/lib/vendor/blamejs/lib/vc.js +1 -1
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +10 -10
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +23 -10
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5498 -5494
- package/lib/vendor/blamejs/lib/webhook.js +16 -1
- package/lib/vendor/blamejs/lib/websocket.js +1 -1
- package/lib/vendor/blamejs/lib/worm.js +1 -1
- package/lib/vendor/blamejs/lib/ws-client.js +57 -46
- package/lib/vendor/blamejs/lib/x509-chain.js +44 -0
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.14.json +122 -0
- package/lib/vendor/blamejs/scripts/check-vendor-currency.js +119 -4
- package/lib/vendor/blamejs/test/00-primitives.js +5 -1
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +18 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +42 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-gz.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-hardening.test.js +160 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-open-nofollow.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-excl.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-stream.test.js +181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-corrupted-anchor.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-incremental-verify.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +48 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +13 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +5 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +62 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-storage.test.js +40 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +146 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compression-range.test.js +115 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +17 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +27 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +20 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-alg-kty.test.js +64 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-throttle-transform.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-header-injection.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +63 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/mdoc.test.js +41 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +61 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/object-store-range-header.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/output-header-hardening.test.js +102 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parser-verify-hardening.test.js +191 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/proto-shadow-allowlist.test.js +120 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-blob-remap.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-sweep-termination.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-body-validation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json-stringify-for-script.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +48 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +42 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +7 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template-escape-html.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-default-store.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-currency-classify.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/x509-chain-ca-enforcement.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +34 -0
- package/package.json +1 -1
|
@@ -117,7 +117,7 @@ function _normalizeLevel(level) {
|
|
|
117
117
|
return level;
|
|
118
118
|
}
|
|
119
119
|
if (typeof level === "string") {
|
|
120
|
-
if (LEVELS
|
|
120
|
+
if (!Object.prototype.hasOwnProperty.call(LEVELS, level)) {
|
|
121
121
|
throw new LogError("log/bad-level",
|
|
122
122
|
"level must be one of " + LEVEL_NAMES.join(", "));
|
|
123
123
|
}
|
|
@@ -587,7 +587,7 @@ function _escapeC0Controls(s) {
|
|
|
587
587
|
function _bootMinLevel() {
|
|
588
588
|
// allow:raw-process-env — see header comment above
|
|
589
589
|
var raw = process.env.BLAMEJS_BOOT_LOG_LEVEL || process.env.LOG_LEVEL || "info";
|
|
590
|
-
return LEVELS
|
|
590
|
+
return Object.prototype.hasOwnProperty.call(LEVELS, raw) ? LEVELS[raw] : LEVELS.info;
|
|
591
591
|
}
|
|
592
592
|
|
|
593
593
|
/**
|
|
@@ -353,7 +353,7 @@ async function _dispatchOrLocal(ctx, method, args, localFn) {
|
|
|
353
353
|
var mode = ctx.dispatch.mode;
|
|
354
354
|
if (mode === "local") return localFn(ctx, args);
|
|
355
355
|
if (mode === "auto") {
|
|
356
|
-
if (HEAVY_METHODS
|
|
356
|
+
if (Object.prototype.hasOwnProperty.call(HEAVY_METHODS, method) && ctx.dispatch.queue) return _enqueueMethod(ctx, method, args);
|
|
357
357
|
return localFn(ctx, args);
|
|
358
358
|
}
|
|
359
359
|
// mode === "queue" — explicit queue dispatch.
|
|
@@ -362,7 +362,7 @@ async function _dispatchOrLocal(ctx, method, args, localFn) {
|
|
|
362
362
|
"agent." + method + ": dispatch.mode='queue' requires opts.dispatch.queue");
|
|
363
363
|
}
|
|
364
364
|
// Sync-result methods refuse until orchestrator's result-bus lands.
|
|
365
|
-
if (!HEAVY_METHODS
|
|
365
|
+
if (!Object.prototype.hasOwnProperty.call(HEAVY_METHODS, method)) {
|
|
366
366
|
throw new MailAgentError("mail-agent/queue-result-bus-deferred",
|
|
367
367
|
"agent." + method + ": queue mode for sync-result methods wires at v0.9.21 " +
|
|
368
368
|
"(b.agent.orchestrator). Use mode='local' or mode='auto' until then.");
|
|
@@ -274,7 +274,7 @@ function parse(rawMessage, opts) {
|
|
|
274
274
|
// Surface non-normalized fields under extraFields for operator
|
|
275
275
|
// visibility (X-* tags ESPs add for routing diagnostics, etc.).
|
|
276
276
|
Object.keys(fieldMap).forEach(function (k) {
|
|
277
|
-
if (!KNOWN_FIELDS
|
|
277
|
+
if (!Object.prototype.hasOwnProperty.call(KNOWN_FIELDS, k)) extraFields[k] = fieldMap[k];
|
|
278
278
|
});
|
|
279
279
|
|
|
280
280
|
var event = {
|
|
@@ -1122,7 +1122,7 @@ function _parseDmarcRecord(text) {
|
|
|
1122
1122
|
else if (key === "aspf") policy.aspf = val.toLowerCase();
|
|
1123
1123
|
else if (key === "np") {
|
|
1124
1124
|
var npVal = val.toLowerCase();
|
|
1125
|
-
if (!DMARCBIS_VALID_NP
|
|
1125
|
+
if (!Object.prototype.hasOwnProperty.call(DMARCBIS_VALID_NP, npVal)) {
|
|
1126
1126
|
throw new MailAuthError("mail-auth/dmarcbis-bad-tag",
|
|
1127
1127
|
"DMARC np= must be one of none|quarantine|reject, got " + JSON.stringify(val));
|
|
1128
1128
|
}
|
|
@@ -1130,7 +1130,7 @@ function _parseDmarcRecord(text) {
|
|
|
1130
1130
|
}
|
|
1131
1131
|
else if (key === "psd") {
|
|
1132
1132
|
var psdVal = val.toLowerCase();
|
|
1133
|
-
if (!DMARCBIS_VALID_PSD
|
|
1133
|
+
if (!Object.prototype.hasOwnProperty.call(DMARCBIS_VALID_PSD, psdVal)) {
|
|
1134
1134
|
throw new MailAuthError("mail-auth/dmarcbis-bad-tag",
|
|
1135
1135
|
"DMARC psd= must be one of y|n|u, got " + JSON.stringify(val));
|
|
1136
1136
|
}
|
|
@@ -2017,7 +2017,7 @@ function authResultsEmit(opts) {
|
|
|
2017
2017
|
}
|
|
2018
2018
|
var method = String(r.method || "").toLowerCase();
|
|
2019
2019
|
var result = String(r.result || "").toLowerCase();
|
|
2020
|
-
if (!AR_VALID_METHODS
|
|
2020
|
+
if (!Object.prototype.hasOwnProperty.call(AR_VALID_METHODS, method)) {
|
|
2021
2021
|
throw new MailAuthError("mail-auth/ar-bad-method",
|
|
2022
2022
|
"authResults.emit: unknown method '" + r.method + "'");
|
|
2023
2023
|
}
|
|
@@ -57,6 +57,7 @@ var lazyRequire = require("./lazy-require");
|
|
|
57
57
|
var networkDnsResolver = lazyRequire(function () { return require("./network-dns-resolver"); });
|
|
58
58
|
var safeBuffer = require("./safe-buffer");
|
|
59
59
|
var markupTokenizer = require("./markup-tokenizer");
|
|
60
|
+
var x509Chain = require("./x509-chain");
|
|
60
61
|
var structuredFields = require("./structured-fields");
|
|
61
62
|
var safeUrl = require("./safe-url");
|
|
62
63
|
var validateOpts = require("./validate-opts");
|
|
@@ -399,7 +400,7 @@ function validateTinyPsSvg(svgBytes) {
|
|
|
399
400
|
}
|
|
400
401
|
// Any element name starting with "animate" is animation (covers
|
|
401
402
|
// future SMIL extensions not in the static list above).
|
|
402
|
-
if (name.indexOf("animate") === 0 && !TINY_PS_FORBIDDEN_TAGS
|
|
403
|
+
if (name.indexOf("animate") === 0 && !Object.prototype.hasOwnProperty.call(TINY_PS_FORBIDDEN_TAGS, name)) {
|
|
403
404
|
_vio("element-forbidden",
|
|
404
405
|
"<" + name + "> animation element is forbidden in Tiny-PS");
|
|
405
406
|
}
|
|
@@ -492,10 +493,14 @@ function _tokenizeTinyPsSvg(s) {
|
|
|
492
493
|
if (lt > pos) tokens.push({ type: "text", raw: s.slice(pos, lt) });
|
|
493
494
|
|
|
494
495
|
if (s.startsWith("<!--", lt)) {
|
|
495
|
-
|
|
496
|
+
// WHATWG comment end ("--!>" + abrupt "<!-->" / "<!--->"), matching a
|
|
497
|
+
// browser parsing inline SVG — so an element smuggled past an early
|
|
498
|
+
// terminator can't slip the Tiny-PS validation (mXSS differential).
|
|
499
|
+
// Fails closed on an unterminated comment.
|
|
500
|
+
var endC = markupTokenizer.htmlCommentEnd(s, lt);
|
|
496
501
|
if (endC === -1) throw new Error("unterminated comment"); // allow:bare-error-throw — caught by outer try/catch and re-thrown as MailBimiError("bimi/svg-tiny-ps-violation")
|
|
497
|
-
tokens.push({ type: "comment", raw: s.slice(lt, endC
|
|
498
|
-
pos = endC
|
|
502
|
+
tokens.push({ type: "comment", raw: s.slice(lt, endC) });
|
|
503
|
+
pos = endC;
|
|
499
504
|
continue;
|
|
500
505
|
}
|
|
501
506
|
if (s.startsWith("<![CDATA[", lt)) {
|
|
@@ -823,11 +828,10 @@ function _verifyCertChain(leaf, intermediates, anchors) {
|
|
|
823
828
|
|
|
824
829
|
for (var ai = 0; ai < anchors.length; ai += 1) {
|
|
825
830
|
var anchor = anchors[ai];
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
+
// issuerValidlyIssued enforces basicConstraints cA:TRUE on the anchor
|
|
832
|
+
// in addition to the issuance + signature checks, so a non-CA cert
|
|
833
|
+
// cannot mint a VMC (basicConstraints bypass, CVE-2002-0862 class).
|
|
834
|
+
if (x509Chain.issuerValidlyIssued(anchor, current)) return { ok: true };
|
|
831
835
|
}
|
|
832
836
|
if (current.checkIssued(current)) {
|
|
833
837
|
return { ok: false, reason: "self-signed root not in trust-anchor bundle" };
|
|
@@ -837,13 +841,9 @@ function _verifyCertChain(leaf, intermediates, anchors) {
|
|
|
837
841
|
for (var ii = 0; ii < intermediates.length; ii += 1) {
|
|
838
842
|
var cand = intermediates[ii];
|
|
839
843
|
if (cand === current) continue;
|
|
840
|
-
if (
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
nextIssuer = cand;
|
|
844
|
-
break;
|
|
845
|
-
}
|
|
846
|
-
} catch (_e) { /* fall through */ }
|
|
844
|
+
if (x509Chain.issuerValidlyIssued(cand, current)) {
|
|
845
|
+
nextIssuer = cand;
|
|
846
|
+
break;
|
|
847
847
|
}
|
|
848
848
|
}
|
|
849
849
|
if (nextIssuer === null) {
|
|
@@ -448,7 +448,7 @@ function handler(opts) {
|
|
|
448
448
|
opts = opts || {};
|
|
449
449
|
var vendor = opts.vendor;
|
|
450
450
|
var customParser = typeof opts.parser === "function" ? opts.parser : null;
|
|
451
|
-
if (!customParser && (typeof vendor !== "string" || !VENDORS
|
|
451
|
+
if (!customParser && (typeof vendor !== "string" || !Object.prototype.hasOwnProperty.call(VENDORS, vendor))) {
|
|
452
452
|
throw _err("handler/bad-config",
|
|
453
453
|
"mailBounce.handler requires { vendor } (one of " +
|
|
454
454
|
Object.keys(VENDORS).join(", ") + ") or { parser }");
|
|
@@ -761,7 +761,7 @@ function _parseDsn(rawMessage) {
|
|
|
761
761
|
throw _err("bounce/dsn-malformed",
|
|
762
762
|
"mailBounce.dsn.parse: per-recipient group missing Final-Recipient");
|
|
763
763
|
}
|
|
764
|
-
if (action && !DSN_ACTIONS
|
|
764
|
+
if (action && !Object.prototype.hasOwnProperty.call(DSN_ACTIONS, action)) {
|
|
765
765
|
throw _err("bounce/dsn-malformed",
|
|
766
766
|
"mailBounce.dsn.parse: Action token '" + action + "' is not RFC 3464 §2.3.3");
|
|
767
767
|
}
|
|
@@ -825,7 +825,7 @@ function _buildDsn(opts) {
|
|
|
825
825
|
validateOpts.requireNonEmptyString(opts.finalRecipient,
|
|
826
826
|
"mailBounce.dsn.build: opts.finalRecipient", MailBounceError, "bounce/dsn-malformed");
|
|
827
827
|
var action = String(opts.action || "failed").toLowerCase();
|
|
828
|
-
if (!DSN_ACTIONS
|
|
828
|
+
if (!Object.prototype.hasOwnProperty.call(DSN_ACTIONS, action)) {
|
|
829
829
|
throw _err("bounce/dsn-malformed",
|
|
830
830
|
"mailBounce.dsn.build: opts.action must be one of " +
|
|
831
831
|
Object.keys(DSN_ACTIONS).join(" / ") + "; got '" + action + "'");
|
|
@@ -98,6 +98,7 @@ var lazyRequire = require("./lazy-require");
|
|
|
98
98
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
99
99
|
var nodeCrypto = require("node:crypto");
|
|
100
100
|
var validateOpts = require("./validate-opts");
|
|
101
|
+
var x509Chain = require("./x509-chain");
|
|
101
102
|
var cms = require("./cms-codec");
|
|
102
103
|
var asn1 = require("./asn1-der");
|
|
103
104
|
var pqcSoftware = require("./pqc-software");
|
|
@@ -297,7 +298,8 @@ function verify(opts) {
|
|
|
297
298
|
// verification failure (bad alg, missing signed-attrs, message-
|
|
298
299
|
// digest mismatch, signature mismatch); reaching the next line
|
|
299
300
|
// means the per-signer verify succeeded.
|
|
300
|
-
var siResult = _verifySignerInfo(sd.signerInfos[0], msgBytes, opts.signerPublicKey, opts.audit
|
|
301
|
+
var siResult = _verifySignerInfo(sd.signerInfos[0], msgBytes, opts.signerPublicKey, opts.audit,
|
|
302
|
+
sd.encapContent && sd.encapContent.eContentType);
|
|
301
303
|
// Trust-anchor chain validation when operator supplies roots. The
|
|
302
304
|
// signer cert is in sd.certificates (its serialNumber matches the
|
|
303
305
|
// sid's serialNumber); intermediate certs are also in
|
|
@@ -336,7 +338,7 @@ function verify(opts) {
|
|
|
336
338
|
// signer's signature, masking real multi-signer envelopes as a single
|
|
337
339
|
// false-failure). verifyAll now iterates `sd.signerInfos` directly and
|
|
338
340
|
// calls this helper per index with the matching per-signer key.
|
|
339
|
-
function _verifySignerInfo(si, msgBytes, signerPublicKey, auditHandle) {
|
|
341
|
+
function _verifySignerInfo(si, msgBytes, signerPublicKey, auditHandle, eContentType) {
|
|
340
342
|
var sigAlg = _oidToSigAlg(si.sigAlgOid);
|
|
341
343
|
if (!sigAlg) {
|
|
342
344
|
throw new MailCryptoError("mail-crypto/smime/bad-sig-alg",
|
|
@@ -365,6 +367,26 @@ function _verifySignerInfo(si, msgBytes, signerPublicKey, auditHandle) {
|
|
|
365
367
|
"smime.verify: recomputed message digest does not match signedAttrs.messageDigest " +
|
|
366
368
|
"(message was tampered or signed-attrs were swapped)");
|
|
367
369
|
}
|
|
370
|
+
// RFC 5652 §11.1: when signedAttrs are present the contentType attribute
|
|
371
|
+
// MUST be present and MUST equal the SignedData eContentType. The TSA
|
|
372
|
+
// sibling enforces this; S/MIME omitted it, so a SignerInfo with a missing
|
|
373
|
+
// or mismatched contentType still verified — a cross-protocol content-type
|
|
374
|
+
// binding gap. The check runs over signedAttrs, which the signature below
|
|
375
|
+
// covers, so a tampered attribute also fails the signature.
|
|
376
|
+
if (eContentType) {
|
|
377
|
+
var ctOid = _extractContentTypeOid(si.signedAttrsRaw);
|
|
378
|
+
if (!ctOid) {
|
|
379
|
+
_audit(auditHandle, "mail.crypto.smime.verify_fail", "denied", { reason: "no-content-type-attr" });
|
|
380
|
+
throw new MailCryptoError("mail-crypto/smime/no-content-type-attr",
|
|
381
|
+
"smime.verify: signedAttrs missing the contentType attribute (RFC 5652 §11.1)");
|
|
382
|
+
}
|
|
383
|
+
if (ctOid !== eContentType) {
|
|
384
|
+
_audit(auditHandle, "mail.crypto.smime.verify_fail", "denied", { reason: "content-type-mismatch" });
|
|
385
|
+
throw new MailCryptoError("mail-crypto/smime/content-type-mismatch",
|
|
386
|
+
"smime.verify: signedAttrs.contentType (" + ctOid + ") does not match eContentType (" +
|
|
387
|
+
eContentType + ")");
|
|
388
|
+
}
|
|
389
|
+
}
|
|
368
390
|
var ok;
|
|
369
391
|
try {
|
|
370
392
|
ok = sigAlg.pqc.verify(
|
|
@@ -471,7 +493,10 @@ function _verifyTrustChain(sd, trustAnchorCertsPem, signerPublicKey, auditHandle
|
|
|
471
493
|
// Stop when we've reached a trust anchor.
|
|
472
494
|
for (var ri = 0; ri < roots.length; ri += 1) {
|
|
473
495
|
var r = roots[ri];
|
|
474
|
-
|
|
496
|
+
// Enforce basicConstraints cA:TRUE on the issuing root in addition to
|
|
497
|
+
// the DN match + signature — a non-CA cert can never be a chain issuer
|
|
498
|
+
// (basicConstraints bypass, CVE-2002-0862 class).
|
|
499
|
+
if (current.issuer === r.subject && x509Chain.isCaCert(r)) {
|
|
475
500
|
try {
|
|
476
501
|
if (current.verify(r.publicKey)) {
|
|
477
502
|
void auditHandle;
|
|
@@ -480,12 +505,12 @@ function _verifyTrustChain(sd, trustAnchorCertsPem, signerPublicKey, auditHandle
|
|
|
480
505
|
} catch (_e) { /* fall through to next root */ }
|
|
481
506
|
}
|
|
482
507
|
}
|
|
483
|
-
// Find an intermediate whose subject == current.issuer.
|
|
508
|
+
// Find an intermediate whose subject == current.issuer (and that is a CA).
|
|
484
509
|
var found = null;
|
|
485
510
|
for (var hi = 0; hi < chain.length; hi += 1) {
|
|
486
511
|
var h = chain[hi];
|
|
487
512
|
if (h === current) continue;
|
|
488
|
-
if (h.subject === current.issuer) {
|
|
513
|
+
if (h.subject === current.issuer && x509Chain.isCaCert(h)) {
|
|
489
514
|
try {
|
|
490
515
|
if (current.verify(h.publicKey)) { found = h; break; }
|
|
491
516
|
} catch (_e) { /* try next */ }
|
|
@@ -574,7 +599,8 @@ function verifyAll(opts) {
|
|
|
574
599
|
throw new MailCryptoError("mail-crypto/smime/missing-key",
|
|
575
600
|
"verifyAll: no public key supplied for SignerInfo serial " + serialHex);
|
|
576
601
|
}
|
|
577
|
-
var siRes = _verifySignerInfo(si, msgBytes, pub, opts.audit
|
|
602
|
+
var siRes = _verifySignerInfo(si, msgBytes, pub, opts.audit,
|
|
603
|
+
sd.encapContent && sd.encapContent.eContentType);
|
|
578
604
|
results.push({
|
|
579
605
|
serialHex: serialHex,
|
|
580
606
|
sigAlgOid: si.sigAlgOid,
|
|
@@ -621,6 +647,42 @@ function _extractSerialHex(sidBytes) {
|
|
|
621
647
|
|
|
622
648
|
// RFC 5652 §11.2 messageDigest OID.
|
|
623
649
|
var OID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
|
|
650
|
+
// RFC 5652 §11.1 contentType signed-attribute OID.
|
|
651
|
+
var OID_CONTENT_TYPE_ATTR = "1.2.840.113549.1.9.3";
|
|
652
|
+
|
|
653
|
+
// Extract the contentType signed-attribute's OID value from a signedAttrs
|
|
654
|
+
// SET, or null if absent / malformed. Mirrors _extractMessageDigest's walk
|
|
655
|
+
// but the attribute value is an OID (the eContentType), not an OCTET STRING.
|
|
656
|
+
function _extractContentTypeOid(signedAttrsRaw) {
|
|
657
|
+
var node;
|
|
658
|
+
try { node = asn1.readNode(signedAttrsRaw); }
|
|
659
|
+
catch (_e) { return null; }
|
|
660
|
+
if (node.tag !== asn1.TAG.SET) return null;
|
|
661
|
+
var attrs;
|
|
662
|
+
try { attrs = asn1.readSequence(node.value); }
|
|
663
|
+
catch (_e) { return null; }
|
|
664
|
+
for (var i = 0; i < attrs.length; i += 1) {
|
|
665
|
+
var attr = attrs[i];
|
|
666
|
+
if (attr.tag !== asn1.TAG.SEQUENCE) continue;
|
|
667
|
+
var children;
|
|
668
|
+
try { children = asn1.readSequence(attr.value); }
|
|
669
|
+
catch (_e) { continue; }
|
|
670
|
+
if (children.length < 2) continue;
|
|
671
|
+
var oid;
|
|
672
|
+
try { oid = asn1.readOid(children[0]); }
|
|
673
|
+
catch (_e) { continue; }
|
|
674
|
+
if (oid !== OID_CONTENT_TYPE_ATTR) continue;
|
|
675
|
+
var valuesSet = children[1];
|
|
676
|
+
if (valuesSet.tag !== asn1.TAG.SET) continue;
|
|
677
|
+
var valueChildren;
|
|
678
|
+
try { valueChildren = asn1.readSequence(valuesSet.value); }
|
|
679
|
+
catch (_e) { continue; }
|
|
680
|
+
if (valueChildren.length === 0) continue;
|
|
681
|
+
try { return asn1.readOid(valueChildren[0]); }
|
|
682
|
+
catch (_e) { return null; }
|
|
683
|
+
}
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
624
686
|
|
|
625
687
|
function _extractMessageDigest(signedAttrsRaw) {
|
|
626
688
|
// signedAttrsRaw is `31 LL VV...` — the universal SET-tagged blob
|
|
@@ -821,4 +883,7 @@ module.exports = {
|
|
|
821
883
|
// validation (a cert matches the verified signer key iff its SPKI public
|
|
822
884
|
// key equals, or has as a suffix, the raw signer key bytes).
|
|
823
885
|
_certKeyMatches: _certKeyMatches,
|
|
886
|
+
// Exposed for tests — RFC 5652 §11.1 contentType signed-attr extraction
|
|
887
|
+
// (verify binds it to the eContentType).
|
|
888
|
+
_extractContentTypeOid: _extractContentTypeOid,
|
|
824
889
|
};
|
|
@@ -123,7 +123,7 @@ function mtaStsPublish(opts) {
|
|
|
123
123
|
throw new MailDeployError("mail-deploy/bad-domain",
|
|
124
124
|
"mtaStsPublish: opts.domain must be a valid hostname");
|
|
125
125
|
}
|
|
126
|
-
if (!STS_MODES
|
|
126
|
+
if (!Object.prototype.hasOwnProperty.call(STS_MODES, opts.mode)) {
|
|
127
127
|
throw new MailDeployError("mail-deploy/bad-mode",
|
|
128
128
|
"mtaStsPublish: opts.mode must be 'enforce' | 'testing' | 'none'");
|
|
129
129
|
}
|
|
@@ -730,14 +730,14 @@ function _validateTlsRptReport(raw, ctx) {
|
|
|
730
730
|
var sRaw = summary["total-successful-session-count"];
|
|
731
731
|
var fRaw = summary["total-failure-session-count"];
|
|
732
732
|
if (sRaw !== undefined) {
|
|
733
|
-
if (
|
|
733
|
+
if (!numericBounds.isNonNegativeFiniteInt(sRaw)) {
|
|
734
734
|
throw new TlsRptParseError("mail-tlsrpt/bad-summary",
|
|
735
735
|
"parseTlsRptReport: policies[" + i + "].summary.total-successful-session-count must be a finite non-negative integer");
|
|
736
736
|
}
|
|
737
737
|
totalSuccess += sRaw;
|
|
738
738
|
}
|
|
739
739
|
if (fRaw !== undefined) {
|
|
740
|
-
if (
|
|
740
|
+
if (!numericBounds.isNonNegativeFiniteInt(fRaw)) {
|
|
741
741
|
throw new TlsRptParseError("mail-tlsrpt/bad-summary",
|
|
742
742
|
"parseTlsRptReport: policies[" + i + "].summary.total-failure-session-count must be a finite non-negative integer");
|
|
743
743
|
}
|
|
@@ -776,7 +776,11 @@ function _validatePolicy(p, idx) {
|
|
|
776
776
|
"parseTlsRptReport: policies[" + idx + "].policy missing");
|
|
777
777
|
}
|
|
778
778
|
var pType = policy["policy-type"];
|
|
779
|
-
|
|
779
|
+
// hasOwnProperty, not `TLSRPT_POLICY_TYPES[pType]`: a remote MTA's report JSON
|
|
780
|
+
// controls pType, and a bracket lookup on the plain-object allowlist resolves
|
|
781
|
+
// inherited members ("constructor"/"__proto__"/"toString") to truthy, passing
|
|
782
|
+
// an out-of-vocabulary policy-type (prototype shadowing).
|
|
783
|
+
if (typeof pType !== "string" || !Object.prototype.hasOwnProperty.call(TLSRPT_POLICY_TYPES, pType)) {
|
|
780
784
|
throw new TlsRptParseError("mail-tlsrpt/bad-policy",
|
|
781
785
|
"parseTlsRptReport: policies[" + idx + "].policy.policy-type '" + pType +
|
|
782
786
|
"' not in {sts, tlsa, no-policy-found}");
|
|
@@ -805,7 +809,7 @@ function _validatePolicy(p, idx) {
|
|
|
805
809
|
throw new TlsRptParseError("mail-tlsrpt/bad-failure-detail",
|
|
806
810
|
"parseTlsRptReport: policies[" + idx + "].failure-details[" + k + "] must be an object");
|
|
807
811
|
}
|
|
808
|
-
if (typeof fd["result-type"] === "string" && !TLSRPT_RESULT_TYPES
|
|
812
|
+
if (typeof fd["result-type"] === "string" && !Object.prototype.hasOwnProperty.call(TLSRPT_RESULT_TYPES, fd["result-type"])) {
|
|
809
813
|
// Unknown result-type — surface as audit metadata but don't
|
|
810
814
|
// refuse; RFC 8460 §4.4 result-type registry can grow over
|
|
811
815
|
// time and we shouldn't break on new IANA entries.
|
|
@@ -162,7 +162,7 @@ var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
|
162
162
|
function create(opts) {
|
|
163
163
|
opts = opts || {};
|
|
164
164
|
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
165
|
-
if (!PROFILES
|
|
165
|
+
if (!Object.prototype.hasOwnProperty.call(PROFILES, profile)) {
|
|
166
166
|
throw new MailGreylistError("mail-greylist/bad-profile",
|
|
167
167
|
"create: unknown profile '" + profile + "'");
|
|
168
168
|
}
|
|
@@ -323,9 +323,7 @@ function create(opts) {
|
|
|
323
323
|
* @example
|
|
324
324
|
* b.mail.greylist.compliancePosture("hipaa"); // → "strict"
|
|
325
325
|
*/
|
|
326
|
-
|
|
327
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
328
|
-
}
|
|
326
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
329
327
|
|
|
330
328
|
function _hashFingerprint(cidr, mailFrom, rcptTo) {
|
|
331
329
|
// Namespace-hash so the on-disk key is unlinkable to the PII
|
|
@@ -201,7 +201,7 @@ var LOCALHOST_REFUSED = Object.freeze({
|
|
|
201
201
|
async function evaluate(ctx, opts) {
|
|
202
202
|
opts = opts || {};
|
|
203
203
|
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
204
|
-
if (!PROFILES
|
|
204
|
+
if (!Object.prototype.hasOwnProperty.call(PROFILES, profile)) {
|
|
205
205
|
throw new MailHeloError("mail-helo/bad-profile",
|
|
206
206
|
"evaluate: unknown profile '" + profile + "'");
|
|
207
207
|
}
|
|
@@ -453,9 +453,7 @@ function _emitAudit(auditImpl, action, metadata) {
|
|
|
453
453
|
* @example
|
|
454
454
|
* b.mail.helo.compliancePosture("hipaa"); // → "strict"
|
|
455
455
|
*/
|
|
456
|
-
|
|
457
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
458
|
-
}
|
|
456
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
459
457
|
|
|
460
458
|
module.exports = {
|
|
461
459
|
evaluate: evaluate,
|
|
@@ -180,9 +180,9 @@ function create(opts) {
|
|
|
180
180
|
throw new MailJournalError("mail-journal/bad-vault",
|
|
181
181
|
"b.mail.journal.create: opts.vault must be a b.vault handle");
|
|
182
182
|
}
|
|
183
|
-
if (!opts.legalHold || typeof opts.legalHold.
|
|
183
|
+
if (!opts.legalHold || typeof opts.legalHold.isHeld !== "function") {
|
|
184
184
|
throw new MailJournalError("mail-journal/bad-legal-hold",
|
|
185
|
-
"b.mail.journal.create: opts.legalHold must be a b.legalHold handle (must expose
|
|
185
|
+
"b.mail.journal.create: opts.legalHold must be a b.legalHold handle (must expose isHeld)");
|
|
186
186
|
}
|
|
187
187
|
if (!opts.db || typeof opts.db.runSql !== "function") {
|
|
188
188
|
throw new MailJournalError("mail-journal/bad-db",
|
|
@@ -252,7 +252,7 @@ function create(opts) {
|
|
|
252
252
|
async function record(req) {
|
|
253
253
|
validateOpts.requireObject(req, "mail.journal.record",
|
|
254
254
|
MailJournalError, "mail-journal/bad-record");
|
|
255
|
-
if (!ALLOWED_DIRECTIONS
|
|
255
|
+
if (!Object.prototype.hasOwnProperty.call(ALLOWED_DIRECTIONS, req.direction)) {
|
|
256
256
|
throw new MailJournalError("mail-journal/bad-direction",
|
|
257
257
|
"mail.journal.record: opts.direction must be 'inbound' | 'outbound' | 'internal'");
|
|
258
258
|
}
|
|
@@ -300,11 +300,13 @@ function create(opts) {
|
|
|
300
300
|
|
|
301
301
|
var regimesJson = JSON.stringify(opts.regimes);
|
|
302
302
|
var floorUntil = archivedAt + floorMs;
|
|
303
|
-
//
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
303
|
+
// Auto-derive the legal-hold flag from the registry: an entry whose actor is
|
|
304
|
+
// under an active legal hold is born held, exempt from retention expiry even
|
|
305
|
+
// after the floor passes (the doc's "every entry carries a legalHold flag").
|
|
306
|
+
// setLegalHold remains the manual override. isHeld already treats a lapsed
|
|
307
|
+
// (retainUntil-expired) hold as not-held, so a stale hold won't over-flag.
|
|
308
|
+
var actorHeld = !!opts.legalHold.isHeld(req.actorId);
|
|
309
|
+
// b.sql quotes every column + binds every value as a placeholder.
|
|
308
310
|
var insBuilt = _t("insert").values({
|
|
309
311
|
journal_id: journalId,
|
|
310
312
|
direction: req.direction,
|
|
@@ -314,6 +316,7 @@ function create(opts) {
|
|
|
314
316
|
size_bytes: sizeBytes,
|
|
315
317
|
regimes: regimesJson,
|
|
316
318
|
floor_until: floorUntil,
|
|
319
|
+
legal_hold: actorHeld ? 1 : 0,
|
|
317
320
|
storage_key: storageKey,
|
|
318
321
|
sealed_payload: sealedBlob,
|
|
319
322
|
}).toSql();
|
|
@@ -162,14 +162,14 @@ function build(opts) {
|
|
|
162
162
|
validateOpts.requireNonEmptyString(opts.finalRecipient,
|
|
163
163
|
"mailMdn.build: opts.finalRecipient", MailMdnError, "mdn/missing-required-field");
|
|
164
164
|
var disposition = String(opts.disposition || "").toLowerCase();
|
|
165
|
-
if (!DISPOSITION_TYPES
|
|
165
|
+
if (!Object.prototype.hasOwnProperty.call(DISPOSITION_TYPES, disposition)) {
|
|
166
166
|
throw _err("mdn/missing-required-field",
|
|
167
167
|
"mailMdn.build: opts.disposition must be one of " +
|
|
168
168
|
Object.keys(DISPOSITION_TYPES).join(" / ") +
|
|
169
169
|
"; got '" + String(opts.disposition) + "'");
|
|
170
170
|
}
|
|
171
171
|
var actionMode = String(opts.actionMode || "manual-action").toLowerCase();
|
|
172
|
-
if (!ACTION_MODES
|
|
172
|
+
if (!Object.prototype.hasOwnProperty.call(ACTION_MODES, actionMode)) {
|
|
173
173
|
throw _err("mdn/missing-required-field",
|
|
174
174
|
"mailMdn.build: opts.actionMode must be one of " +
|
|
175
175
|
Object.keys(ACTION_MODES).join(" / ") +
|
|
@@ -179,7 +179,7 @@ function build(opts) {
|
|
|
179
179
|
// Accept the canonical mixed-case form too — RFC 3798 §3.2.6.2 uses
|
|
180
180
|
// `MDN-sent-manually` / `MDN-sent-automatically`. Compare lower-case
|
|
181
181
|
// for robustness; emit canonical mixed-case in the output.
|
|
182
|
-
if (!SENDING_MODES
|
|
182
|
+
if (!Object.prototype.hasOwnProperty.call(SENDING_MODES, sendingMode)) {
|
|
183
183
|
throw _err("mdn/missing-required-field",
|
|
184
184
|
"mailMdn.build: opts.sendingMode must be one of " +
|
|
185
185
|
"MDN-sent-manually / MDN-sent-automatically; got '" +
|
|
@@ -395,7 +395,11 @@ function parse(rawMessage) {
|
|
|
395
395
|
"mailMdn.parse: message/disposition-notification missing Disposition");
|
|
396
396
|
}
|
|
397
397
|
var disposition = _parseDisposition(dispositionField);
|
|
398
|
-
|
|
398
|
+
// hasOwnProperty: the Disposition token comes from an untrusted inbound MDN, so
|
|
399
|
+
// a bracket lookup lets "constructor"/"__proto__" pass as a valid type (proto
|
|
400
|
+
// shadowing).
|
|
401
|
+
if (!disposition || typeof disposition.type !== "string" ||
|
|
402
|
+
!Object.prototype.hasOwnProperty.call(DISPOSITION_TYPES, disposition.type)) {
|
|
399
403
|
throw _err("mdn/parse-failed",
|
|
400
404
|
"mailMdn.parse: Disposition type token not in RFC 3798 §3.2.6 vocabulary; got '" +
|
|
401
405
|
(disposition && disposition.type) + "'");
|
|
@@ -140,7 +140,7 @@ function create(opts) {
|
|
|
140
140
|
"create: opts.resolver must be a b.network.dns.resolver.create() instance");
|
|
141
141
|
}
|
|
142
142
|
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
143
|
-
if (!PROFILES
|
|
143
|
+
if (!Object.prototype.hasOwnProperty.call(PROFILES, profile)) {
|
|
144
144
|
throw new MailRblError("mail-rbl/bad-profile",
|
|
145
145
|
"create: unknown profile '" + profile + "'");
|
|
146
146
|
}
|
|
@@ -314,9 +314,7 @@ function reverseIp(ip) {
|
|
|
314
314
|
* @example
|
|
315
315
|
* b.mail.rbl.compliancePosture("hipaa"); // → "strict"
|
|
316
316
|
*/
|
|
317
|
-
|
|
318
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
319
|
-
}
|
|
317
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
320
318
|
|
|
321
319
|
function _validateZoneNames(zones) {
|
|
322
320
|
for (var i = 0; i < zones.length; i += 1) {
|
|
@@ -164,7 +164,7 @@ function create(opts) {
|
|
|
164
164
|
numericBounds.requirePositiveFiniteInt(opts.port, "mail.scan.create.port",
|
|
165
165
|
MailScanError, "mail-scan/bad-port", { max: 65535 }); // TCP port-number range cap
|
|
166
166
|
var protocol = opts.protocol || DEFAULT_PROTOCOL;
|
|
167
|
-
if (!ALLOWED_PROTOCOLS
|
|
167
|
+
if (!Object.prototype.hasOwnProperty.call(ALLOWED_PROTOCOLS, protocol)) {
|
|
168
168
|
throw new MailScanError("mail-scan/bad-protocol",
|
|
169
169
|
"mail.scan.create.protocol must be 'icap' or 'clamav-instream'; got '" + protocol + "'");
|
|
170
170
|
}
|
|
@@ -174,7 +174,7 @@ function create(opts) {
|
|
|
174
174
|
MailScanError, "mail-scan/bad-service");
|
|
175
175
|
}
|
|
176
176
|
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
177
|
-
if (!PROFILES
|
|
177
|
+
if (!Object.prototype.hasOwnProperty.call(PROFILES, profile)) {
|
|
178
178
|
throw new MailScanError("mail-scan/bad-profile",
|
|
179
179
|
"mail.scan.create.profile: unknown '" + profile + "' (valid: strict / balanced / permissive)");
|
|
180
180
|
}
|
|
@@ -448,9 +448,7 @@ function create(opts) {
|
|
|
448
448
|
* @example
|
|
449
449
|
* b.mail.scan.compliancePosture("hipaa"); // → "strict"
|
|
450
450
|
*/
|
|
451
|
-
|
|
452
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
453
|
-
}
|
|
451
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
454
452
|
|
|
455
453
|
function _emitScanResult(auditImpl, rv) {
|
|
456
454
|
if (rv.verdict === "clean") {
|
|
@@ -1138,7 +1138,10 @@ function create(opts) {
|
|
|
1138
1138
|
return;
|
|
1139
1139
|
}
|
|
1140
1140
|
var text = data.toString("utf8");
|
|
1141
|
-
|
|
1141
|
+
// Byte cap measured on the raw frame buffer, not text.length (UTF-16
|
|
1142
|
+
// code units) — a multibyte payload is 2-4x larger in bytes than chars,
|
|
1143
|
+
// so a char-length check under-enforces the limit.
|
|
1144
|
+
if (data.length > (opts.webSocketMaxMessageBytes || (10 * 1024 * 1024))) { // allow:raw-byte-literal — mirrors handleUpgrade cap
|
|
1142
1145
|
_sendRequestError(null,
|
|
1143
1146
|
"urn:ietf:params:jmap:error:limit",
|
|
1144
1147
|
"WebSocket message exceeds maxSizeRequest");
|
|
@@ -142,7 +142,7 @@ function create(opts) {
|
|
|
142
142
|
validateOpts.requireNonEmptyString(opts.protocol,
|
|
143
143
|
"b.mail.serverRegistry.create: protocol", MailServerRegistryError,
|
|
144
144
|
"mail-server-registry/bad-protocol");
|
|
145
|
-
if (!CATALOGUE
|
|
145
|
+
if (!Object.prototype.hasOwnProperty.call(CATALOGUE, opts.protocol)) {
|
|
146
146
|
throw new MailServerRegistryError("mail-server-registry/unknown-protocol",
|
|
147
147
|
"create: protocol must be 'imap', 'jmap', or 'managesieve' (got '" + opts.protocol + "')");
|
|
148
148
|
}
|
|
@@ -93,6 +93,7 @@ var nodeFs = require("node:fs");
|
|
|
93
93
|
var nodeTls = require("node:tls");
|
|
94
94
|
var lazyRequire = require("./lazy-require");
|
|
95
95
|
var C = require("./constants");
|
|
96
|
+
var atomicFile = require("./atomic-file");
|
|
96
97
|
var validateOpts = require("./validate-opts");
|
|
97
98
|
var { defineClass } = require("./framework-error");
|
|
98
99
|
|
|
@@ -177,7 +178,11 @@ function context(opts) {
|
|
|
177
178
|
var stopped = false;
|
|
178
179
|
|
|
179
180
|
function _readKey() {
|
|
180
|
-
|
|
181
|
+
// Cap + fd-bound TLS-private-key read. NO refuseSymlink: keyFile is commonly
|
|
182
|
+
// certbot's /etc/letsencrypt/live/<host>/privkey.pem, a symlink chain into
|
|
183
|
+
// ../../archive — refusing symlinks would break the documented Let's Encrypt
|
|
184
|
+
// layout. The cap is the OOM-before-use defense.
|
|
185
|
+
var raw = atomicFile.fdSafeReadSync(keyFile, { maxBytes: C.BYTES.kib(64), encoding: "utf8" });
|
|
181
186
|
// b.vault.sealPemFile produces blobs that decrypt via vault.unseal.
|
|
182
187
|
// Detect by the sealed-cell prefix the framework's vault layer
|
|
183
188
|
// already documents (everything else passes through as plain PEM).
|
|
@@ -196,7 +201,9 @@ function context(opts) {
|
|
|
196
201
|
function _build() {
|
|
197
202
|
var certPem;
|
|
198
203
|
try {
|
|
199
|
-
|
|
204
|
+
// Cap + fd-bound cert-chain read. NO refuseSymlink (certbot fullchain.pem
|
|
205
|
+
// is a symlink); the cap is the safe hardening.
|
|
206
|
+
certPem = atomicFile.fdSafeReadSync(certFile, { maxBytes: C.BYTES.mib(1), encoding: "utf8" });
|
|
200
207
|
} catch (e) {
|
|
201
208
|
throw new MailServerTlsError("mail-server-tls/cert-unreadable",
|
|
202
209
|
"b.mail.server.tls.context: cannot read certFile " + certFile + ": " +
|
|
@@ -133,7 +133,7 @@ function create(opts) {
|
|
|
133
133
|
"mail.spamScore.create.scorer must be a function; got " + (typeof opts.scorer));
|
|
134
134
|
}
|
|
135
135
|
var profile = gateContract.resolveProfileName(opts, COMPLIANCE_POSTURES, DEFAULT_PROFILE);
|
|
136
|
-
if (!PROFILES
|
|
136
|
+
if (!Object.prototype.hasOwnProperty.call(PROFILES, profile)) {
|
|
137
137
|
throw new MailSpamScoreError("mail-spam-score/bad-profile",
|
|
138
138
|
"mail.spamScore.create.profile: unknown '" + profile +
|
|
139
139
|
"' (valid: strict / balanced / permissive)");
|
|
@@ -222,9 +222,7 @@ function create(opts) {
|
|
|
222
222
|
* @example
|
|
223
223
|
* b.mail.spamScore.compliancePosture("hipaa"); // → "strict"
|
|
224
224
|
*/
|
|
225
|
-
|
|
226
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
227
|
-
}
|
|
225
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
228
226
|
|
|
229
227
|
function _sanitizeReasons(reasons, caps) {
|
|
230
228
|
if (reasons === undefined || reasons === null) return [];
|
|
@@ -321,7 +321,7 @@ var QUERY_KEY_MAP = {
|
|
|
321
321
|
* // → { column: "addr_toks", field: "addr" }
|
|
322
322
|
*/
|
|
323
323
|
function columnAndFieldFor(key) {
|
|
324
|
-
return QUERY_KEY_MAP[key]
|
|
324
|
+
return Object.prototype.hasOwnProperty.call(QUERY_KEY_MAP, key) ? QUERY_KEY_MAP[key] : null;
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
// Rewrite an operator query term into a FTS5 MATCH expression. The
|