@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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.botDisclose — California SB 1001 bot-disclosure.
|
|
6
|
+
*
|
|
7
|
+
* Drives the load-bearing disclosure surfaces: the X-Bot-Disclosure
|
|
8
|
+
* header on every in-scope request, banner injection into text/html
|
|
9
|
+
* responses, res.locals for JSON handlers, and mountPaths scoping.
|
|
10
|
+
*
|
|
11
|
+
* Run standalone: `node test/layer-0-primitives/middleware-bot-disclose.test.js`
|
|
12
|
+
* Or via smoke: `node test/smoke.js`
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
var helpers = require("../helpers");
|
|
16
|
+
var b = helpers.b;
|
|
17
|
+
var check = helpers.check;
|
|
18
|
+
var _mockReq = helpers._mockReq;
|
|
19
|
+
var _mockRes = helpers._mockRes;
|
|
20
|
+
|
|
21
|
+
function testHeaderSetOnEveryRequest() {
|
|
22
|
+
var mw = b.middleware.botDisclose({ mountPaths: ["/chat"] });
|
|
23
|
+
var req = _mockReq({ method: "GET", url: "/chat" });
|
|
24
|
+
var res = _mockRes();
|
|
25
|
+
var nextCalled = false;
|
|
26
|
+
mw(req, res, function () { nextCalled = true; });
|
|
27
|
+
res.end("{}");
|
|
28
|
+
check("botDisclose: X-Bot-Disclosure header set for API consumers",
|
|
29
|
+
res._captured().headers["x-bot-disclosure"] === "automated-assistant");
|
|
30
|
+
check("botDisclose: delegates to the handler via next()", nextCalled === true);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function testBannerInjectedIntoHtml() {
|
|
34
|
+
var mw = b.middleware.botDisclose({
|
|
35
|
+
mountPaths: ["/chat"],
|
|
36
|
+
bannerHtml: '<div id="BOT-BANNER">automated</div>',
|
|
37
|
+
});
|
|
38
|
+
var req = _mockReq({ method: "GET", url: "/chat" });
|
|
39
|
+
var res = _mockRes();
|
|
40
|
+
mw(req, res, function () {});
|
|
41
|
+
// Operator handler renders HTML — the middleware patched res.end.
|
|
42
|
+
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
43
|
+
res.end("<html><body><h1>hi</h1></body></html>");
|
|
44
|
+
var body = res._captured().body;
|
|
45
|
+
check("botDisclose: banner injected into the HTML response",
|
|
46
|
+
body.indexOf('<div id="BOT-BANNER">automated</div>') !== -1);
|
|
47
|
+
check("botDisclose: banner injected AFTER the <body> open tag",
|
|
48
|
+
body.indexOf("<body>") < body.indexOf("BOT-BANNER") &&
|
|
49
|
+
body.indexOf("BOT-BANNER") < body.indexOf("<h1>"));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function testNonHtmlResponseNotRewritten() {
|
|
53
|
+
var mw = b.middleware.botDisclose({ mountPaths: ["/api/chat"] });
|
|
54
|
+
var req = _mockReq({ method: "POST", url: "/api/chat" });
|
|
55
|
+
var res = _mockRes();
|
|
56
|
+
mw(req, res, function () {});
|
|
57
|
+
res.setHeader("content-type", "application/json");
|
|
58
|
+
res.end('{"reply":"hi"}');
|
|
59
|
+
check("botDisclose: JSON body left byte-for-byte intact (header carries the disclosure)",
|
|
60
|
+
res._captured().body === '{"reply":"hi"}');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function testJsonDisclosureOnLocals() {
|
|
64
|
+
var mw = b.middleware.botDisclose({
|
|
65
|
+
mountPaths: ["/chat"],
|
|
66
|
+
bannerJson: { _bot: true, disclosure: "automated-assistant" },
|
|
67
|
+
});
|
|
68
|
+
var req = _mockReq({ method: "GET", url: "/chat" });
|
|
69
|
+
var res = _mockRes();
|
|
70
|
+
res.locals = {};
|
|
71
|
+
mw(req, res, function () {});
|
|
72
|
+
check("botDisclose: bannerJson exposed on res.locals for JSON handlers",
|
|
73
|
+
res.locals.botDisclosure && res.locals.botDisclosure._bot === true);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function testMountPathScoping() {
|
|
77
|
+
var mw = b.middleware.botDisclose({ mountPaths: ["/chat"] });
|
|
78
|
+
var req = _mockReq({ method: "GET", url: "/dashboard" });
|
|
79
|
+
var res = _mockRes();
|
|
80
|
+
var nextCalled = false;
|
|
81
|
+
mw(req, res, function () { nextCalled = true; });
|
|
82
|
+
check("botDisclose: request outside mountPaths passes through untouched", nextCalled === true);
|
|
83
|
+
check("botDisclose: no header on out-of-scope route",
|
|
84
|
+
res._captured().headers["x-bot-disclosure"] === undefined);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function testNullMountPathsAppliesEverywhere() {
|
|
88
|
+
// null mountPaths = apply to every route.
|
|
89
|
+
var mw = b.middleware.botDisclose({});
|
|
90
|
+
var req = _mockReq({ method: "GET", url: "/anything/at/all" });
|
|
91
|
+
var res = _mockRes();
|
|
92
|
+
mw(req, res, function () {});
|
|
93
|
+
check("botDisclose: null mountPaths applies the header to every route",
|
|
94
|
+
res._captured().headers["x-bot-disclosure"] === "automated-assistant");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function testCustomHeaderName() {
|
|
98
|
+
var mw = b.middleware.botDisclose({ headerName: "X-Automated-Agent" });
|
|
99
|
+
var req = _mockReq({ method: "GET", url: "/x" });
|
|
100
|
+
var res = _mockRes();
|
|
101
|
+
mw(req, res, function () {});
|
|
102
|
+
check("botDisclose: custom headerName honored",
|
|
103
|
+
res._captured().headers["x-automated-agent"] === "automated-assistant");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function run() {
|
|
107
|
+
testHeaderSetOnEveryRequest();
|
|
108
|
+
testBannerInjectedIntoHtml();
|
|
109
|
+
testNonHtmlResponseNotRewritten();
|
|
110
|
+
testJsonDisclosureOnLocals();
|
|
111
|
+
testMountPathScoping();
|
|
112
|
+
testNullMountPathsAppliesEverywhere();
|
|
113
|
+
testCustomHeaderName();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { run: run };
|
|
117
|
+
|
|
118
|
+
if (require.main === module) {
|
|
119
|
+
Promise.resolve().then(run).then(
|
|
120
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
121
|
+
function (e) { console.error("FAIL:", e && e.message); process.exit(1); }
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.cookies — inbound Cookie-header threat detection.
|
|
6
|
+
*
|
|
7
|
+
* Drives the request-lifecycle wrapper around b.cookies.parseSafe:
|
|
8
|
+
* populates req.cookieJar, refuses on a HIGH-severity issue in enforce
|
|
9
|
+
* mode, passes through (but still parses) in audit-only mode, and is
|
|
10
|
+
* idempotent when a jar is already present.
|
|
11
|
+
*
|
|
12
|
+
* Run standalone: `node test/layer-0-primitives/middleware-cookies.test.js`
|
|
13
|
+
* Or via smoke: `node test/smoke.js`
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
var helpers = require("../helpers");
|
|
17
|
+
var b = helpers.b;
|
|
18
|
+
var check = helpers.check;
|
|
19
|
+
var _mockReq = helpers._mockReq;
|
|
20
|
+
var _mockRes = helpers._mockRes;
|
|
21
|
+
|
|
22
|
+
function testCleanCookiePopulatesJar() {
|
|
23
|
+
var mw = b.middleware.cookies({ mode: "enforce" });
|
|
24
|
+
var req = _mockReq({ headers: { cookie: "sid=abc; theme=dark" } });
|
|
25
|
+
var res = _mockRes();
|
|
26
|
+
var nextCalled = false;
|
|
27
|
+
mw(req, res, function () { nextCalled = true; });
|
|
28
|
+
check("cookies: clean header delegates via next()", nextCalled === true);
|
|
29
|
+
check("cookies: req.cookieJar populated with parsed pairs",
|
|
30
|
+
req.cookieJar.sid === "abc" && req.cookieJar.theme === "dark");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function testEnforceRefusesDuplicateName() {
|
|
34
|
+
// Cookie-tossing: a duplicate name is a HIGH issue; enforce mode
|
|
35
|
+
// refuses with HTTP 400 + JSON body and does NOT call next().
|
|
36
|
+
var mw = b.middleware.cookies({ mode: "enforce" });
|
|
37
|
+
var req = _mockReq({ headers: { cookie: "session=abc; session=evil" } });
|
|
38
|
+
var res = _mockRes();
|
|
39
|
+
var nextCalled = false;
|
|
40
|
+
mw(req, res, function () { nextCalled = true; });
|
|
41
|
+
check("cookies: enforce refuses HIGH-severity issue with 400", res.statusCode === 400);
|
|
42
|
+
check("cookies: refusal does not delegate to the handler", nextCalled === false);
|
|
43
|
+
var body = JSON.parse(res._captured().body);
|
|
44
|
+
check("cookies: refusal body names the threat",
|
|
45
|
+
body.error === "cookie-threat-detected" &&
|
|
46
|
+
body.issues.some(function (i) { return i.kind === "duplicate-name" && i.severity === "high"; }));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function testAuditOnlyPassesThroughButParses() {
|
|
50
|
+
var mw = b.middleware.cookies({ mode: "audit-only" });
|
|
51
|
+
var req = _mockReq({ headers: { cookie: "session=abc; session=evil" } });
|
|
52
|
+
var res = _mockRes();
|
|
53
|
+
var nextCalled = false;
|
|
54
|
+
mw(req, res, function () { nextCalled = true; });
|
|
55
|
+
check("cookies: audit-only passes the request through", nextCalled === true);
|
|
56
|
+
check("cookies: audit-only still populates the jar (last-write-wins)",
|
|
57
|
+
req.cookieJar.session === "evil");
|
|
58
|
+
check("cookies: audit-only writes no refusal status", res.statusCode === null);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function testAuditSinkReceivesThreat() {
|
|
62
|
+
var audit = b.testing.captureAudit();
|
|
63
|
+
var mw = b.middleware.cookies({ mode: "enforce", audit: audit });
|
|
64
|
+
var req = _mockReq({ headers: { cookie: "session=abc; session=evil" } });
|
|
65
|
+
mw(req, _mockRes(), function () {});
|
|
66
|
+
check("cookies: threat routed to the audit sink",
|
|
67
|
+
audit.captured.some(function (e) { return e.action === "middleware.cookies.threat-detected"; }));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function testIdempotentWhenJarPresent() {
|
|
71
|
+
var mw = b.middleware.cookies({ mode: "enforce" });
|
|
72
|
+
var req = _mockReq({ headers: { cookie: "session=abc; session=evil" } });
|
|
73
|
+
// A prior cookies middleware already parsed the jar this request.
|
|
74
|
+
req.cookieJar = { session: "trusted" };
|
|
75
|
+
var res = _mockRes();
|
|
76
|
+
var nextCalled = false;
|
|
77
|
+
mw(req, res, function () { nextCalled = true; });
|
|
78
|
+
check("cookies: idempotent — pre-existing jar is not re-parsed or refused",
|
|
79
|
+
nextCalled === true && req.cookieJar.session === "trusted" && res.statusCode === null);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function testControlByteRefused() {
|
|
83
|
+
var mw = b.middleware.cookies({ mode: "enforce" });
|
|
84
|
+
var req = _mockReq({ headers: { cookie: "a=1\r\nSet-Cookie: evil=1" } });
|
|
85
|
+
var res = _mockRes();
|
|
86
|
+
var nextCalled = false;
|
|
87
|
+
mw(req, res, function () { nextCalled = true; });
|
|
88
|
+
check("cookies: CR/LF control-byte header refused with 400",
|
|
89
|
+
res.statusCode === 400 && nextCalled === false);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function run() {
|
|
93
|
+
testCleanCookiePopulatesJar();
|
|
94
|
+
testEnforceRefusesDuplicateName();
|
|
95
|
+
testAuditOnlyPassesThroughButParses();
|
|
96
|
+
testAuditSinkReceivesThreat();
|
|
97
|
+
testIdempotentWhenJarPresent();
|
|
98
|
+
testControlByteRefused();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = { run: run };
|
|
102
|
+
|
|
103
|
+
if (require.main === module) {
|
|
104
|
+
Promise.resolve().then(run).then(
|
|
105
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
106
|
+
function (e) { console.error("FAIL:", e && e.message); process.exit(1); }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.gpc — Sec-GPC (Global Privacy Control) handler.
|
|
6
|
+
*
|
|
7
|
+
* Drives the advertised contract: reads Sec-GPC: 1, sets
|
|
8
|
+
* req.gpcOptOut, echoes Sec-GPC-Status, records purpose withdrawal
|
|
9
|
+
* through an optional b.consent integration, and always calls next().
|
|
10
|
+
*
|
|
11
|
+
* Run standalone: `node test/layer-0-primitives/middleware-gpc.test.js`
|
|
12
|
+
* Or via smoke: `node test/smoke.js`
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
var helpers = require("../helpers");
|
|
16
|
+
var b = helpers.b;
|
|
17
|
+
var check = helpers.check;
|
|
18
|
+
var _mockReq = helpers._mockReq;
|
|
19
|
+
var _mockRes = helpers._mockRes;
|
|
20
|
+
|
|
21
|
+
function testOptOutHonored() {
|
|
22
|
+
var mw = b.middleware.gpc({ mode: "enforce" });
|
|
23
|
+
var req = _mockReq({ headers: { "sec-gpc": "1" } });
|
|
24
|
+
var res = _mockRes();
|
|
25
|
+
var nextCalled = false;
|
|
26
|
+
mw(req, res, function () { nextCalled = true; });
|
|
27
|
+
check("gpc: Sec-GPC:1 sets req.gpcOptOut = true", req.gpcOptOut === true);
|
|
28
|
+
check("gpc: honored acknowledgement header echoed",
|
|
29
|
+
res._captured().headers["sec-gpc-status"] === "honored");
|
|
30
|
+
check("gpc: middleware always delegates via next()", nextCalled === true);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function testNoSignalIsNotOptOut() {
|
|
34
|
+
var mw = b.middleware.gpc({ mode: "enforce" });
|
|
35
|
+
var req = _mockReq({ headers: {} });
|
|
36
|
+
var res = _mockRes();
|
|
37
|
+
var nextCalled = false;
|
|
38
|
+
mw(req, res, function () { nextCalled = true; });
|
|
39
|
+
check("gpc: absent Sec-GPC leaves req.gpcOptOut = false", req.gpcOptOut === false);
|
|
40
|
+
check("gpc: no acknowledgement header without the signal",
|
|
41
|
+
res._captured().headers["sec-gpc-status"] === undefined);
|
|
42
|
+
check("gpc: passes through", nextCalled === true);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function testNonOneValueIsNotOptOut() {
|
|
46
|
+
// Only the exact "1" token is the opt-out per the IETF draft.
|
|
47
|
+
var mw = b.middleware.gpc({});
|
|
48
|
+
var req = _mockReq({ headers: { "sec-gpc": "0" } });
|
|
49
|
+
mw(req, _mockRes(), function () {});
|
|
50
|
+
check("gpc: Sec-GPC:0 is not an opt-out", req.gpcOptOut === false);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function testAuditOnlyModeStatus() {
|
|
54
|
+
var mw = b.middleware.gpc({ mode: "audit-only" });
|
|
55
|
+
var req = _mockReq({ headers: { "sec-gpc": "1" } });
|
|
56
|
+
var res = _mockRes();
|
|
57
|
+
mw(req, res, function () {});
|
|
58
|
+
check("gpc: audit-only still records the opt-out", req.gpcOptOut === true);
|
|
59
|
+
check("gpc: audit-only acknowledgement header reflects the mode",
|
|
60
|
+
res._captured().headers["sec-gpc-status"] === "audit-only");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function testStatusHeaderSuppressible() {
|
|
64
|
+
var mw = b.middleware.gpc({ statusHeader: false });
|
|
65
|
+
var req = _mockReq({ headers: { "sec-gpc": "1" } });
|
|
66
|
+
var res = _mockRes();
|
|
67
|
+
mw(req, res, function () {});
|
|
68
|
+
check("gpc: statusHeader:false suppresses the acknowledgement header",
|
|
69
|
+
res._captured().headers["sec-gpc-status"] === undefined);
|
|
70
|
+
check("gpc: opt-out still recorded even with the header suppressed",
|
|
71
|
+
req.gpcOptOut === true);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function testConsentIntegrationRecordsPurposes() {
|
|
75
|
+
var recorded = null;
|
|
76
|
+
var fakeConsent = {
|
|
77
|
+
recordOptOut: function (o) { recorded = o; },
|
|
78
|
+
};
|
|
79
|
+
var mw = b.middleware.gpc({ consent: fakeConsent });
|
|
80
|
+
var req = _mockReq({ headers: { "sec-gpc": "1" } });
|
|
81
|
+
mw(req, _mockRes(), function () {});
|
|
82
|
+
check("gpc: consent integration invoked with source sec-gpc",
|
|
83
|
+
recorded !== null && recorded.source === "sec-gpc");
|
|
84
|
+
check("gpc: the CCPA/CPRA opt-out purposes are withdrawn",
|
|
85
|
+
recorded.purposes.indexOf("sale") !== -1 &&
|
|
86
|
+
recorded.purposes.indexOf("share") !== -1 &&
|
|
87
|
+
recorded.purposes.indexOf("targeted-ads") !== -1 &&
|
|
88
|
+
recorded.purposes.indexOf("profiling") !== -1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function testConsentErrorDoesNotCrashRequest() {
|
|
92
|
+
// A throwing consent integration must be swallowed (drop-silent) so
|
|
93
|
+
// the request that carried the GPC signal still completes.
|
|
94
|
+
var mw = b.middleware.gpc({
|
|
95
|
+
consent: { recordOptOut: function () { throw new Error("consent store down"); } },
|
|
96
|
+
});
|
|
97
|
+
var req = _mockReq({ headers: { "sec-gpc": "1" } });
|
|
98
|
+
var nextCalled = false;
|
|
99
|
+
mw(req, _mockRes(), function () { nextCalled = true; });
|
|
100
|
+
check("gpc: a throwing consent store does not crash the request",
|
|
101
|
+
nextCalled === true && req.gpcOptOut === true);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function run() {
|
|
105
|
+
testOptOutHonored();
|
|
106
|
+
testNoSignalIsNotOptOut();
|
|
107
|
+
testNonOneValueIsNotOptOut();
|
|
108
|
+
testAuditOnlyModeStatus();
|
|
109
|
+
testStatusHeaderSuppressible();
|
|
110
|
+
testConsentIntegrationRecordsPurposes();
|
|
111
|
+
testConsentErrorDoesNotCrashRequest();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = { run: run };
|
|
115
|
+
|
|
116
|
+
if (require.main === module) {
|
|
117
|
+
Promise.resolve().then(run).then(
|
|
118
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
119
|
+
function (e) { console.error("FAIL:", e && e.message); process.exit(1); }
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.headers — inbound HTTP header threat detection.
|
|
6
|
+
*
|
|
7
|
+
* Drives the RFC 9110 §5.1 token grammar check, RFC 9112 §6.1
|
|
8
|
+
* request-smuggling shapes (CL+TE, multi-CL, multi-TE), oversize
|
|
9
|
+
* count / value caps, deprecated X-Forwarded-* warning, and the
|
|
10
|
+
* enforce-vs-audit-only disposition.
|
|
11
|
+
*
|
|
12
|
+
* Run standalone: `node test/layer-0-primitives/middleware-headers.test.js`
|
|
13
|
+
* Or via smoke: `node test/smoke.js`
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
var helpers = require("../helpers");
|
|
17
|
+
var b = helpers.b;
|
|
18
|
+
var check = helpers.check;
|
|
19
|
+
|
|
20
|
+
function _req(headers) {
|
|
21
|
+
return { method: "GET", url: "/x", headers: headers || {} };
|
|
22
|
+
}
|
|
23
|
+
function _res() {
|
|
24
|
+
return b.testing.mockRes();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function testCleanHeadersPass() {
|
|
28
|
+
var mw = b.middleware.headers({});
|
|
29
|
+
var req = _req({ host: "app.example.com", accept: "*/*" });
|
|
30
|
+
var res = _res();
|
|
31
|
+
var nextCalled = false;
|
|
32
|
+
mw(req, res, function () { nextCalled = true; });
|
|
33
|
+
check("headers: clean request passes through", nextCalled === true);
|
|
34
|
+
check("headers: clean request writes no refusal", res.statusCode === null);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function testCrlfInValueRefused() {
|
|
38
|
+
var mw = b.middleware.headers({ mode: "enforce" });
|
|
39
|
+
var req = _req({ host: "x", "x-note": "line1\r\nline2" });
|
|
40
|
+
var res = _res();
|
|
41
|
+
var nextCalled = false;
|
|
42
|
+
mw(req, res, function () { nextCalled = true; });
|
|
43
|
+
check("headers: CR/LF in a header value refused with 400",
|
|
44
|
+
res.statusCode === 400 && nextCalled === false);
|
|
45
|
+
var body = JSON.parse(res._captured().body);
|
|
46
|
+
check("headers: refusal names header-value-control-byte",
|
|
47
|
+
body.error === "header-threat-detected" &&
|
|
48
|
+
body.issues.some(function (i) { return i.kind === "header-value-control-byte"; }));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function testClTeSmugglingRefused() {
|
|
52
|
+
var mw = b.middleware.headers({ mode: "enforce" });
|
|
53
|
+
var req = _req({ host: "x", "content-length": "5", "transfer-encoding": "chunked" });
|
|
54
|
+
var res = _res();
|
|
55
|
+
var nextCalled = false;
|
|
56
|
+
mw(req, res, function () { nextCalled = true; });
|
|
57
|
+
check("headers: CL+TE request-smuggling shape refused with 400",
|
|
58
|
+
res.statusCode === 400 && nextCalled === false);
|
|
59
|
+
var body = JSON.parse(res._captured().body);
|
|
60
|
+
check("headers: refusal names smuggling-cl-te",
|
|
61
|
+
body.issues.some(function (i) { return i.kind === "smuggling-cl-te"; }));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function testMultiValueSmugglingRefused() {
|
|
65
|
+
var mw = b.middleware.headers({ mode: "enforce" });
|
|
66
|
+
// Node surfaces repeated headers as an array — the proxy-desync class.
|
|
67
|
+
var reqCl = _req({ host: "x", "content-length": ["5", "6"] });
|
|
68
|
+
var resCl = _res();
|
|
69
|
+
mw(reqCl, resCl, function () {});
|
|
70
|
+
check("headers: multiple Content-Length values refused", resCl.statusCode === 400);
|
|
71
|
+
|
|
72
|
+
var reqTe = _req({ host: "x", "transfer-encoding": ["chunked", "gzip"] });
|
|
73
|
+
var resTe = _res();
|
|
74
|
+
mw(reqTe, resTe, function () {});
|
|
75
|
+
check("headers: multiple Transfer-Encoding values refused", resTe.statusCode === 400);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function testHeaderCountCapRefused() {
|
|
79
|
+
var mw = b.middleware.headers({ mode: "enforce", maxHeaderCount: 3 });
|
|
80
|
+
var req = _req({ host: "x", a: "1", b: "2", c: "3", d: "4" });
|
|
81
|
+
var res = _res();
|
|
82
|
+
var nextCalled = false;
|
|
83
|
+
mw(req, res, function () { nextCalled = true; });
|
|
84
|
+
check("headers: header count over the cap refused",
|
|
85
|
+
res.statusCode === 400 && nextCalled === false);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function testValueByteCapRefused() {
|
|
89
|
+
var mw = b.middleware.headers({ mode: "enforce", maxValueBytes: 16 });
|
|
90
|
+
var req = _req({ host: "x", "x-big": "A".repeat(64) });
|
|
91
|
+
var res = _res();
|
|
92
|
+
mw(req, res, function () {});
|
|
93
|
+
check("headers: header value over the byte cap refused", res.statusCode === 400);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function testInvalidHeaderNameShapeRefused() {
|
|
97
|
+
var mw = b.middleware.headers({ mode: "enforce" });
|
|
98
|
+
var req = _req({ host: "x", "bad header name": "v" });
|
|
99
|
+
var res = _res();
|
|
100
|
+
mw(req, res, function () {});
|
|
101
|
+
check("headers: non-RFC9110-token header name refused", res.statusCode === 400);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function testDeprecatedTrustHeaderWarnsButPasses() {
|
|
105
|
+
var audit = b.testing.captureAudit();
|
|
106
|
+
var mw = b.middleware.headers({ audit: audit });
|
|
107
|
+
var req = _req({ host: "x", "x-forwarded-for": "1.2.3.4" });
|
|
108
|
+
var res = _res();
|
|
109
|
+
var nextCalled = false;
|
|
110
|
+
mw(req, res, function () { nextCalled = true; });
|
|
111
|
+
check("headers: deprecated X-Forwarded-* is WARN-only — request passes",
|
|
112
|
+
nextCalled === true && res.statusCode === null);
|
|
113
|
+
check("headers: the deprecated-trust-header warning is audited",
|
|
114
|
+
audit.captured.some(function (e) {
|
|
115
|
+
return e.action === "middleware.headers.threat-detected" &&
|
|
116
|
+
e.metadata && e.metadata.kind === "deprecated-trust-header";
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function testTrustProxySuppressesWarning() {
|
|
121
|
+
var mw = b.middleware.headers({ trustProxy: true });
|
|
122
|
+
var req = _req({ host: "x", "x-forwarded-for": "1.2.3.4" });
|
|
123
|
+
var res = _res();
|
|
124
|
+
var nextCalled = false;
|
|
125
|
+
mw(req, res, function () { nextCalled = true; });
|
|
126
|
+
check("headers: trustProxy opt-in suppresses the X-Forwarded-* warning",
|
|
127
|
+
nextCalled === true && res.statusCode === null);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function testAuditOnlyPassesHighSeverity() {
|
|
131
|
+
var audit = b.testing.captureAudit();
|
|
132
|
+
var mw = b.middleware.headers({ mode: "audit-only", audit: audit });
|
|
133
|
+
var req = _req({ host: "x", "x-note": "a\r\nb" });
|
|
134
|
+
var res = _res();
|
|
135
|
+
var nextCalled = false;
|
|
136
|
+
mw(req, res, function () { nextCalled = true; });
|
|
137
|
+
check("headers: audit-only passes a HIGH-severity request through",
|
|
138
|
+
nextCalled === true && res.statusCode === null);
|
|
139
|
+
check("headers: audit-only still emits the threat audit",
|
|
140
|
+
audit.captured.some(function (e) { return e.action === "middleware.headers.threat-detected"; }));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function run() {
|
|
144
|
+
testCleanHeadersPass();
|
|
145
|
+
testCrlfInValueRefused();
|
|
146
|
+
testClTeSmugglingRefused();
|
|
147
|
+
testMultiValueSmugglingRefused();
|
|
148
|
+
testHeaderCountCapRefused();
|
|
149
|
+
testValueByteCapRefused();
|
|
150
|
+
testInvalidHeaderNameShapeRefused();
|
|
151
|
+
testDeprecatedTrustHeaderWarnsButPasses();
|
|
152
|
+
testTrustProxySuppressesWarning();
|
|
153
|
+
testAuditOnlyPassesHighSeverity();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = { run: run };
|
|
157
|
+
|
|
158
|
+
if (require.main === module) {
|
|
159
|
+
Promise.resolve().then(run).then(
|
|
160
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
161
|
+
function (e) { console.error("FAIL:", e && e.message); process.exit(1); }
|
|
162
|
+
);
|
|
163
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.middleware.hostAllowlist — DNS-rebinding defense.
|
|
6
|
+
*
|
|
7
|
+
* Drives the Host-header allowlist: exact + wildcard-single-label
|
|
8
|
+
* matching, port-agnostic entries, refusal of an off-allowlist or
|
|
9
|
+
* missing Host with HTTP 421, the onDeny hook, and create-time
|
|
10
|
+
* validation.
|
|
11
|
+
*
|
|
12
|
+
* Run standalone: `node test/layer-0-primitives/middleware-host-allowlist.test.js`
|
|
13
|
+
* Or via smoke: `node test/smoke.js`
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
var helpers = require("../helpers");
|
|
17
|
+
var b = helpers.b;
|
|
18
|
+
var check = helpers.check;
|
|
19
|
+
var _mockReq = helpers._mockReq;
|
|
20
|
+
var _mockRes = helpers._mockRes;
|
|
21
|
+
|
|
22
|
+
function _drive(mw, host) {
|
|
23
|
+
var headers = (host === null || host === undefined) ? {} : { host: host };
|
|
24
|
+
var req = _mockReq({ method: "GET", url: "/", headers: headers });
|
|
25
|
+
var res = _mockRes();
|
|
26
|
+
var nextCalled = false;
|
|
27
|
+
mw(req, res, function () { nextCalled = true; });
|
|
28
|
+
var cap = res._captured();
|
|
29
|
+
cap.nextCalled = nextCalled;
|
|
30
|
+
// The problem+json path sets res.statusCode directly (not via
|
|
31
|
+
// writeHead), so surface that property alongside the writeHead status.
|
|
32
|
+
cap.statusCode = res.statusCode;
|
|
33
|
+
return cap;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function testExactHostAllowed() {
|
|
37
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["app.example.com"] });
|
|
38
|
+
var cap = _drive(mw, "app.example.com");
|
|
39
|
+
check("hostAllowlist: exact Host match passes through", cap.nextCalled === true);
|
|
40
|
+
check("hostAllowlist: allowed request writes no refusal", cap.status === null);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function testCaseInsensitiveMatch() {
|
|
44
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["app.example.com"] });
|
|
45
|
+
var cap = _drive(mw, "APP.Example.COM");
|
|
46
|
+
check("hostAllowlist: Host match is case-insensitive (RFC 7230 §5.4)",
|
|
47
|
+
cap.nextCalled === true);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function testWrongHostRefused() {
|
|
51
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["app.example.com"] });
|
|
52
|
+
var cap = _drive(mw, "attacker.evil.com");
|
|
53
|
+
check("hostAllowlist: off-allowlist Host refused with 421", cap.status === 421);
|
|
54
|
+
check("hostAllowlist: refusal does not delegate", cap.nextCalled === false);
|
|
55
|
+
check("hostAllowlist: default refusal body is Misdirected Request",
|
|
56
|
+
cap.body === "Misdirected Request");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function testMissingHostRefused() {
|
|
60
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["app.example.com"] });
|
|
61
|
+
var cap = _drive(mw, null);
|
|
62
|
+
check("hostAllowlist: missing Host header refused with 421", cap.status === 421);
|
|
63
|
+
check("hostAllowlist: missing Host does not delegate", cap.nextCalled === false);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function testWildcardSingleLabel() {
|
|
67
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["*.example.com"] });
|
|
68
|
+
var single = _drive(mw, "app.example.com");
|
|
69
|
+
check("hostAllowlist: wildcard matches a single label", single.nextCalled === true);
|
|
70
|
+
var multi = _drive(mw, "deep.app.example.com");
|
|
71
|
+
check("hostAllowlist: wildcard does NOT match multiple labels", multi.status === 421);
|
|
72
|
+
var apex = _drive(mw, "example.com");
|
|
73
|
+
check("hostAllowlist: wildcard does NOT match the bare apex", apex.status === 421);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function testPortAgnosticEntry() {
|
|
77
|
+
var mw = b.middleware.hostAllowlist({ hosts: ["app.example.com"] });
|
|
78
|
+
var cap = _drive(mw, "app.example.com:8443");
|
|
79
|
+
check("hostAllowlist: entry without a port matches any port", cap.nextCalled === true);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function testCustomDenyStatusAndBody() {
|
|
83
|
+
var mw = b.middleware.hostAllowlist({
|
|
84
|
+
hosts: ["app.example.com"],
|
|
85
|
+
denyStatus: 403,
|
|
86
|
+
denyBody: "Nope",
|
|
87
|
+
});
|
|
88
|
+
var cap = _drive(mw, "evil.com");
|
|
89
|
+
check("hostAllowlist: custom denyStatus honored", cap.status === 403);
|
|
90
|
+
check("hostAllowlist: custom denyBody honored", cap.body === "Nope");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function testOnDenyHookOwnsRefusal() {
|
|
94
|
+
var seen = null;
|
|
95
|
+
var mw = b.middleware.hostAllowlist({
|
|
96
|
+
hosts: ["app.example.com"],
|
|
97
|
+
onDeny: function (req, res, info) {
|
|
98
|
+
seen = info;
|
|
99
|
+
res.writeHead(499, { "Content-Type": "text/plain" });
|
|
100
|
+
res.end("blocked-by-hook");
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
var cap = _drive(mw, "evil.com");
|
|
104
|
+
check("hostAllowlist: onDeny hook owns the refusal response",
|
|
105
|
+
cap.status === 499 && cap.body === "blocked-by-hook");
|
|
106
|
+
check("hostAllowlist: onDeny info carries the reason + host",
|
|
107
|
+
seen && seen.reason === "host-not-in-allowlist" && seen.host === "evil.com");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function testProblemDetailsMode() {
|
|
111
|
+
var mw = b.middleware.hostAllowlist({
|
|
112
|
+
hosts: ["app.example.com"],
|
|
113
|
+
problemDetails: true,
|
|
114
|
+
});
|
|
115
|
+
var cap = _drive(mw, "evil.com");
|
|
116
|
+
check("hostAllowlist: problemDetails emits application/problem+json",
|
|
117
|
+
/application\/problem\+json/.test(cap.headers["content-type"] || ""));
|
|
118
|
+
check("hostAllowlist: problem document carries the 421 status",
|
|
119
|
+
cap.statusCode === 421);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function testCreateValidationThrows() {
|
|
123
|
+
function code(fn) {
|
|
124
|
+
try { fn(); return null; } catch (e) { return e.code || e.message; }
|
|
125
|
+
}
|
|
126
|
+
check("hostAllowlist: non-object opts throws",
|
|
127
|
+
code(function () { b.middleware.hostAllowlist(null); }) !== null);
|
|
128
|
+
check("hostAllowlist: empty hosts array throws",
|
|
129
|
+
/no-hosts/.test(code(function () { b.middleware.hostAllowlist({ hosts: [] }); })));
|
|
130
|
+
check("hostAllowlist: non-string host entry throws",
|
|
131
|
+
/bad-host/.test(code(function () { b.middleware.hostAllowlist({ hosts: [42] }); })));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function run() {
|
|
135
|
+
testExactHostAllowed();
|
|
136
|
+
testCaseInsensitiveMatch();
|
|
137
|
+
testWrongHostRefused();
|
|
138
|
+
testMissingHostRefused();
|
|
139
|
+
testWildcardSingleLabel();
|
|
140
|
+
testPortAgnosticEntry();
|
|
141
|
+
testCustomDenyStatusAndBody();
|
|
142
|
+
testOnDenyHookOwnsRefusal();
|
|
143
|
+
testProblemDetailsMode();
|
|
144
|
+
testCreateValidationThrows();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = { run: run };
|
|
148
|
+
|
|
149
|
+
if (require.main === module) {
|
|
150
|
+
Promise.resolve().then(run).then(
|
|
151
|
+
function () { console.log("OK — " + helpers.getChecks() + " checks passed"); },
|
|
152
|
+
function (e) { console.error("FAIL:", e && e.message); process.exit(1); }
|
|
153
|
+
);
|
|
154
|
+
}
|