@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
|
@@ -14,6 +14,16 @@ var check = require("../helpers/check").check;
|
|
|
14
14
|
var http = require("http");
|
|
15
15
|
var net = require("net");
|
|
16
16
|
var crypto = require("crypto");
|
|
17
|
+
var zlib = require("zlib");
|
|
18
|
+
|
|
19
|
+
// RFC 6455 §1.3 accept-key GUID + the frame serializer, reused by the raw
|
|
20
|
+
// fixture servers below to hand-craft handshake responses and adversarial
|
|
21
|
+
// frames the client must reject.
|
|
22
|
+
var WS_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
23
|
+
var wsFrame = b.websocket;
|
|
24
|
+
function _acceptFor(key) {
|
|
25
|
+
return crypto.createHash("sha1").update(key + WS_ACCEPT_GUID).digest("base64");
|
|
26
|
+
}
|
|
17
27
|
|
|
18
28
|
function rejects(label, fn, pattern) {
|
|
19
29
|
var threw = false; var msg = "";
|
|
@@ -158,6 +168,71 @@ function _makeServer(opts) {
|
|
|
158
168
|
});
|
|
159
169
|
}
|
|
160
170
|
|
|
171
|
+
// HTTP-upgrade fixture that writes a correct (or, via respOpts.tamperKey, a
|
|
172
|
+
// deliberately wrong) 101 handshake — optionally advertising an extension /
|
|
173
|
+
// subprotocol — then hands the raw socket to `afterHandshake(socket, req)` so a
|
|
174
|
+
// scenario can push hand-crafted server->client frames.
|
|
175
|
+
function _makeFrameServer(afterHandshake, respOpts) {
|
|
176
|
+
respOpts = respOpts || {};
|
|
177
|
+
var server = http.createServer(function (req, res) { res.writeHead(404); res.end(); });
|
|
178
|
+
server._wsSockets = [];
|
|
179
|
+
server.on("upgrade", function (req, socket) {
|
|
180
|
+
server._wsSockets.push(socket);
|
|
181
|
+
socket.on("error", function () { /* drop-silent */ });
|
|
182
|
+
var key = req.headers["sec-websocket-key"];
|
|
183
|
+
var lines = [
|
|
184
|
+
"HTTP/1.1 101 Switching Protocols",
|
|
185
|
+
"Upgrade: websocket",
|
|
186
|
+
"Connection: Upgrade",
|
|
187
|
+
"Sec-WebSocket-Accept: " + _acceptFor(respOpts.tamperKey ? "wrong" : key),
|
|
188
|
+
];
|
|
189
|
+
if (respOpts.extensions) lines.push("Sec-WebSocket-Extensions: " + respOpts.extensions);
|
|
190
|
+
if (respOpts.subprotocol) lines.push("Sec-WebSocket-Protocol: " + respOpts.subprotocol);
|
|
191
|
+
lines.push(""); lines.push("");
|
|
192
|
+
socket.write(lines.join("\r\n"));
|
|
193
|
+
if (typeof afterHandshake === "function") afterHandshake(socket, req);
|
|
194
|
+
});
|
|
195
|
+
return new Promise(function (resolve) {
|
|
196
|
+
server.listen(0, "127.0.0.1", function () { resolve(_trackServer(server)); });
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Raw TCP fixture that replies to the client's HTTP upgrade request with
|
|
201
|
+
// operator-supplied bytes — used to feed malformed handshake responses (bad
|
|
202
|
+
// status line / oversized header / missing Upgrade) that _makeFrameServer
|
|
203
|
+
// (which always writes a valid 101) cannot express.
|
|
204
|
+
function _makeRawResponder(responseBytes) {
|
|
205
|
+
var server = net.createServer(function (socket) {
|
|
206
|
+
server._wsSockets.push(socket);
|
|
207
|
+
socket.on("error", function () { /* drop-silent */ });
|
|
208
|
+
socket.once("data", function () { socket.write(responseBytes); });
|
|
209
|
+
});
|
|
210
|
+
server._wsSockets = [];
|
|
211
|
+
return new Promise(function (resolve) {
|
|
212
|
+
server.listen(0, "127.0.0.1", function () { resolve(_trackServer(server)); });
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Drive one adversarial-frame scenario: stand up a frame server whose
|
|
217
|
+
// afterHandshake pushes the crafted frame(s), dial it, and assert the client
|
|
218
|
+
// surfaces `expectedCode` on 'error'. connOpts.client overrides connect opts;
|
|
219
|
+
// connOpts.respOpts overrides the handshake response.
|
|
220
|
+
async function _expectFrameError(afterHandshake, connOpts, expectedCode, label) {
|
|
221
|
+
connOpts = connOpts || {};
|
|
222
|
+
var server = await _makeFrameServer(afterHandshake, connOpts.respOpts);
|
|
223
|
+
var port = server.address().port;
|
|
224
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", Object.assign(
|
|
225
|
+
{ reconnect: false, audit: false, allowInternal: true }, connOpts.client || {}));
|
|
226
|
+
var err = null;
|
|
227
|
+
c.on("error", function (e) { if (!err) err = e; });
|
|
228
|
+
await helpers.waitUntil(function () { return err !== null; },
|
|
229
|
+
{ timeoutMs: 5000, label: "ws-client: " + label });
|
|
230
|
+
check(label, err && err.code === expectedCode);
|
|
231
|
+
try { c.close(); } catch (_e) { /* already torn down */ }
|
|
232
|
+
await _sleep(30);
|
|
233
|
+
server.close();
|
|
234
|
+
}
|
|
235
|
+
|
|
161
236
|
async function run() {
|
|
162
237
|
try {
|
|
163
238
|
await _runTests();
|
|
@@ -540,9 +615,563 @@ async function _runTests() {
|
|
|
540
615
|
check("urlFor swap did not surface an unhandled rejection", sawUnhandled === null);
|
|
541
616
|
process.removeListener("unhandledRejection", _onUnhandled);
|
|
542
617
|
|
|
618
|
+
// ---- error / adversarial / defensive / option-default branch coverage ----
|
|
619
|
+
_testExtraConfigValidation();
|
|
620
|
+
await _testTlsOptsForOverride();
|
|
621
|
+
await _testLocalhostPinnedLookup();
|
|
622
|
+
await _testAuditPaths();
|
|
623
|
+
await _testPingNotOpenAndCloseTruncation();
|
|
624
|
+
await _testHeadersAndOrigin();
|
|
625
|
+
await _testMalformedHandshakes();
|
|
626
|
+
await _testAdversarialFrames();
|
|
627
|
+
await _testServerPingElicitsPong();
|
|
628
|
+
await _testDeflate();
|
|
629
|
+
await _testJsonAndCustomParser();
|
|
630
|
+
await _testHeartbeat();
|
|
631
|
+
await _testCancelPendingReconnect();
|
|
632
|
+
await _testOptionDefaultBranches();
|
|
633
|
+
await _testPostCloseSocketErrorSwallowed();
|
|
634
|
+
await _testWssDialReachesTlsHandshake();
|
|
635
|
+
await _testWssDialIpv6LiteralOmitsSni();
|
|
636
|
+
|
|
543
637
|
console.log("OK — ws-client tests");
|
|
544
638
|
}
|
|
545
639
|
|
|
640
|
+
// urlFor / tlsOptsFor must be functions when present — rejected at config time.
|
|
641
|
+
function _testExtraConfigValidation() {
|
|
642
|
+
rejects("connect: urlFor must be a function",
|
|
643
|
+
function () { b.wsClient.connect("ws://localhost:1", { urlFor: 42 }); },
|
|
644
|
+
/urlFor must be a function/);
|
|
645
|
+
rejects("connect: tlsOptsFor must be a function",
|
|
646
|
+
function () { b.wsClient.connect("ws://localhost:1", { tlsOptsFor: "nope" }); },
|
|
647
|
+
/tlsOptsFor must be a function/);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// tlsOptsFor(attempt) returning an object is merged over tlsOpts in
|
|
651
|
+
// _prepareDial. On a ws:// dial the merged TLS material is unused, but the
|
|
652
|
+
// merge branch must run every dial without breaking the connection.
|
|
653
|
+
async function _testTlsOptsForOverride() {
|
|
654
|
+
var server = await _makeServer({});
|
|
655
|
+
var port = server.address().port;
|
|
656
|
+
var called = 0;
|
|
657
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", {
|
|
658
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
659
|
+
tlsOpts: { minVersion: "TLSv1.3" },
|
|
660
|
+
tlsOptsFor: function () { called += 1; return { servername: "override.example" }; },
|
|
661
|
+
});
|
|
662
|
+
var opened = false, errSeen = null;
|
|
663
|
+
c.on("open", function () { opened = true; });
|
|
664
|
+
c.on("error", function (e) { errSeen = e; });
|
|
665
|
+
await helpers.waitUntil(function () { return opened || errSeen; },
|
|
666
|
+
{ timeoutMs: 5000, label: "ws-client: tlsOptsFor override dial resolves" });
|
|
667
|
+
check("tlsOptsFor: per-dial override merged, ws:// dial still opens",
|
|
668
|
+
opened === true && errSeen === null && called >= 1);
|
|
669
|
+
c.close();
|
|
670
|
+
await _sleep(30);
|
|
671
|
+
server.close();
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Dial via a HOSTNAME so the SSRF-pinned custom lookup is actually invoked (an
|
|
675
|
+
// IP-literal host lets Node skip DNS, leaving the pinned-lookup branch dead).
|
|
676
|
+
// The fixture binds the unspecified address so whichever loopback the pin
|
|
677
|
+
// resolves (::1 / 127.0.0.1) is reachable.
|
|
678
|
+
async function _testLocalhostPinnedLookup() {
|
|
679
|
+
var server = http.createServer(function (req, res) { res.writeHead(404); res.end(); });
|
|
680
|
+
server._wsSockets = [];
|
|
681
|
+
server.on("upgrade", function (req, socket) {
|
|
682
|
+
server._wsSockets.push(socket);
|
|
683
|
+
socket.on("error", function () { /* drop-silent */ });
|
|
684
|
+
socket.write([
|
|
685
|
+
"HTTP/1.1 101 Switching Protocols", "Upgrade: websocket", "Connection: Upgrade",
|
|
686
|
+
"Sec-WebSocket-Accept: " + _acceptFor(req.headers["sec-websocket-key"]), "", "",
|
|
687
|
+
].join("\r\n"));
|
|
688
|
+
});
|
|
689
|
+
await new Promise(function (r) { server.listen(0, r); }); // no host → dual-stack loopback
|
|
690
|
+
_trackServer(server);
|
|
691
|
+
var port = server.address().port;
|
|
692
|
+
var c = _trackedConnect("ws://localhost:" + port + "/", {
|
|
693
|
+
reconnect: false, audit: false, allowInternal: true, handshakeTimeoutMs: 4000,
|
|
694
|
+
});
|
|
695
|
+
var opened = false, errSeen = null;
|
|
696
|
+
c.on("open", function () { opened = true; });
|
|
697
|
+
c.on("error", function (e) { if (!errSeen) errSeen = e; });
|
|
698
|
+
await helpers.waitUntil(function () { return opened || errSeen; },
|
|
699
|
+
{ timeoutMs: 6000, label: "ws-client: localhost pinned-lookup dial resolves" });
|
|
700
|
+
check("pinned-lookup: hostname dial connects through the SSRF-pinned lookup",
|
|
701
|
+
opened === true && errSeen === null);
|
|
702
|
+
c.close();
|
|
703
|
+
await _sleep(30);
|
|
704
|
+
server.close();
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// audit ON (the default) exercises the connect / close / error audit metadata
|
|
708
|
+
// builders — including _captureCertFingerprint on a non-TLS socket (returns
|
|
709
|
+
// null when getPeerCertificate is absent).
|
|
710
|
+
async function _testAuditPaths() {
|
|
711
|
+
var server = await _makeServer({}); // echoes frames; echoes + ends on close
|
|
712
|
+
var port = server.address().port;
|
|
713
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", { reconnect: false, allowInternal: true });
|
|
714
|
+
var opened = false, closed = false;
|
|
715
|
+
c.on("open", function () { opened = true; });
|
|
716
|
+
c.on("close", function () { closed = true; });
|
|
717
|
+
await helpers.waitUntil(function () { return opened; },
|
|
718
|
+
{ timeoutMs: 5000, label: "ws-client: audit-on connect opens" });
|
|
719
|
+
check("audit-on: connect built connect-audit metadata (opened)", opened === true);
|
|
720
|
+
c.close(1000, "bye");
|
|
721
|
+
await helpers.waitUntil(function () { return closed; },
|
|
722
|
+
{ timeoutMs: 5000, label: "ws-client: audit-on close emits" });
|
|
723
|
+
check("audit-on: close built close-audit metadata (closed)", closed === true);
|
|
724
|
+
server.close();
|
|
725
|
+
|
|
726
|
+
var server2 = await _makeServer({ tamperKey: true }); // accept-mismatch, audit on
|
|
727
|
+
var port2 = server2.address().port;
|
|
728
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + port2 + "/", { reconnect: false, allowInternal: true });
|
|
729
|
+
var err2 = null;
|
|
730
|
+
c2.on("error", function (e) { err2 = e; });
|
|
731
|
+
await helpers.waitUntil(function () { return err2 !== null; },
|
|
732
|
+
{ timeoutMs: 5000, label: "ws-client: audit-on error emits" });
|
|
733
|
+
check("audit-on: error path built error-audit metadata", err2 && err2.code === "ws-client/accept-mismatch");
|
|
734
|
+
server2.close();
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// ping() before open is a no-op; close() with a >123-byte reason ending
|
|
738
|
+
// mid-codepoint truncates to a code-point boundary without throwing.
|
|
739
|
+
async function _testPingNotOpenAndCloseTruncation() {
|
|
740
|
+
var server = await _makeServer({});
|
|
741
|
+
var port = server.address().port;
|
|
742
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
743
|
+
c.ping(Buffer.from("early")); // readyState "connecting" → no-op, no throw
|
|
744
|
+
check("ping: no-op before open (readyState not yet open)", c.readyState !== "open");
|
|
745
|
+
await helpers.waitUntil(function () { return c.readyState === "open"; },
|
|
746
|
+
{ timeoutMs: 5000, label: "ws-client: ping/close-trunc client opens" });
|
|
747
|
+
// 122 ASCII bytes + one 3-byte '€' = 125 bytes > 123; the 123-byte cut lands
|
|
748
|
+
// mid-'€', forcing the byte-boundary back-off loop.
|
|
749
|
+
c.close(1000, "x".repeat(122) + "€");
|
|
750
|
+
check("close: mid-codepoint reason truncated without throw", true);
|
|
751
|
+
await _sleep(30);
|
|
752
|
+
server.close();
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Valid Origin + custom headers reach the request builder (forbidden keys and
|
|
756
|
+
// non-string values skipped, valid header emitted); an Origin carrying CR/LF is
|
|
757
|
+
// refused at build time.
|
|
758
|
+
async function _testHeadersAndOrigin() {
|
|
759
|
+
var server = await _makeServer({});
|
|
760
|
+
var port = server.address().port;
|
|
761
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", {
|
|
762
|
+
origin: "https://app.example.com",
|
|
763
|
+
headers: { "X-Custom": "keep", "Host": "evil.example", "X-Number": 42 },
|
|
764
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
765
|
+
});
|
|
766
|
+
var opened = false, errSeen = null;
|
|
767
|
+
c.on("open", function () { opened = true; });
|
|
768
|
+
c.on("error", function (e) { errSeen = e; });
|
|
769
|
+
await helpers.waitUntil(function () { return opened || errSeen; },
|
|
770
|
+
{ timeoutMs: 5000, label: "ws-client: headers/origin handshake" });
|
|
771
|
+
check("headers/origin: valid origin + custom headers → handshake opens",
|
|
772
|
+
opened === true && errSeen === null);
|
|
773
|
+
c.close();
|
|
774
|
+
await _sleep(30);
|
|
775
|
+
server.close();
|
|
776
|
+
|
|
777
|
+
var server2 = await _makeServer({});
|
|
778
|
+
var port2 = server2.address().port;
|
|
779
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + port2 + "/", {
|
|
780
|
+
origin: "https://evil\r\nX-Injected: 1",
|
|
781
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
782
|
+
});
|
|
783
|
+
var err2 = null;
|
|
784
|
+
c2.on("error", function (e) { err2 = e; });
|
|
785
|
+
await helpers.waitUntil(function () { return err2 !== null; },
|
|
786
|
+
{ timeoutMs: 5000, label: "ws-client: origin CRLF refused" });
|
|
787
|
+
check("origin CRLF: handshake refused with bad-header",
|
|
788
|
+
err2 && err2.code === "ws-client/bad-header" && /CR\/LF/.test(err2.message));
|
|
789
|
+
server2.close();
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Malformed handshake responses the frame parser must reject before the frame
|
|
793
|
+
// layer starts: bad status line, oversized header section, missing Upgrade.
|
|
794
|
+
async function _testMalformedHandshakes() {
|
|
795
|
+
var s1 = await _makeRawResponder("NOT-AN-HTTP-STATUS-LINE\r\n\r\n");
|
|
796
|
+
var c1 = _trackedConnect("ws://127.0.0.1:" + s1.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
797
|
+
var e1 = null; c1.on("error", function (e) { e1 = e; });
|
|
798
|
+
await helpers.waitUntil(function () { return e1 !== null; },
|
|
799
|
+
{ timeoutMs: 5000, label: "ws-client: malformed status line" });
|
|
800
|
+
check("handshake: malformed status line → bad-status-line", e1 && e1.code === "ws-client/bad-status-line");
|
|
801
|
+
s1.close();
|
|
802
|
+
|
|
803
|
+
var pad = "HTTP/1.1 101 Switching Protocols\r\nX-Pad: " + "a".repeat(70 * 1024); // no CRLFCRLF
|
|
804
|
+
var s2 = await _makeRawResponder(pad);
|
|
805
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + s2.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
806
|
+
var e2 = null; c2.on("error", function (e) { e2 = e; });
|
|
807
|
+
await helpers.waitUntil(function () { return e2 !== null; },
|
|
808
|
+
{ timeoutMs: 5000, label: "ws-client: handshake too large" });
|
|
809
|
+
check("handshake: >64 KiB before CRLFCRLF → handshake-too-large", e2 && e2.code === "ws-client/handshake-too-large");
|
|
810
|
+
s2.close();
|
|
811
|
+
|
|
812
|
+
var s3 = await _makeRawResponder("HTTP/1.1 101 Switching Protocols\r\nSec-WebSocket-Accept: x\r\n\r\n");
|
|
813
|
+
var c3 = _trackedConnect("ws://127.0.0.1:" + s3.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
814
|
+
var e3 = null; c3.on("error", function (e) { e3 = e; });
|
|
815
|
+
await helpers.waitUntil(function () { return e3 !== null; },
|
|
816
|
+
{ timeoutMs: 5000, label: "ws-client: missing upgrade header" });
|
|
817
|
+
check("handshake: 101 without Upgrade/Connection → bad-upgrade", e3 && e3.code === "ws-client/bad-upgrade");
|
|
818
|
+
s3.close();
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// RFC 6455 §5.2/§5.5 frame validation: control-frame caps, reserved opcodes,
|
|
822
|
+
// RSV1-on-continuation, fragmentation ordering, close-reason UTF-8, and a
|
|
823
|
+
// frame that exceeds maxFrameBytes (parser throw surfaced through _consumeFrames).
|
|
824
|
+
async function _testAdversarialFrames() {
|
|
825
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x09, Buffer.alloc(200), { fin: true })); },
|
|
826
|
+
null, "ws-client/control-too-big", "frame: control payload > 125 → control-too-big");
|
|
827
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x09, Buffer.alloc(4), { fin: false })); },
|
|
828
|
+
null, "ws-client/control-fragmented", "frame: control FIN=0 → control-fragmented");
|
|
829
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x03, Buffer.from("x"), { fin: true })); },
|
|
830
|
+
null, "ws-client/reserved-opcode", "frame: reserved opcode 0x3 → reserved-opcode");
|
|
831
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x00, Buffer.from("y"), { fin: true, rsv1: true })); },
|
|
832
|
+
null, "ws-client/rsv1-on-continuation", "frame: RSV1 on continuation → rsv1-on-continuation");
|
|
833
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x00, Buffer.from("z"), { fin: true })); },
|
|
834
|
+
null, "ws-client/protocol-error", "frame: continuation with no prior frame → protocol-error");
|
|
835
|
+
await _expectFrameError(function (s) {
|
|
836
|
+
s.write(wsFrame.serializeFrame(0x01, Buffer.from("a"), { fin: false })); // text start, no FIN
|
|
837
|
+
s.write(wsFrame.serializeFrame(0x01, Buffer.from("b"), { fin: true })); // second text mid-fragment
|
|
838
|
+
}, null, "ws-client/protocol-error", "frame: non-continuation mid-fragment → protocol-error");
|
|
839
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x08, Buffer.from([0x03, 0xE8, 0xFF, 0xFF]), { fin: true })); },
|
|
840
|
+
null, "ws-client/invalid-utf8", "frame: close reason invalid UTF-8 → invalid-utf8");
|
|
841
|
+
await _expectFrameError(function (s) { s.write(wsFrame.serializeFrame(0x01, Buffer.alloc(300), { fin: true })); },
|
|
842
|
+
{ client: { maxFrameBytes: 100 } }, "ws/frame-too-large", "frame: over maxFrameBytes → parser error surfaced");
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// A server-initiated PING must elicit a client PONG (masked, per RFC 6455 §5.3).
|
|
846
|
+
async function _testServerPingElicitsPong() {
|
|
847
|
+
var gotPong = false;
|
|
848
|
+
var server = await _makeFrameServer(function (socket) {
|
|
849
|
+
var fp = new wsFrame.FrameParser({ maxFrameBytes: 1024 });
|
|
850
|
+
socket.on("data", function (chunk) {
|
|
851
|
+
var frames = fp.push(chunk) || [];
|
|
852
|
+
for (var i = 0; i < frames.length; i += 1) if (frames[i].opcode === 0x0A) gotPong = true;
|
|
853
|
+
});
|
|
854
|
+
socket.write(wsFrame.serializeFrame(0x09, Buffer.from("srv-ping"), { fin: true }));
|
|
855
|
+
});
|
|
856
|
+
var port = server.address().port;
|
|
857
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
858
|
+
c.on("error", function () { /* keep-alive noise */ });
|
|
859
|
+
await helpers.waitUntil(function () { return gotPong; },
|
|
860
|
+
{ timeoutMs: 5000, label: "ws-client: server PING elicits client PONG" });
|
|
861
|
+
check("frame: server PING → client responds with PONG", gotPong === true);
|
|
862
|
+
c.close();
|
|
863
|
+
await _sleep(30);
|
|
864
|
+
server.close();
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// permessage-deflate: negotiated compressed message decodes, window-bits bounds
|
|
868
|
+
// are honored / refused, a decompression bomb is capped, and inflated bytes are
|
|
869
|
+
// UTF-8-validated.
|
|
870
|
+
async function _testDeflate() {
|
|
871
|
+
var msg = JSON.stringify({ deflate: "round trip", nums: [1, 2, 3] });
|
|
872
|
+
var s1 = await _makeFrameServer(function (s) {
|
|
873
|
+
s.write(wsFrame.serializeFrame(0x01, zlib.deflateRawSync(Buffer.from(msg, "utf8")), { fin: true, rsv1: true }));
|
|
874
|
+
}, { extensions: "permessage-deflate" });
|
|
875
|
+
var c1 = _trackedConnect("ws://127.0.0.1:" + s1.address().port + "/", { reconnect: false, audit: false, allowInternal: true, parse: "json" });
|
|
876
|
+
var got1 = null; c1.on("message", function (m) { got1 = m; }); c1.on("error", function () {});
|
|
877
|
+
await helpers.waitUntil(function () { return got1 !== null; },
|
|
878
|
+
{ timeoutMs: 5000, label: "ws-client: deflate message decodes" });
|
|
879
|
+
check("deflate: compressed RSV1 message inflates + JSON-parses", got1 && got1.deflate === "round trip");
|
|
880
|
+
c1.close(); await _sleep(30); s1.close();
|
|
881
|
+
|
|
882
|
+
var s2 = await _makeFrameServer(null, { extensions: "permessage-deflate; server_max_window_bits=12" });
|
|
883
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + s2.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
884
|
+
var open2 = false; c2.on("open", function () { open2 = true; }); c2.on("error", function () {});
|
|
885
|
+
await helpers.waitUntil(function () { return open2; },
|
|
886
|
+
{ timeoutMs: 5000, label: "ws-client: deflate smwb in-range opens" });
|
|
887
|
+
check("deflate: server_max_window_bits in [8,15] honored (opens)", open2 === true);
|
|
888
|
+
c2.close(); await _sleep(30); s2.close();
|
|
889
|
+
|
|
890
|
+
var s3 = await _makeFrameServer(null, { extensions: "permessage-deflate; server_max_window_bits=20" });
|
|
891
|
+
var c3 = _trackedConnect("ws://127.0.0.1:" + s3.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
892
|
+
var e3 = null; c3.on("error", function (e) { e3 = e; });
|
|
893
|
+
await helpers.waitUntil(function () { return e3 !== null; },
|
|
894
|
+
{ timeoutMs: 5000, label: "ws-client: deflate smwb out-of-range" });
|
|
895
|
+
check("deflate: server_max_window_bits=20 → deflate-error", e3 && e3.code === "ws-client/deflate-error");
|
|
896
|
+
s3.close();
|
|
897
|
+
|
|
898
|
+
var bomb = zlib.deflateRawSync(Buffer.alloc(8000, 0x61));
|
|
899
|
+
var s4 = await _makeFrameServer(function (s) {
|
|
900
|
+
s.write(wsFrame.serializeFrame(0x01, bomb, { fin: true, rsv1: true }));
|
|
901
|
+
}, { extensions: "permessage-deflate" });
|
|
902
|
+
var c4 = _trackedConnect("ws://127.0.0.1:" + s4.address().port + "/", { reconnect: false, audit: false, allowInternal: true, maxMessageBytes: 1000 });
|
|
903
|
+
var e4 = null; c4.on("error", function (e) { e4 = e; });
|
|
904
|
+
await helpers.waitUntil(function () { return e4 !== null; },
|
|
905
|
+
{ timeoutMs: 5000, label: "ws-client: decompression bomb" });
|
|
906
|
+
check("deflate: decompression bomb capped → deflate-error",
|
|
907
|
+
e4 && e4.code === "ws-client/deflate-error" && /bomb|exceeded/i.test(e4.message || ""));
|
|
908
|
+
s4.close();
|
|
909
|
+
|
|
910
|
+
var s5 = await _makeFrameServer(function (s) {
|
|
911
|
+
s.write(wsFrame.serializeFrame(0x01, zlib.deflateRawSync(Buffer.from([0xff, 0xfe, 0xfd])), { fin: true, rsv1: true }));
|
|
912
|
+
}, { extensions: "permessage-deflate" });
|
|
913
|
+
var c5 = _trackedConnect("ws://127.0.0.1:" + s5.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
914
|
+
var e5 = null; c5.on("error", function (e) { e5 = e; });
|
|
915
|
+
await helpers.waitUntil(function () { return e5 !== null; },
|
|
916
|
+
{ timeoutMs: 5000, label: "ws-client: inflated invalid UTF-8" });
|
|
917
|
+
check("deflate: inflated invalid UTF-8 on TEXT → invalid-utf8", e5 && e5.code === "ws-client/invalid-utf8");
|
|
918
|
+
s5.close();
|
|
919
|
+
|
|
920
|
+
// Corrupt (non-deflate) RSV1 payload → inflate raises a Z_DATA_ERROR that is
|
|
921
|
+
// NOT the decompression-bomb sentinel, so it is re-thrown and surfaces as a
|
|
922
|
+
// generic deflate-error (the non-bomb branch of the bounded inflate helper).
|
|
923
|
+
var s6 = await _makeFrameServer(function (s) {
|
|
924
|
+
s.write(wsFrame.serializeFrame(0x01, Buffer.from([0xde, 0xad, 0xbe, 0xef]), { fin: true, rsv1: true }));
|
|
925
|
+
}, { extensions: "permessage-deflate" });
|
|
926
|
+
var c6 = _trackedConnect("ws://127.0.0.1:" + s6.address().port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
927
|
+
var e6 = null; c6.on("error", function (e) { e6 = e; });
|
|
928
|
+
await helpers.waitUntil(function () { return e6 !== null; },
|
|
929
|
+
{ timeoutMs: 5000, label: "ws-client: corrupt deflate payload" });
|
|
930
|
+
check("deflate: corrupt compressed payload → deflate-error (non-bomb)",
|
|
931
|
+
e6 && e6.code === "ws-client/deflate-error" && !/bomb/i.test(e6.message || ""));
|
|
932
|
+
s6.close();
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// parse:"json" and a custom parser fn — success paths transform the message;
|
|
936
|
+
// failure paths surface json-parse / parser-failed on 'error'.
|
|
937
|
+
async function _testJsonAndCustomParser() {
|
|
938
|
+
var server = await _makeServer({});
|
|
939
|
+
var c = _trackedConnect("ws://127.0.0.1:" + server.address().port + "/", { parse: "json", reconnect: false, audit: false, allowInternal: true });
|
|
940
|
+
var got = null; c.on("message", function (m) { got = m; }); c.on("error", function () {});
|
|
941
|
+
await helpers.waitUntil(function () { return c.readyState === "open"; },
|
|
942
|
+
{ timeoutMs: 5000, label: "ws-client: json-parse client opens" });
|
|
943
|
+
c.send(JSON.stringify({ parsed: true, k: 9 }));
|
|
944
|
+
await helpers.waitUntil(function () { return got !== null; },
|
|
945
|
+
{ timeoutMs: 5000, label: "ws-client: json-parse message" });
|
|
946
|
+
check("parse:json — echoed JSON text parses to object", got && got.parsed === true && got.k === 9);
|
|
947
|
+
c.close(); await _sleep(30); server.close();
|
|
948
|
+
|
|
949
|
+
var server2 = await _makeFrameServer(function (s) { s.write(wsFrame.serializeFrame(0x01, Buffer.from("this is not json{", "utf8"), { fin: true })); });
|
|
950
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + server2.address().port + "/", { parse: "json", reconnect: false, audit: false, allowInternal: true });
|
|
951
|
+
var e2 = null; c2.on("error", function (e) { e2 = e; });
|
|
952
|
+
await helpers.waitUntil(function () { return e2 !== null; },
|
|
953
|
+
{ timeoutMs: 5000, label: "ws-client: json-parse failure" });
|
|
954
|
+
check("parse:json — invalid JSON text → json-parse error", e2 && e2.code === "ws-client/json-parse");
|
|
955
|
+
c2.close(); await _sleep(30); server2.close();
|
|
956
|
+
|
|
957
|
+
var server3 = await _makeServer({});
|
|
958
|
+
var c3 = _trackedConnect("ws://127.0.0.1:" + server3.address().port + "/", {
|
|
959
|
+
parser: function (text) { return "parsed:" + text; },
|
|
960
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
961
|
+
});
|
|
962
|
+
var got3 = null; c3.on("message", function (m) { got3 = m; }); c3.on("error", function () {});
|
|
963
|
+
await helpers.waitUntil(function () { return c3.readyState === "open"; },
|
|
964
|
+
{ timeoutMs: 5000, label: "ws-client: custom parser opens" });
|
|
965
|
+
c3.send("hello");
|
|
966
|
+
await helpers.waitUntil(function () { return got3 !== null; },
|
|
967
|
+
{ timeoutMs: 5000, label: "ws-client: custom parser message" });
|
|
968
|
+
check("parser fn — transforms payload", got3 === "parsed:hello");
|
|
969
|
+
c3.close(); await _sleep(30); server3.close();
|
|
970
|
+
|
|
971
|
+
var server4 = await _makeFrameServer(function (s) { s.write(wsFrame.serializeFrame(0x01, Buffer.from("x", "utf8"), { fin: true })); });
|
|
972
|
+
var c4 = _trackedConnect("ws://127.0.0.1:" + server4.address().port + "/", {
|
|
973
|
+
parser: function () { throw new Error("parser boom"); },
|
|
974
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
975
|
+
});
|
|
976
|
+
var e4 = null; c4.on("error", function (e) { e4 = e; });
|
|
977
|
+
await helpers.waitUntil(function () { return e4 !== null; },
|
|
978
|
+
{ timeoutMs: 5000, label: "ws-client: parser throws" });
|
|
979
|
+
check("parser fn — thrown error → parser-failed", e4 && e4.code === "ws-client/parser-failed");
|
|
980
|
+
c4.close(); await _sleep(30); server4.close();
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// Heartbeat: with pingMs < pongMs the client sends pings the echo server pongs
|
|
984
|
+
// (deadline refreshed, no timeout); with pingMs > pongMs the first heartbeat
|
|
985
|
+
// fires past a lapsed pong deadline → pong-timeout (transient).
|
|
986
|
+
async function _testHeartbeat() {
|
|
987
|
+
var server = await _makeServer({});
|
|
988
|
+
var port = server.address().port;
|
|
989
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", {
|
|
990
|
+
pingMs: 60, pongMs: 5000, reconnect: false, audit: false, allowInternal: true,
|
|
991
|
+
});
|
|
992
|
+
var errSeen = null;
|
|
993
|
+
c.on("error", function (e) { errSeen = e; });
|
|
994
|
+
await helpers.waitUntil(function () { return c.readyState === "open"; },
|
|
995
|
+
{ timeoutMs: 5000, label: "ws-client: heartbeat client opens" });
|
|
996
|
+
await _sleep(220); // ~3 heartbeat intervals — pings sent, pongs refresh the deadline
|
|
997
|
+
check("heartbeat: pings sent + pongs refresh deadline (no pong-timeout)",
|
|
998
|
+
c.readyState === "open" && errSeen === null);
|
|
999
|
+
c.close();
|
|
1000
|
+
await _sleep(30);
|
|
1001
|
+
server.close();
|
|
1002
|
+
|
|
1003
|
+
var server2 = await _makeServer({});
|
|
1004
|
+
var port2 = server2.address().port;
|
|
1005
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + port2 + "/", {
|
|
1006
|
+
pingMs: 150, pongMs: 40, reconnect: false, audit: false, allowInternal: true,
|
|
1007
|
+
});
|
|
1008
|
+
var err2 = null;
|
|
1009
|
+
c2.on("error", function (e) { if (!err2) err2 = e; });
|
|
1010
|
+
await helpers.waitUntil(function () { return err2 !== null; },
|
|
1011
|
+
{ timeoutMs: 5000, label: "ws-client: pong-timeout fires" });
|
|
1012
|
+
check("heartbeat: no pong before deadline → pong-timeout", err2 && err2.code === "ws-client/pong-timeout");
|
|
1013
|
+
check("heartbeat: pong-timeout is transient (permanent === false)", err2 && err2.permanent === false);
|
|
1014
|
+
server2.close();
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// A pending reconnect timer is cleared by cancelReconnect(). Dial a dead port
|
|
1018
|
+
// with a long backoff so the timer stays pending, then cancel before it fires.
|
|
1019
|
+
async function _testCancelPendingReconnect() {
|
|
1020
|
+
var c = _trackedConnect("ws://127.0.0.1:1", {
|
|
1021
|
+
reconnect: { maxAttempts: 5, baseMs: 10000, maxMs: 20000 },
|
|
1022
|
+
handshakeTimeoutMs: 300, audit: false, allowInternal: true,
|
|
1023
|
+
});
|
|
1024
|
+
var reconnecting = 0;
|
|
1025
|
+
c.on("error", function () { /* dial failure */ });
|
|
1026
|
+
c.on("reconnecting", function () { reconnecting += 1; });
|
|
1027
|
+
await helpers.waitUntil(function () { return reconnecting >= 1; },
|
|
1028
|
+
{ timeoutMs: 5000, label: "ws-client: first reconnect scheduled" });
|
|
1029
|
+
check("cancelReconnect: a reconnect was scheduled", reconnecting === 1);
|
|
1030
|
+
c.cancelReconnect(); // clears the pending timer
|
|
1031
|
+
await _sleep(150);
|
|
1032
|
+
check("cancelReconnect: no further reconnect after cancel", reconnecting === 1);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// Option-default arms: a reconnect object omitting maxAttempts/baseMs/maxMs
|
|
1036
|
+
// falls back to framework defaults; ping() with no payload sends an empty
|
|
1037
|
+
// frame; a tlsOptsFor returning a non-object is ignored.
|
|
1038
|
+
async function _testOptionDefaultBranches() {
|
|
1039
|
+
var c = _trackedConnect("ws://127.0.0.1:1", {
|
|
1040
|
+
reconnect: { enabled: true }, handshakeTimeoutMs: 300, audit: false, allowInternal: true,
|
|
1041
|
+
});
|
|
1042
|
+
var reconnecting = 0;
|
|
1043
|
+
c.on("error", function () { /* dial failure */ });
|
|
1044
|
+
c.on("reconnecting", function () { reconnecting += 1; });
|
|
1045
|
+
await helpers.waitUntil(function () { return reconnecting >= 1; },
|
|
1046
|
+
{ timeoutMs: 5000, label: "ws-client: reconnect-default schedules" });
|
|
1047
|
+
check("reconnect defaults: enabled-only object schedules a reconnect", reconnecting >= 1);
|
|
1048
|
+
c.cancelReconnect();
|
|
1049
|
+
|
|
1050
|
+
var server = await _makeServer({});
|
|
1051
|
+
var port = server.address().port;
|
|
1052
|
+
var c2 = _trackedConnect("ws://127.0.0.1:" + port + "/", {
|
|
1053
|
+
reconnect: false, audit: false, allowInternal: true,
|
|
1054
|
+
tlsOptsFor: function () { return null; }, // non-object → merge skipped, dial unaffected
|
|
1055
|
+
});
|
|
1056
|
+
var opened = false;
|
|
1057
|
+
c2.on("open", function () { opened = true; });
|
|
1058
|
+
c2.on("error", function () { /* keep-alive noise */ });
|
|
1059
|
+
await helpers.waitUntil(function () { return opened; },
|
|
1060
|
+
{ timeoutMs: 5000, label: "ws-client: option-default dial opens" });
|
|
1061
|
+
c2.ping(); // no payload → default empty ping frame
|
|
1062
|
+
check("ping(): no-arg ping on open client (tlsOptsFor non-object ignored)", opened === true);
|
|
1063
|
+
c2.close();
|
|
1064
|
+
await _sleep(30);
|
|
1065
|
+
server.close();
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// After the client is marked closed (cancelReconnect while the socket is still
|
|
1069
|
+
// live), a raw peer ECONNRESET is swallowed — not surfaced as a spurious 'error'.
|
|
1070
|
+
async function _testPostCloseSocketErrorSwallowed() {
|
|
1071
|
+
var server = await _makeFrameServer(function (socket) {
|
|
1072
|
+
setTimeout(function () {
|
|
1073
|
+
try { socket.resetAndDestroy(); }
|
|
1074
|
+
catch (_e) { try { socket.destroy(); } catch (_e2) { /* best-effort */ } }
|
|
1075
|
+
}, 120);
|
|
1076
|
+
});
|
|
1077
|
+
var port = server.address().port;
|
|
1078
|
+
var c = _trackedConnect("ws://127.0.0.1:" + port + "/", { reconnect: false, audit: false, allowInternal: true });
|
|
1079
|
+
var opened = false, errAfterClose = null;
|
|
1080
|
+
c.on("open", function () { opened = true; c.cancelReconnect(); }); // mark closed, socket still live
|
|
1081
|
+
c.on("error", function (e) { if (opened) errAfterClose = e; });
|
|
1082
|
+
await helpers.waitUntil(function () { return opened; },
|
|
1083
|
+
{ timeoutMs: 5000, label: "ws-client: post-close swallow opens" });
|
|
1084
|
+
await _sleep(300); // let the peer RST arrive after the client is marked closed
|
|
1085
|
+
check("post-close: peer ECONNRESET after close is swallowed (no spurious error)",
|
|
1086
|
+
errAfterClose === null);
|
|
1087
|
+
server.close();
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// wss:// to an IP-literal target must reach the TLS handshake (then time out
|
|
1091
|
+
// against a non-TLS listener) — not throw a raw ERR_INVALID_ARG_VALUE because
|
|
1092
|
+
// servername was forced to an IP literal (RFC 6066: SNI MUST be a hostname).
|
|
1093
|
+
async function _testWssDialReachesTlsHandshake() {
|
|
1094
|
+
var tcp = net.createServer(function (socket) { tcp._wsSockets.push(socket); socket.on("error", function () {}); });
|
|
1095
|
+
tcp._wsSockets = [];
|
|
1096
|
+
await new Promise(function (r) { tcp.listen(0, "127.0.0.1", r); });
|
|
1097
|
+
_trackServer(tcp);
|
|
1098
|
+
var port = tcp.address().port;
|
|
1099
|
+
var c = _trackedConnect("wss://127.0.0.1:" + port + "/", {
|
|
1100
|
+
reconnect: false, audit: false, allowInternal: true, handshakeTimeoutMs: 300,
|
|
1101
|
+
});
|
|
1102
|
+
var err = null;
|
|
1103
|
+
c.on("error", function (e) { if (!err) err = e; });
|
|
1104
|
+
await helpers.waitUntil(function () { return err !== null; },
|
|
1105
|
+
{ timeoutMs: 5000, label: "ws-client: wss dial reaches TLS handshake" });
|
|
1106
|
+
check("wss dial: IP-literal target reaches TLS handshake (times out, not ERR_INVALID_ARG_VALUE)",
|
|
1107
|
+
err && err.code === "ws-client/handshake-timeout");
|
|
1108
|
+
tcp.close();
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// Same defense for an IPv6 literal: `parsed.hostname` keeps the brackets
|
|
1112
|
+
// (`[::1]`), and net.isIP only recognizes the bare form. Without stripping the
|
|
1113
|
+
// brackets before the IP test, the client sends SNI = "[::1]" — a bracketed IP
|
|
1114
|
+
// literal, which is malformed per RFC 6066 §3 (SNI MUST be a hostname) and a
|
|
1115
|
+
// strict TLS server can reject. Observe the exact options handed to
|
|
1116
|
+
// tls.connect: for an IPv6-literal target the servername must be OMITTED (the
|
|
1117
|
+
// same treatment IPv4 literals get), not set to the bracketed address.
|
|
1118
|
+
async function _testWssDialIpv6LiteralOmitsSni() {
|
|
1119
|
+
var tls = require("node:tls");
|
|
1120
|
+
var orig = tls.connect;
|
|
1121
|
+
var captured = null;
|
|
1122
|
+
tls.connect = function (opts) {
|
|
1123
|
+
if (captured === null) { captured = opts || {}; tls.connect = orig; }
|
|
1124
|
+
// Return a dummy socket that immediately errors so the dial tears down
|
|
1125
|
+
// cleanly without a real network attempt.
|
|
1126
|
+
var s = orig.call(tls, { host: "127.0.0.1", port: 1, servername: undefined });
|
|
1127
|
+
s.on("error", function () {});
|
|
1128
|
+
return s;
|
|
1129
|
+
};
|
|
1130
|
+
try {
|
|
1131
|
+
var c = _trackedConnect("wss://[::1]:8443/", {
|
|
1132
|
+
reconnect: false, audit: false, allowInternal: true, handshakeTimeoutMs: 300,
|
|
1133
|
+
});
|
|
1134
|
+
c.on("error", function () {});
|
|
1135
|
+
await helpers.waitUntil(function () { return captured !== null; },
|
|
1136
|
+
{ timeoutMs: 5000, label: "ws-client: tls.connect called for wss IPv6-literal dial" });
|
|
1137
|
+
check("wss dial: IPv6-literal target omits SNI (not set to the bracketed IP literal)",
|
|
1138
|
+
captured && captured.servername === undefined);
|
|
1139
|
+
} finally {
|
|
1140
|
+
tls.connect = orig;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// #492 — a close() during a slow INITIAL dial (the >1s SSRF re-resolve in
|
|
1144
|
+
// _prepareDial) must not resolve into _dial() and open a socket nobody owns.
|
|
1145
|
+
// The reconnect path guards _closed before AND inside its .then; the initial
|
|
1146
|
+
// dial did not. Drive it by making _prepareDial's ssrfGuard.checkUrl slow.
|
|
1147
|
+
{
|
|
1148
|
+
var ssrfGuardMod = require("../../lib/ssrf-guard");
|
|
1149
|
+
var origCheckUrl = ssrfGuardMod.checkUrl;
|
|
1150
|
+
var releaseDial;
|
|
1151
|
+
var dialGate = new Promise(function (res) { releaseDial = res; });
|
|
1152
|
+
// Gate _prepareDial's SSRF re-resolve so it stays pending until we release
|
|
1153
|
+
// it AFTER close() — deterministically reproduces "close during a slow
|
|
1154
|
+
// initial dial" with no timer.
|
|
1155
|
+
ssrfGuardMod.checkUrl = function (u, o) {
|
|
1156
|
+
return dialGate.then(function () { return origCheckUrl.call(ssrfGuardMod, u, o); });
|
|
1157
|
+
};
|
|
1158
|
+
try {
|
|
1159
|
+
var opened492 = false;
|
|
1160
|
+
var c492 = _trackedConnect("ws://127.0.0.1:9/", { reconnect: false, audit: false, allowInternal: true });
|
|
1161
|
+
c492.on("open", function () { opened492 = true; });
|
|
1162
|
+
c492.on("error", function () { /* the dead-port dial errors; irrelevant */ });
|
|
1163
|
+
c492.close(); // close WHILE _prepareDial is still pending
|
|
1164
|
+
releaseDial(); // now let _prepareDial resolve — on the buggy tree its .then runs _dial()
|
|
1165
|
+
await helpers.passiveObserve(300,
|
|
1166
|
+
"ws-client #492: no dial after close() during a slow initial _prepareDial");
|
|
1167
|
+
check("wsClient: close() during a slow initial dial opens no socket",
|
|
1168
|
+
c492._socket == null && opened492 === false);
|
|
1169
|
+
} finally {
|
|
1170
|
+
ssrfGuardMod.checkUrl = origCheckUrl;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
546
1175
|
module.exports = { run: run };
|
|
547
1176
|
if (require.main === module) {
|
|
548
1177
|
run().then(function () { process.exit(0); })
|