@blamejs/blamejs-shop 0.5.12 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -2,20 +2,105 @@
|
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
5
|
+
var nodeCrypto = require("node:crypto");
|
|
6
|
+
var zlib = require("node:zlib");
|
|
7
|
+
var EventEmitter = require("events");
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
var helpers = require("../helpers");
|
|
10
|
+
var b = helpers.b;
|
|
11
|
+
var check = helpers.check;
|
|
12
|
+
var _bodyReq = helpers._bodyReq;
|
|
13
|
+
var _bodyRes = helpers._bodyRes;
|
|
14
|
+
var waitUntil = helpers.waitUntil;
|
|
15
|
+
|
|
16
|
+
// ---- shared negative-test helpers ----
|
|
17
|
+
|
|
18
|
+
function _expectPrefix(label, fn, prefix) {
|
|
19
|
+
var threw = null;
|
|
20
|
+
try { fn(); } catch (e) { threw = e; }
|
|
21
|
+
check(label, threw && (threw.code || "").indexOf(prefix) === 0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function _expectCode(label, fn, code) {
|
|
25
|
+
var threw = null;
|
|
26
|
+
try { fn(); } catch (e) { threw = e; }
|
|
27
|
+
check(label, threw && threw.code === code);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ---- fixtures ----
|
|
31
|
+
|
|
32
|
+
// A canonical RFC 8460 §4.4 aggregate report the parser accepts. Tests
|
|
33
|
+
// clone + mutate this to drive individual schema-rejection branches.
|
|
34
|
+
function _validReport() {
|
|
35
|
+
return {
|
|
36
|
+
"organization-name": "Reporter Inc",
|
|
37
|
+
"contact-info": "postmaster@reporter.example",
|
|
38
|
+
"report-id": "2026-07-11T00:00:00Z_example.com",
|
|
39
|
+
"date-range": {
|
|
40
|
+
"start-datetime": "2026-07-10T00:00:00Z",
|
|
41
|
+
"end-datetime": "2026-07-11T00:00:00Z",
|
|
42
|
+
},
|
|
43
|
+
"policies": [
|
|
44
|
+
{
|
|
45
|
+
"policy": {
|
|
46
|
+
"policy-type": "sts",
|
|
47
|
+
"policy-domain": "example.com",
|
|
48
|
+
"policy-string": ["version: STSv1", "mode: enforce"],
|
|
49
|
+
"mx-host": ["mx1.example.com"],
|
|
50
|
+
},
|
|
51
|
+
"summary": {
|
|
52
|
+
"total-successful-session-count": 100,
|
|
53
|
+
"total-failure-session-count": 2,
|
|
54
|
+
},
|
|
55
|
+
"failure-details": [
|
|
56
|
+
{ "result-type": "certificate-expired", "failed-session-count": 2 },
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _reportWithPolicies(policies) {
|
|
64
|
+
var r = _validReport();
|
|
65
|
+
r.policies = policies;
|
|
66
|
+
return r;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Mint a real RSA self-signed cert + matching key PEM via the vendored
|
|
70
|
+
// pki bundle (node:crypto exposes no cert generator). Lets the DANE
|
|
71
|
+
// generator exercise its real SPKI / full-DER hash path instead of only
|
|
72
|
+
// the input-validation guards.
|
|
73
|
+
async function _makeSelfSignedCert() {
|
|
74
|
+
var pki = require("../../lib/vendor/pki.cjs");
|
|
75
|
+
var x509 = pki.x509;
|
|
76
|
+
var keys = await nodeCrypto.webcrypto.subtle.generateKey(
|
|
77
|
+
{ name: "RSASSA-PKCS1-v1_5",
|
|
78
|
+
modulusLength: 2048,
|
|
79
|
+
publicExponent: new Uint8Array([1, 0, 1]),
|
|
80
|
+
hash: "SHA-256" },
|
|
81
|
+
true, ["sign", "verify"]);
|
|
82
|
+
var now = new Date();
|
|
83
|
+
var cert = await x509.X509CertificateGenerator.createSelfSigned({
|
|
84
|
+
serialNumber: "01",
|
|
85
|
+
name: "CN=mx1.example.com",
|
|
86
|
+
notBefore: now,
|
|
87
|
+
notAfter: new Date(now.getTime() + 7 * 86400000),
|
|
88
|
+
signingAlgorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
|
|
89
|
+
keys: keys,
|
|
90
|
+
});
|
|
91
|
+
return cert.toString("pem");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---- existing surface / happy-path coverage ----
|
|
13
95
|
|
|
14
96
|
function testSurface() {
|
|
15
|
-
check("b.mail.deploy.mtaStsPublish",
|
|
16
|
-
check("b.mail.deploy.danePublish",
|
|
17
|
-
check("b.mail.deploy.autoConfigXml",
|
|
18
|
-
check("b.mail.deploy.autoDiscoverXml",
|
|
97
|
+
check("b.mail.deploy.mtaStsPublish", typeof b.mail.deploy.mtaStsPublish === "function");
|
|
98
|
+
check("b.mail.deploy.danePublish", typeof b.mail.deploy.danePublish === "function");
|
|
99
|
+
check("b.mail.deploy.autoConfigXml", typeof b.mail.deploy.autoConfigXml === "function");
|
|
100
|
+
check("b.mail.deploy.autoDiscoverXml", typeof b.mail.deploy.autoDiscoverXml === "function");
|
|
101
|
+
check("b.mail.deploy.parseTlsRptReport", typeof b.mail.deploy.parseTlsRptReport === "function");
|
|
102
|
+
check("b.mail.deploy.tlsRptReportSchema", typeof b.mail.deploy.tlsRptReportSchema === "function");
|
|
103
|
+
check("b.mail.deploy.tlsRptIngestHttp", typeof b.mail.deploy.tlsRptIngestHttp === "function");
|
|
19
104
|
}
|
|
20
105
|
|
|
21
106
|
function testMtaStsHappy() {
|
|
@@ -38,20 +123,61 @@ function testMtaStsHappy() {
|
|
|
38
123
|
/^v=STSv1; id=[A-Za-z0-9_-]+;$/.test(rv.dnsTxtRecord));
|
|
39
124
|
}
|
|
40
125
|
|
|
126
|
+
// Operator-supplied policyId (valid token shape) is embedded verbatim
|
|
127
|
+
// rather than replaced by the ISO-timestamp default.
|
|
128
|
+
function testMtaStsExplicitPolicyId() {
|
|
129
|
+
var rv = b.mail.deploy.mtaStsPublish({
|
|
130
|
+
domain: "example.com",
|
|
131
|
+
mode: "testing",
|
|
132
|
+
mxHosts: ["mx1.example.com"],
|
|
133
|
+
maxAgeSec: 86400,
|
|
134
|
+
policyId: "policy-2026-07",
|
|
135
|
+
});
|
|
136
|
+
check("mta-sts honours explicit policyId", rv.policyId === "policy-2026-07");
|
|
137
|
+
check("mta-sts TXT record carries explicit id",
|
|
138
|
+
rv.dnsTxtRecord === "v=STSv1; id=policy-2026-07;");
|
|
139
|
+
}
|
|
140
|
+
|
|
41
141
|
function testMtaStsBadInput() {
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
142
|
+
_expectPrefix("refuses bad domain", function () { b.mail.deploy.mtaStsPublish({ domain: "", mode: "enforce", mxHosts: ["x.com"], maxAgeSec: 100 }); }, "mail-deploy/");
|
|
143
|
+
_expectPrefix("refuses bad mode", function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "fake", mxHosts: ["x.com"], maxAgeSec: 100 }); }, "mail-deploy/");
|
|
144
|
+
_expectPrefix("refuses empty mx list", function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: [], maxAgeSec: 100 }); }, "mail-deploy/");
|
|
145
|
+
_expectPrefix("refuses max-age > 1 year", function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["x.com"], maxAgeSec: 99999999 }); }, "mail-deploy/");
|
|
146
|
+
_expectPrefix("refuses CR in domain", function () { b.mail.deploy.mtaStsPublish({ domain: "x.com\r\nFAKE", mode: "enforce", mxHosts: ["x.com"], maxAgeSec: 100 }); }, "mail-deploy/");
|
|
147
|
+
_expectPrefix("refuses bad policyId", function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["x.com"], maxAgeSec: 100, policyId: "with space" }); }, "mail-deploy/");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// The mxHosts array + per-entry validation branches: non-array, cap,
|
|
151
|
+
// wrong element type, over-length entry, wildcard whose bare host is
|
|
152
|
+
// invalid, and a non-integer maxAgeSec.
|
|
153
|
+
function testMtaStsMxAndMaxAgeBranches() {
|
|
154
|
+
var big = [];
|
|
155
|
+
for (var i = 0; i < 65; i++) big.push("mx" + i + ".example.com");
|
|
156
|
+
_expectCode("refuses mxHosts over 64-entry cap",
|
|
157
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: big, maxAgeSec: 100 }); },
|
|
158
|
+
"mail-deploy/bad-mx");
|
|
159
|
+
_expectCode("refuses non-string mx entry",
|
|
160
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: [123], maxAgeSec: 100 }); },
|
|
161
|
+
"mail-deploy/bad-mx");
|
|
162
|
+
_expectCode("refuses over-length mx entry",
|
|
163
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["a".repeat(254)], maxAgeSec: 100 }); },
|
|
164
|
+
"mail-deploy/bad-mx");
|
|
165
|
+
_expectCode("refuses wildcard mx whose bare host is invalid",
|
|
166
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["*.bad\r\nhost.com"], maxAgeSec: 100 }); },
|
|
167
|
+
"mail-deploy/bad-mx");
|
|
168
|
+
_expectCode("refuses non-integer maxAgeSec",
|
|
169
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["mx.x.com"], maxAgeSec: 1.5 }); },
|
|
170
|
+
"mail-deploy/bad-max-age");
|
|
171
|
+
_expectCode("refuses negative maxAgeSec",
|
|
172
|
+
function () { b.mail.deploy.mtaStsPublish({ domain: "x.com", mode: "enforce", mxHosts: ["mx.x.com"], maxAgeSec: -1 }); },
|
|
173
|
+
"mail-deploy/bad-max-age");
|
|
174
|
+
_expectCode("refuses non-object opts",
|
|
175
|
+
function () { b.mail.deploy.mtaStsPublish("nope"); },
|
|
176
|
+
"mail-deploy/bad-opts");
|
|
53
177
|
}
|
|
54
178
|
|
|
179
|
+
// ---- DANE ----
|
|
180
|
+
|
|
55
181
|
function testAutoConfigHappy() {
|
|
56
182
|
var xml = b.mail.deploy.autoConfigXml({
|
|
57
183
|
domain: "example.com",
|
|
@@ -65,9 +191,20 @@ function testAutoConfigHappy() {
|
|
|
65
191
|
check("autoconfig carries displayName", xml.indexOf("<displayName>Example Mail</displayName>") !== -1);
|
|
66
192
|
}
|
|
67
193
|
|
|
194
|
+
// socketType "plain" + explicit username exercise the non-default
|
|
195
|
+
// socket-type and custom-username branches of the _server builder.
|
|
196
|
+
function testAutoConfigPlainSocketAndUsername() {
|
|
197
|
+
var xml = b.mail.deploy.autoConfigXml({
|
|
198
|
+
domain: "example.com",
|
|
199
|
+
imap: { host: "imap.example.com", port: 143, socketType: "plain", username: "alice" },
|
|
200
|
+
});
|
|
201
|
+
check("autoconfig honours socketType=plain",
|
|
202
|
+
xml.indexOf("<socketType>plain</socketType>") !== -1);
|
|
203
|
+
check("autoconfig embeds explicit username",
|
|
204
|
+
xml.indexOf("<username>alice</username>") !== -1);
|
|
205
|
+
}
|
|
206
|
+
|
|
68
207
|
function testAutoConfigEscape() {
|
|
69
|
-
// Operator-supplied displayName may carry XML metacharacters. Validate
|
|
70
|
-
// they get escaped, not echoed raw.
|
|
71
208
|
var xml = b.mail.deploy.autoConfigXml({
|
|
72
209
|
domain: "example.com",
|
|
73
210
|
displayName: "<bad>&\"'</bad>",
|
|
@@ -78,8 +215,6 @@ function testAutoConfigEscape() {
|
|
|
78
215
|
}
|
|
79
216
|
|
|
80
217
|
function testAutoConfigProtocolTypeAttr() {
|
|
81
|
-
// Per Mozilla config-v1.1 spec, `type` is the protocol (imap/pop3/smtp),
|
|
82
|
-
// not the direction. Regression for Codex P1.
|
|
83
218
|
var xml = b.mail.deploy.autoConfigXml({
|
|
84
219
|
domain: "example.com",
|
|
85
220
|
imap: { host: "imap.example.com", port: 993 },
|
|
@@ -95,7 +230,6 @@ function testAutoConfigProtocolTypeAttr() {
|
|
|
95
230
|
}
|
|
96
231
|
|
|
97
232
|
function testAutoConfigJmap() {
|
|
98
|
-
// Regression for Codex P2: JMAP-only configuration must be accepted.
|
|
99
233
|
var xml = b.mail.deploy.autoConfigXml({
|
|
100
234
|
domain: "example.com",
|
|
101
235
|
jmap: { url: "https://jmap.example.com/.well-known/jmap" },
|
|
@@ -104,27 +238,35 @@ function testAutoConfigJmap() {
|
|
|
104
238
|
xml.indexOf("<incomingServer type=\"jmap\">") !== -1);
|
|
105
239
|
check("autoconfig JMAP URL embedded",
|
|
106
240
|
xml.indexOf("<url>https://jmap.example.com/.well-known/jmap</url>") !== -1);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
b.mail.deploy.autoConfigXml({ domain: "x.com", jmap: { url: "bad\r\nurl" } });
|
|
111
|
-
} catch (e) { threw = e; }
|
|
112
|
-
check("autoconfig refuses CR/LF in jmap URL",
|
|
113
|
-
threw && threw.code === "mail-deploy/bad-jmap-url");
|
|
241
|
+
_expectCode("autoconfig refuses CR/LF in jmap URL",
|
|
242
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", jmap: { url: "bad\r\nurl" } }); },
|
|
243
|
+
"mail-deploy/bad-jmap-url");
|
|
114
244
|
}
|
|
115
245
|
|
|
116
246
|
function testAutoConfigBadInput() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
247
|
+
_expectPrefix("refuses no incoming server",
|
|
248
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com" }); }, "mail-deploy/");
|
|
249
|
+
_expectPrefix("refuses bad imap host",
|
|
250
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", imap: { host: "", port: 993 } }); }, "mail-deploy/");
|
|
251
|
+
_expectPrefix("refuses bad imap port",
|
|
252
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", imap: { host: "x.com", port: 99999 } }); }, "mail-deploy/");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Bad top-level domain, over-length displayName, and the two remaining
|
|
256
|
+
// jmap-url rejection shapes (empty string, over-length).
|
|
257
|
+
function testAutoConfigMoreBranches() {
|
|
258
|
+
_expectCode("autoconfig refuses bad top-level domain",
|
|
259
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "bad\r\ndomain", imap: { host: "x.com", port: 1 } }); },
|
|
260
|
+
"mail-deploy/bad-domain");
|
|
261
|
+
_expectCode("autoconfig refuses over-length displayName",
|
|
262
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", displayName: "d".repeat(257), imap: { host: "x.com", port: 1 } }); },
|
|
263
|
+
"mail-deploy/bad-displayName");
|
|
264
|
+
_expectCode("autoconfig refuses empty jmap url",
|
|
265
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", jmap: { url: "" } }); },
|
|
266
|
+
"mail-deploy/bad-jmap-url");
|
|
267
|
+
_expectCode("autoconfig refuses over-length jmap url",
|
|
268
|
+
function () { b.mail.deploy.autoConfigXml({ domain: "x.com", jmap: { url: "https://x/" + "a".repeat(1024) } }); },
|
|
269
|
+
"mail-deploy/bad-jmap-url");
|
|
128
270
|
}
|
|
129
271
|
|
|
130
272
|
function testAutoDiscoverHappy() {
|
|
@@ -133,12 +275,6 @@ function testAutoDiscoverHappy() {
|
|
|
133
275
|
imap: { host: "imap.example.com", port: 993, ssl: true },
|
|
134
276
|
smtp: { host: "smtp.example.com", port: 587, ssl: false },
|
|
135
277
|
});
|
|
136
|
-
// Match the full xmlns attribute value (anchored both sides) — using
|
|
137
|
-
// indexOf on the bare host alone trips CodeQL's `js/incomplete-url-
|
|
138
|
-
// substring-sanitization` query (false positive in a test assertion
|
|
139
|
-
// context, but the anchored shape is the right test anyway because
|
|
140
|
-
// we want to verify the canonical xmlns declaration, not just any
|
|
141
|
-
// mention of the string).
|
|
142
278
|
check("autodiscover declares Microsoft schema",
|
|
143
279
|
xml.indexOf("xmlns=\"http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006\"") !== -1);
|
|
144
280
|
check("autodiscover carries IMAP proto", xml.indexOf("<Type>IMAP</Type>") !== -1);
|
|
@@ -147,55 +283,468 @@ function testAutoDiscoverHappy() {
|
|
|
147
283
|
xml.indexOf("<SSL>on</SSL>") !== -1 && xml.indexOf("<SSL>off</SSL>") !== -1);
|
|
148
284
|
}
|
|
149
285
|
|
|
286
|
+
// POP3 protocol block + the per-proto host/port rejection branches, plus
|
|
287
|
+
// the email length/type guard (distinct from the control-byte scanner).
|
|
288
|
+
function testAutoDiscoverMoreBranches() {
|
|
289
|
+
var xml = b.mail.deploy.autoDiscoverXml({
|
|
290
|
+
email: "bob@example.com",
|
|
291
|
+
pop3: { host: "pop3.example.com", port: 995, ssl: true },
|
|
292
|
+
});
|
|
293
|
+
check("autodiscover emits POP3 proto block", xml.indexOf("<Type>POP3</Type>") !== -1);
|
|
294
|
+
|
|
295
|
+
_expectCode("autodiscover refuses missing email",
|
|
296
|
+
function () { b.mail.deploy.autoDiscoverXml({ imap: { host: "x.com", port: 1 } }); },
|
|
297
|
+
"mail-deploy/bad-email");
|
|
298
|
+
_expectCode("autodiscover refuses over-length email",
|
|
299
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "a".repeat(255) + "@x.com", imap: { host: "x.com", port: 1 } }); },
|
|
300
|
+
"mail-deploy/bad-email");
|
|
301
|
+
_expectCode("autodiscover refuses bad proto host",
|
|
302
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "a@x.com", imap: { host: "", port: 1 } }); },
|
|
303
|
+
"mail-deploy/bad-host");
|
|
304
|
+
_expectCode("autodiscover refuses bad proto port",
|
|
305
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "a@x.com", imap: { host: "x.com", port: 99999 } }); },
|
|
306
|
+
"mail-deploy/bad-port");
|
|
307
|
+
}
|
|
308
|
+
|
|
150
309
|
function testAutoDiscoverXmlInjection() {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
function () { b.mail.deploy.danePublish({ certPem: "
|
|
176
|
-
|
|
177
|
-
function () { b.mail.deploy.danePublish({ certPem: "", mxHost: "mx.x.com" }); });
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
function
|
|
310
|
+
_expectPrefix("refuses CR/LF in email",
|
|
311
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "alice@x.com\r\n<inject/>", imap: { host: "x.com", port: 1 } }); }, "mail-deploy/");
|
|
312
|
+
_expectPrefix("refuses NUL in email",
|
|
313
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "alice@x.com\x00", imap: { host: "x.com", port: 1 } }); }, "mail-deploy/");
|
|
314
|
+
_expectPrefix("refuses missing protos",
|
|
315
|
+
function () { b.mail.deploy.autoDiscoverXml({ email: "alice@x.com" }); }, "mail-deploy/");
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Input-validation guards that gate BEFORE the cert parse: too-large PEM,
|
|
319
|
+
// bad mxHost, out-of-range port, and each RFC 6698 code enum.
|
|
320
|
+
function testDanePublishInputGuards() {
|
|
321
|
+
_expectCode("danePublish refuses bad pem",
|
|
322
|
+
function () { b.mail.deploy.danePublish({ certPem: "not a pem", mxHost: "mx.x.com" }); }, "mail-deploy/bad-cert");
|
|
323
|
+
_expectCode("danePublish refuses empty pem",
|
|
324
|
+
function () { b.mail.deploy.danePublish({ certPem: "", mxHost: "mx.x.com" }); }, "mail-deploy/bad-cert");
|
|
325
|
+
_expectCode("danePublish refuses over-size pem",
|
|
326
|
+
function () { b.mail.deploy.danePublish({ certPem: "x".repeat(65537), mxHost: "mx.x.com" }); }, "mail-deploy/bad-cert");
|
|
327
|
+
_expectCode("danePublish refuses bad mxHost",
|
|
328
|
+
function () { b.mail.deploy.danePublish({ certPem: "x", mxHost: "bad\r\nhost" }); }, "mail-deploy/bad-mx-host");
|
|
329
|
+
_expectCode("danePublish refuses out-of-range port",
|
|
330
|
+
function () { b.mail.deploy.danePublish({ certPem: "x", mxHost: "mx.x.com", port: 70000 }); }, "mail-deploy/bad-port");
|
|
331
|
+
_expectCode("danePublish refuses bad usage",
|
|
332
|
+
function () { b.mail.deploy.danePublish({ certPem: "x", mxHost: "mx.x.com", usage: 7 }); }, "mail-deploy/bad-usage");
|
|
333
|
+
_expectCode("danePublish refuses bad selector",
|
|
334
|
+
function () { b.mail.deploy.danePublish({ certPem: "x", mxHost: "mx.x.com", selector: 5 }); }, "mail-deploy/bad-selector");
|
|
335
|
+
_expectCode("danePublish refuses bad matchType",
|
|
336
|
+
function () { b.mail.deploy.danePublish({ certPem: "x", mxHost: "mx.x.com", matchType: 0 }); }, "mail-deploy/bad-match-type");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Real-cert deep path — SPKI (selector 1) SHA-256 default AND full-DER
|
|
340
|
+
// (selector 0) SHA-512 with a non-default usage + port.
|
|
341
|
+
async function testDanePublishDeepHash() {
|
|
342
|
+
var certPem = await _makeSelfSignedCert();
|
|
343
|
+
var rv1 = b.mail.deploy.danePublish({ certPem: certPem, mxHost: "mx1.example.com" });
|
|
344
|
+
check("dane default record is DANE-EE / SPKI / SHA-256", /^3 1 1 [0-9a-f]{64}$/.test(rv1.record));
|
|
345
|
+
check("dane dnsName defaults to port 25", rv1.dnsName === "_25._tcp.mx1.example.com");
|
|
346
|
+
check("dane zoneLine composes name + TLSA record",
|
|
347
|
+
rv1.zoneLine === "_25._tcp.mx1.example.com. IN TLSA " + rv1.record);
|
|
348
|
+
|
|
349
|
+
var rv0 = b.mail.deploy.danePublish({
|
|
350
|
+
certPem: certPem, mxHost: "mx1.example.com",
|
|
351
|
+
selector: 0, matchType: 2, usage: 2, port: 465,
|
|
352
|
+
});
|
|
353
|
+
check("dane full-DER / SHA-512 record", /^2 0 2 [0-9a-f]{128}$/.test(rv0.record));
|
|
354
|
+
check("dane honours explicit port in dnsName", rv0.dnsName === "_465._tcp.mx1.example.com");
|
|
355
|
+
check("dane echoes usage/selector/matchType",
|
|
356
|
+
rv0.usage === 2 && rv0.selector === 0 && rv0.matchType === 2);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ---- TLS-RPT parser ----
|
|
360
|
+
|
|
361
|
+
function testTlsRptHappy() {
|
|
362
|
+
var rv = b.mail.deploy.parseTlsRptReport(JSON.stringify(_validReport()));
|
|
363
|
+
check("tlsrpt parse returns organization-name", rv["organization-name"] === "Reporter Inc");
|
|
364
|
+
check("tlsrpt parse sums session totals", rv.sessionTotals.success === 100 && rv.sessionTotals.failure === 2);
|
|
365
|
+
check("tlsrpt parse marks uncompressed", rv.wasCompressed === false);
|
|
366
|
+
check("tlsrpt parse preserves policies array", Array.isArray(rv.policies) && rv.policies.length === 1);
|
|
367
|
+
|
|
368
|
+
// Buffer input path + typed-error class identity.
|
|
369
|
+
var rvBuf = b.mail.deploy.parseTlsRptReport(Buffer.from(JSON.stringify(_validReport())));
|
|
370
|
+
check("tlsrpt parse accepts Buffer input", rvBuf["report-id"] === "2026-07-11T00:00:00Z_example.com");
|
|
371
|
+
|
|
372
|
+
var threw = null;
|
|
373
|
+
try { b.mail.deploy.parseTlsRptReport(42); } catch (e) { threw = e; }
|
|
374
|
+
check("tlsrpt bad-input throws TlsRptParseError",
|
|
375
|
+
threw instanceof b.mail.deploy.TlsRptParseError && threw.code === "mail-tlsrpt/bad-input");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function testTlsRptOptsAndSize() {
|
|
379
|
+
_expectCode("tlsrpt refuses bad opts (negative maxRatio)",
|
|
380
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_validReport()), { maxRatio: -1 }); },
|
|
381
|
+
"mail-tlsrpt/bad-opts");
|
|
382
|
+
_expectCode("tlsrpt refuses oversize compressed payload",
|
|
383
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_validReport()), { maxCompressedBytes: 4 }); },
|
|
384
|
+
"mail-tlsrpt/oversize-compressed");
|
|
385
|
+
_expectCode("tlsrpt refuses malformed JSON",
|
|
386
|
+
function () { b.mail.deploy.parseTlsRptReport("{not json"); },
|
|
387
|
+
"mail-tlsrpt/bad-json");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function testTlsRptGzipBranches() {
|
|
391
|
+
var gz = zlib.gzipSync(Buffer.from(JSON.stringify(_validReport())));
|
|
392
|
+
var rv = b.mail.deploy.parseTlsRptReport(gz, { contentType: "application/tlsrpt+gzip" });
|
|
393
|
+
check("tlsrpt gzip auto-detect marks compressed", rv.wasCompressed === true);
|
|
394
|
+
check("tlsrpt gzip decodes report body", rv["organization-name"] === "Reporter Inc");
|
|
395
|
+
|
|
396
|
+
var gzBig = zlib.gzipSync(Buffer.from("x".repeat(50000)));
|
|
397
|
+
_expectCode("tlsrpt refuses gunzip bomb (decompressed cap)",
|
|
398
|
+
function () { b.mail.deploy.parseTlsRptReport(gzBig, { maxDecompressedBytes: 100 }); },
|
|
399
|
+
"mail-tlsrpt/gunzip-bomb");
|
|
400
|
+
_expectCode("tlsrpt refuses ratio bomb",
|
|
401
|
+
function () { b.mail.deploy.parseTlsRptReport(gzBig, { maxRatio: 2 }); },
|
|
402
|
+
"mail-tlsrpt/ratio-bomb");
|
|
403
|
+
_expectCode("tlsrpt refuses malformed gzip",
|
|
404
|
+
function () { b.mail.deploy.parseTlsRptReport(Buffer.from([0x1f, 0x8b, 0x08, 0x00, 0xde, 0xad, 0xbe, 0xef])); },
|
|
405
|
+
"mail-tlsrpt/gunzip-failed");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function testTlsRptSchemaRejections() {
|
|
409
|
+
_expectCode("tlsrpt refuses non-object top level",
|
|
410
|
+
function () { b.mail.deploy.parseTlsRptReport("[]"); }, "mail-tlsrpt/bad-schema");
|
|
411
|
+
_expectCode("tlsrpt refuses missing organization-name",
|
|
412
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify({ "contact-info": "x", "report-id": "y", "date-range": { "start-datetime": "a", "end-datetime": "b" }, "policies": [] })); },
|
|
413
|
+
"mail-tlsrpt/bad-schema");
|
|
414
|
+
_expectCode("tlsrpt refuses missing contact-info", function () {
|
|
415
|
+
var r = _validReport(); delete r["contact-info"];
|
|
416
|
+
b.mail.deploy.parseTlsRptReport(JSON.stringify(r));
|
|
417
|
+
}, "mail-tlsrpt/bad-schema");
|
|
418
|
+
_expectCode("tlsrpt refuses missing report-id", function () {
|
|
419
|
+
var r = _validReport(); delete r["report-id"];
|
|
420
|
+
b.mail.deploy.parseTlsRptReport(JSON.stringify(r));
|
|
421
|
+
}, "mail-tlsrpt/bad-schema");
|
|
422
|
+
_expectCode("tlsrpt refuses malformed date-range", function () {
|
|
423
|
+
var r = _validReport(); r["date-range"] = { "start-datetime": "a" };
|
|
424
|
+
b.mail.deploy.parseTlsRptReport(JSON.stringify(r));
|
|
425
|
+
}, "mail-tlsrpt/bad-schema");
|
|
426
|
+
_expectCode("tlsrpt refuses non-array policies", function () {
|
|
427
|
+
var r = _validReport(); r.policies = { "policy-type": "sts" };
|
|
428
|
+
b.mail.deploy.parseTlsRptReport(JSON.stringify(r));
|
|
429
|
+
}, "mail-tlsrpt/bad-schema");
|
|
430
|
+
_expectCode("tlsrpt refuses empty policies array",
|
|
431
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([]))); },
|
|
432
|
+
"mail-tlsrpt/bad-schema");
|
|
433
|
+
|
|
434
|
+
var many = [];
|
|
435
|
+
for (var i = 0; i < 1001; i++) many.push({ policy: { "policy-type": "sts", "policy-domain": "e" + i + ".example" } });
|
|
436
|
+
_expectCode("tlsrpt refuses too many policies",
|
|
437
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies(many))); },
|
|
438
|
+
"mail-tlsrpt/too-many-policies");
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function testTlsRptPolicyRejections() {
|
|
442
|
+
_expectCode("tlsrpt refuses non-object policy entry",
|
|
443
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([null]))); },
|
|
444
|
+
"mail-tlsrpt/bad-policy");
|
|
445
|
+
_expectCode("tlsrpt refuses policy missing .policy",
|
|
446
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{}]))); },
|
|
447
|
+
"mail-tlsrpt/bad-policy");
|
|
448
|
+
// Prototype-shadowing: an inherited member name must NOT resolve as a
|
|
449
|
+
// valid policy-type through the plain-object allowlist.
|
|
450
|
+
_expectCode("tlsrpt refuses prototype-shadowed policy-type",
|
|
451
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "constructor", "policy-domain": "x" } }]))); },
|
|
452
|
+
"mail-tlsrpt/bad-policy");
|
|
453
|
+
_expectCode("tlsrpt refuses out-of-vocabulary policy-type",
|
|
454
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "made-up", "policy-domain": "x" } }]))); },
|
|
455
|
+
"mail-tlsrpt/bad-policy");
|
|
456
|
+
_expectCode("tlsrpt refuses policy missing policy-domain",
|
|
457
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "tlsa" } }]))); },
|
|
458
|
+
"mail-tlsrpt/bad-policy");
|
|
459
|
+
_expectCode("tlsrpt refuses non-integer success count",
|
|
460
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "sts", "policy-domain": "x" }, summary: { "total-successful-session-count": -5 } }]))); },
|
|
461
|
+
"mail-tlsrpt/bad-summary");
|
|
462
|
+
_expectCode("tlsrpt refuses non-integer failure count",
|
|
463
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "sts", "policy-domain": "x" }, summary: { "total-failure-session-count": "lots" } }]))); },
|
|
464
|
+
"mail-tlsrpt/bad-summary");
|
|
465
|
+
_expectCode("tlsrpt refuses non-array failure-details",
|
|
466
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "sts", "policy-domain": "x" }, "failure-details": {} }]))); },
|
|
467
|
+
"mail-tlsrpt/bad-policy");
|
|
468
|
+
_expectCode("tlsrpt refuses non-object failure-detail entry",
|
|
469
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "sts", "policy-domain": "x" }, "failure-details": [null] }]))); },
|
|
470
|
+
"mail-tlsrpt/bad-failure-detail");
|
|
471
|
+
|
|
472
|
+
// Per-policy failure-details cardinality cap (10000).
|
|
473
|
+
var fds = [];
|
|
474
|
+
for (var f = 0; f < 10001; f++) fds.push({ "result-type": "validation-failure" });
|
|
475
|
+
_expectCode("tlsrpt refuses over-cap failure-details",
|
|
476
|
+
function () { b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([{ policy: { "policy-type": "sts", "policy-domain": "x" }, "failure-details": fds }]))); },
|
|
477
|
+
"mail-tlsrpt/too-many-failures");
|
|
478
|
+
|
|
479
|
+
// Unknown result-type is tolerated (IANA registry can grow) — surfaced,
|
|
480
|
+
// not refused.
|
|
481
|
+
var rv = b.mail.deploy.parseTlsRptReport(JSON.stringify(_reportWithPolicies([
|
|
482
|
+
{ policy: { "policy-type": "no-policy-found", "policy-domain": "x" },
|
|
483
|
+
"failure-details": [{ "result-type": "future-iana-type" }] },
|
|
484
|
+
])));
|
|
485
|
+
check("tlsrpt tolerates unknown result-type", rv.policies.length === 1);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function testTlsRptSchemaDescriptor() {
|
|
489
|
+
var schema = b.mail.deploy.tlsRptReportSchema();
|
|
490
|
+
check("tlsrpt schema names RFC 8460 §4.4", schema.rfc === "RFC 8460 §4.4");
|
|
491
|
+
check("tlsrpt schema requires report-id", schema.required.indexOf("report-id") !== -1);
|
|
492
|
+
check("tlsrpt schema lists policy field descriptors", typeof schema.policyFields.policy === "object");
|
|
493
|
+
check("tlsrpt schema enumerates policy types", schema.policyTypes.indexOf("sts") !== -1);
|
|
494
|
+
check("tlsrpt schema enumerates result types", schema.resultTypes.indexOf("certificate-expired") !== -1);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ---- TLS-RPT HTTP ingest handler ----
|
|
498
|
+
|
|
499
|
+
var _CT_JSON = "application/tlsrpt+json";
|
|
500
|
+
|
|
501
|
+
// Drive a handler with a mock req/res pair and resolve once the response
|
|
502
|
+
// has been written. Polls res.statusCode rather than sleeping.
|
|
503
|
+
function _driveIngest(handler, req, res) {
|
|
504
|
+
handler(req, res);
|
|
505
|
+
return waitUntil(function () { return res.statusCode !== null; }, {
|
|
506
|
+
timeoutMs: 4000,
|
|
507
|
+
label: "tlsRptIngestHttp: response written",
|
|
508
|
+
}).then(function () { return res; });
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// An onRefuse hook that records the code then throws — every refusal
|
|
512
|
+
// path wraps the operator hook in try/catch and must stay drop-silent
|
|
513
|
+
// (a buggy hook must not change the response the peer receives).
|
|
514
|
+
function _throwingRefuse(sink) {
|
|
515
|
+
return function (code) { sink.push(code); throw new Error("onRefuse hook bug"); };
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function testTlsRptIngestOptsValidation() {
|
|
519
|
+
_expectCode("ingest refuses non-function authenticate",
|
|
520
|
+
function () { b.mail.deploy.tlsRptIngestHttp({ authenticate: 5 }); }, "mail-tlsrpt/bad-opts");
|
|
521
|
+
_expectCode("ingest refuses non-string trustedReporters entry",
|
|
522
|
+
function () { b.mail.deploy.tlsRptIngestHttp({ trustedReporters: [5] }); }, "mail-tlsrpt/bad-opts");
|
|
523
|
+
_expectCode("ingest refuses non-integer maxCompressedBytes",
|
|
524
|
+
function () { b.mail.deploy.tlsRptIngestHttp({ maxCompressedBytes: -1 }); }, "mail-tlsrpt/bad-opts");
|
|
525
|
+
// Zero-arg construction defaults opts to {} and returns a usable handler.
|
|
526
|
+
check("ingest builds a handler with no opts",
|
|
527
|
+
typeof b.mail.deploy.tlsRptIngestHttp() === "function");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async function testTlsRptIngestMethodAndContentType() {
|
|
531
|
+
var refusals = [];
|
|
532
|
+
// A deliberately-throwing hook: the 415 refusal must still be written.
|
|
533
|
+
var handler = b.mail.deploy.tlsRptIngestHttp({ onRefuse: _throwingRefuse(refusals) });
|
|
534
|
+
|
|
535
|
+
var res405 = await _driveIngest(handler, _bodyReq("GET", { "content-type": _CT_JSON }, ""), _bodyRes());
|
|
536
|
+
check("ingest non-POST returns 405", res405.statusCode === 405);
|
|
537
|
+
check("ingest 405 advertises Allow: POST", res405._headers.Allow === "POST");
|
|
538
|
+
|
|
539
|
+
var res415 = await _driveIngest(handler, _bodyReq("POST", { "content-type": "text/plain" }, "x"), _bodyRes());
|
|
540
|
+
check("ingest bad content-type returns 415 despite throwing onRefuse", res415.statusCode === 415);
|
|
541
|
+
check("ingest 415 advertises Accept media types",
|
|
542
|
+
(res415._headers.Accept || "").indexOf("application/tlsrpt+json") !== -1);
|
|
543
|
+
check("ingest 415 fires onRefuse with typed code",
|
|
544
|
+
refusals.indexOf("mail-tlsrpt/bad-content-type") !== -1);
|
|
545
|
+
|
|
546
|
+
// A POST with NO content-type header falls into the same 415 path (the
|
|
547
|
+
// header defaults to "").
|
|
548
|
+
var resNoCt = await _driveIngest(handler, _bodyReq("POST", {}, "x"), _bodyRes());
|
|
549
|
+
check("ingest missing content-type returns 415", resNoCt.statusCode === 415);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
async function testTlsRptIngestAuthBoundary() {
|
|
553
|
+
var refusals = [];
|
|
554
|
+
var res401 = await _driveIngest(
|
|
555
|
+
b.mail.deploy.tlsRptIngestHttp({
|
|
556
|
+
authenticate: function () { return false; },
|
|
557
|
+
onRefuse: _throwingRefuse(refusals),
|
|
558
|
+
}),
|
|
559
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
560
|
+
check("ingest falsy authenticate returns 401", res401.statusCode === 401);
|
|
561
|
+
check("ingest 401 carries unauthenticated Error-Type",
|
|
562
|
+
res401._headers["Error-Type"] === "mail-tlsrpt/unauthenticated");
|
|
563
|
+
check("ingest 401 fires onRefuse with unauthenticated code",
|
|
564
|
+
refusals.indexOf("mail-tlsrpt/unauthenticated") !== -1);
|
|
565
|
+
|
|
566
|
+
var res500 = await _driveIngest(
|
|
567
|
+
b.mail.deploy.tlsRptIngestHttp({
|
|
568
|
+
authenticate: function () { throw new Error("auth backend down"); },
|
|
569
|
+
onRefuse: _throwingRefuse(refusals),
|
|
570
|
+
}),
|
|
571
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
572
|
+
check("ingest throwing authenticate returns 500", res500.statusCode === 500);
|
|
573
|
+
check("ingest 500 carries auth-error Error-Type",
|
|
574
|
+
res500._headers["Error-Type"] === "mail-tlsrpt/auth-error");
|
|
575
|
+
check("ingest 500 fires onRefuse with auth-error code",
|
|
576
|
+
refusals.indexOf("mail-tlsrpt/auth-error") !== -1);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
async function testTlsRptIngestAcceptPaths() {
|
|
580
|
+
var audits = [];
|
|
581
|
+
var fakeAudit = { safeEmit: function (e) { audits.push(e); } };
|
|
582
|
+
|
|
583
|
+
// authenticate true + sync onAccept → 201
|
|
584
|
+
var accepted = [];
|
|
585
|
+
var res201 = await _driveIngest(
|
|
586
|
+
b.mail.deploy.tlsRptIngestHttp({
|
|
587
|
+
audit: fakeAudit,
|
|
588
|
+
authenticate: function () { return true; },
|
|
589
|
+
onAccept: function (report) { accepted.push(report["report-id"]); },
|
|
590
|
+
}),
|
|
591
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
592
|
+
check("ingest authenticated + accepted returns 201", res201.statusCode === 201);
|
|
593
|
+
check("ingest passes parsed report to onAccept",
|
|
594
|
+
accepted[0] === "2026-07-11T00:00:00Z_example.com");
|
|
595
|
+
check("ingest emits a success audit event",
|
|
596
|
+
audits.some(function (e) { return e.outcome === "success"; }));
|
|
597
|
+
|
|
598
|
+
// async onAccept resolved → 201
|
|
599
|
+
var resAsync = await _driveIngest(
|
|
600
|
+
b.mail.deploy.tlsRptIngestHttp({ onAccept: function () { return Promise.resolve(); } }),
|
|
601
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
602
|
+
check("ingest async onAccept resolve returns 201", resAsync.statusCode === 201);
|
|
603
|
+
|
|
604
|
+
// async onAccept rejected → 500
|
|
605
|
+
var resReject = await _driveIngest(
|
|
606
|
+
b.mail.deploy.tlsRptIngestHttp({ onAccept: function () { return Promise.reject(new Error("store down")); } }),
|
|
607
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
608
|
+
check("ingest async onAccept reject returns 500", resReject.statusCode === 500);
|
|
609
|
+
|
|
610
|
+
// sync onAccept throw → best-effort, still 201
|
|
611
|
+
var resThrow = await _driveIngest(
|
|
612
|
+
b.mail.deploy.tlsRptIngestHttp({ onAccept: function () { throw new Error("hook bug"); } }),
|
|
613
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
614
|
+
check("ingest sync onAccept throw still returns 201", resThrow.statusCode === 201);
|
|
615
|
+
|
|
616
|
+
// no onAccept configured → 201 (uses the framework's default audit, not
|
|
617
|
+
// an injected handle — exercises the fallback branch of _safeAuditEmit)
|
|
618
|
+
var resNoHook = await _driveIngest(
|
|
619
|
+
b.mail.deploy.tlsRptIngestHttp({}),
|
|
620
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
621
|
+
check("ingest without onAccept returns 201", resNoHook.statusCode === 201);
|
|
622
|
+
|
|
623
|
+
// A throwing audit handle must not block ingest — _safeAuditEmit is
|
|
624
|
+
// drop-silent by design.
|
|
625
|
+
var resAuditThrows = await _driveIngest(
|
|
626
|
+
b.mail.deploy.tlsRptIngestHttp({ audit: { safeEmit: function () { throw new Error("audit sink down"); } } }),
|
|
627
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
628
|
+
check("ingest survives a throwing audit sink", resAuditThrows.statusCode === 201);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
async function testTlsRptIngestRefusalStatuses() {
|
|
632
|
+
var refusals = [];
|
|
633
|
+
var onRefuse = _throwingRefuse(refusals);
|
|
634
|
+
|
|
635
|
+
// parse failure → 400 with Error-Type
|
|
636
|
+
var res400 = await _driveIngest(
|
|
637
|
+
b.mail.deploy.tlsRptIngestHttp({ onRefuse: onRefuse }),
|
|
638
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, "{not json"), _bodyRes());
|
|
639
|
+
check("ingest parse failure returns 400", res400.statusCode === 400);
|
|
640
|
+
check("ingest 400 carries the parser's Error-Type",
|
|
641
|
+
res400._headers["Error-Type"] === "mail-tlsrpt/bad-json");
|
|
642
|
+
check("ingest 400 fires onRefuse with parser code",
|
|
643
|
+
refusals.indexOf("mail-tlsrpt/bad-json") !== -1);
|
|
644
|
+
|
|
645
|
+
// gunzip bomb via the handler → 413
|
|
646
|
+
var gzBig = zlib.gzipSync(Buffer.from("x".repeat(50000)));
|
|
647
|
+
var res413 = await _driveIngest(
|
|
648
|
+
b.mail.deploy.tlsRptIngestHttp({ maxDecompressedBytes: 100 }),
|
|
649
|
+
_bodyReq("POST", { "content-type": "application/tlsrpt+gzip" }, gzBig), _bodyRes());
|
|
650
|
+
check("ingest gunzip bomb returns 413", res413.statusCode === 413);
|
|
651
|
+
check("ingest 413 carries gunzip-bomb Error-Type",
|
|
652
|
+
res413._headers["Error-Type"] === "mail-tlsrpt/gunzip-bomb");
|
|
653
|
+
|
|
654
|
+
// ratio bomb via the handler → 413 (distinct status-map branch)
|
|
655
|
+
var resRatio = await _driveIngest(
|
|
656
|
+
b.mail.deploy.tlsRptIngestHttp({ maxRatio: 2 }),
|
|
657
|
+
_bodyReq("POST", { "content-type": "application/tlsrpt+gzip" }, gzBig), _bodyRes());
|
|
658
|
+
check("ingest ratio bomb returns 413", resRatio.statusCode === 413);
|
|
659
|
+
check("ingest 413 carries ratio-bomb Error-Type",
|
|
660
|
+
resRatio._headers["Error-Type"] === "mail-tlsrpt/ratio-bomb");
|
|
661
|
+
|
|
662
|
+
// oversize compressed body (collector cap) → 413
|
|
663
|
+
var resOversize = await _driveIngest(
|
|
664
|
+
b.mail.deploy.tlsRptIngestHttp({ maxCompressedBytes: 16, onRefuse: onRefuse }),
|
|
665
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, "y".repeat(500)), _bodyRes());
|
|
666
|
+
check("ingest oversize body returns 413", resOversize.statusCode === 413);
|
|
667
|
+
check("ingest oversize body fires onRefuse",
|
|
668
|
+
refusals.indexOf("mail-tlsrpt/oversize-compressed") !== -1);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
async function testTlsRptIngestTrustedReporters() {
|
|
672
|
+
// Advisory content filter: report.organization-name not in the
|
|
673
|
+
// allowlist → 403.
|
|
674
|
+
var refusals = [];
|
|
675
|
+
var res403 = await _driveIngest(
|
|
676
|
+
b.mail.deploy.tlsRptIngestHttp({ trustedReporters: ["Other Org"], onRefuse: _throwingRefuse(refusals) }),
|
|
677
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
678
|
+
check("ingest untrusted reporter returns 403", res403.statusCode === 403);
|
|
679
|
+
check("ingest 403 carries untrusted-reporter Error-Type",
|
|
680
|
+
res403._headers["Error-Type"] === "mail-tlsrpt/untrusted-reporter");
|
|
681
|
+
check("ingest 403 fires onRefuse with untrusted-reporter code",
|
|
682
|
+
refusals.indexOf("mail-tlsrpt/untrusted-reporter") !== -1);
|
|
683
|
+
|
|
684
|
+
// matching reporter → 201
|
|
685
|
+
var res201 = await _driveIngest(
|
|
686
|
+
b.mail.deploy.tlsRptIngestHttp({ trustedReporters: ["Reporter Inc"] }),
|
|
687
|
+
_bodyReq("POST", { "content-type": _CT_JSON }, JSON.stringify(_validReport())), _bodyRes());
|
|
688
|
+
check("ingest trusted reporter returns 201", res201.statusCode === 201);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
async function testTlsRptIngestRequestError() {
|
|
692
|
+
var req = new EventEmitter();
|
|
693
|
+
req.method = "POST";
|
|
694
|
+
req.headers = { "content-type": _CT_JSON };
|
|
695
|
+
req.socket = { remoteAddress: "127.0.0.1" };
|
|
696
|
+
req.destroy = function () { /* mock */ };
|
|
697
|
+
var res = _bodyRes();
|
|
698
|
+
b.mail.deploy.tlsRptIngestHttp({})(req, res);
|
|
699
|
+
// Emit a stream error after listeners attach (handler registers them
|
|
700
|
+
// synchronously since no authenticate hook is configured).
|
|
701
|
+
setImmediate(function () { req.emit("error", new Error("connection reset")); });
|
|
702
|
+
await waitUntil(function () { return res.statusCode !== null; }, {
|
|
703
|
+
timeoutMs: 4000, label: "tlsRptIngestHttp: req-error response",
|
|
704
|
+
});
|
|
705
|
+
check("ingest request-stream error returns 400", res.statusCode === 400);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async function run() {
|
|
183
709
|
testSurface();
|
|
184
710
|
testMtaStsHappy();
|
|
711
|
+
testMtaStsExplicitPolicyId();
|
|
185
712
|
testMtaStsBadInput();
|
|
713
|
+
testMtaStsMxAndMaxAgeBranches();
|
|
186
714
|
testAutoConfigHappy();
|
|
715
|
+
testAutoConfigPlainSocketAndUsername();
|
|
187
716
|
testAutoConfigEscape();
|
|
188
717
|
testAutoConfigProtocolTypeAttr();
|
|
189
718
|
testAutoConfigJmap();
|
|
190
719
|
testAutoConfigBadInput();
|
|
720
|
+
testAutoConfigMoreBranches();
|
|
191
721
|
testAutoDiscoverHappy();
|
|
722
|
+
testAutoDiscoverMoreBranches();
|
|
192
723
|
testAutoDiscoverXmlInjection();
|
|
193
|
-
|
|
724
|
+
testDanePublishInputGuards();
|
|
725
|
+
await testDanePublishDeepHash();
|
|
726
|
+
testTlsRptHappy();
|
|
727
|
+
testTlsRptOptsAndSize();
|
|
728
|
+
testTlsRptGzipBranches();
|
|
729
|
+
testTlsRptSchemaRejections();
|
|
730
|
+
testTlsRptPolicyRejections();
|
|
731
|
+
testTlsRptSchemaDescriptor();
|
|
732
|
+
testTlsRptIngestOptsValidation();
|
|
733
|
+
await testTlsRptIngestMethodAndContentType();
|
|
734
|
+
await testTlsRptIngestAuthBoundary();
|
|
735
|
+
await testTlsRptIngestAcceptPaths();
|
|
736
|
+
await testTlsRptIngestRefusalStatuses();
|
|
737
|
+
await testTlsRptIngestTrustedReporters();
|
|
738
|
+
await testTlsRptIngestRequestError();
|
|
194
739
|
}
|
|
195
740
|
|
|
196
741
|
module.exports = { run: run };
|
|
197
742
|
|
|
198
743
|
if (require.main === module) {
|
|
199
|
-
|
|
200
|
-
|
|
744
|
+
run().then(function () {
|
|
745
|
+
console.log("OK — mail-deploy " + helpers.getChecks() + " checks passed");
|
|
746
|
+
}).catch(function (e) {
|
|
747
|
+
process.stderr.write("FAIL: " + (e && e.stack || e) + "\n");
|
|
748
|
+
process.exit(1);
|
|
749
|
+
});
|
|
201
750
|
}
|