@blamejs/blamejs-shop 0.5.12 → 0.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/sales-tax-filings.js +143 -0
- 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
|
@@ -512,6 +512,13 @@ var ATTESTATION_ALGS = Object.freeze([
|
|
|
512
512
|
"EdDSA",
|
|
513
513
|
]);
|
|
514
514
|
|
|
515
|
+
// draft-ietf-oauth-attestation-based-client-auth §4.1 / §5.1 — the REQUIRED,
|
|
516
|
+
// distinct `typ` header of each JWT. One literal per role, used by BOTH the
|
|
517
|
+
// builders (the value we emit) and the verifier (the value we pin) so the
|
|
518
|
+
// produced typ and the checked typ can never drift apart.
|
|
519
|
+
var ATTESTATION_JWT_TYP = "oauth-client-attestation+jwt";
|
|
520
|
+
var ATTESTATION_POP_JWT_TYP = "oauth-client-attestation-pop+jwt";
|
|
521
|
+
|
|
515
522
|
// Cap on an attestation / PoP JWT. HTTP-header-borne JWTs are small;
|
|
516
523
|
// 16 KiB refuses a pathological header without touching real tokens.
|
|
517
524
|
var MAX_ATTESTATION_JWT_BYTES = C.BYTES.kib(16);
|
|
@@ -582,7 +589,10 @@ function _signAttestationJws(header, payload, privateKey, alg) {
|
|
|
582
589
|
// Verify a compact JWS against an already-imported public KeyObject. The
|
|
583
590
|
// alg is read from the header but MUST equal expectedAlg AND match the
|
|
584
591
|
// key's kty (via the shared cross-check) — no alg-confusion window.
|
|
585
|
-
|
|
592
|
+
// `expectedTyp` (when supplied) pins the JOSE `typ` header so a JWT minted
|
|
593
|
+
// for another purpose but signed by the same key can't be replayed into the
|
|
594
|
+
// attestation / PoP slot.
|
|
595
|
+
function _verifyAttestationJws(jws, publicKeyJwk, label, expectedTyp) {
|
|
586
596
|
if (typeof jws !== "string" || jws.length === 0) {
|
|
587
597
|
throw new OAuthError("auth-oauth/attestation-malformed", label + ": JWT must be a non-empty string");
|
|
588
598
|
}
|
|
@@ -618,6 +628,18 @@ function _verifyAttestationJws(jws, publicKeyJwk, label) {
|
|
|
618
628
|
throw new OAuthError("auth-oauth/attestation-crit-not-supported",
|
|
619
629
|
label + ": JWS 'crit' header is not supported (RFC 7515 §4.1.11)");
|
|
620
630
|
}
|
|
631
|
+
// Explicit typing (RFC 8725 §3.11 / draft-ietf-oauth-attestation-based-
|
|
632
|
+
// client-auth §6): the attestation and PoP JWTs each carry a REQUIRED,
|
|
633
|
+
// distinct `typ`. Pinning it stops a JWT minted for a different purpose
|
|
634
|
+
// but signed by the same key (a private_key_jwt client assertion, another
|
|
635
|
+
// proof-of-possession JWT) from being replayed into the attestation / PoP
|
|
636
|
+
// slot — the cross-JWT confused-deputy class. The framework's other JWS
|
|
637
|
+
// verifiers already pin typ (dpop+jwt, logout+jwt); this one now matches.
|
|
638
|
+
if (typeof expectedTyp === "string" && header.typ !== expectedTyp) {
|
|
639
|
+
throw new OAuthError("auth-oauth/attestation-wrong-typ",
|
|
640
|
+
label + ": header.typ must be '" + expectedTyp + "' (RFC 8725 §3.11 " +
|
|
641
|
+
"explicit typing); got " + JSON.stringify(header.typ));
|
|
642
|
+
}
|
|
621
643
|
// CVE-2026-22817 — cross-check alg against the key's kty before verify.
|
|
622
644
|
jwtExternal._assertAlgKtyMatch(header.alg, publicKeyJwk);
|
|
623
645
|
var keyObject = _jwkToKey(publicKeyJwk);
|
|
@@ -744,7 +766,7 @@ function buildClientAttestation(aopts) {
|
|
|
744
766
|
validateOpts.assignOwnEnumerable(payload, aopts.extraClaims, Object.keys(payload));
|
|
745
767
|
}
|
|
746
768
|
return _signAttestationJws(
|
|
747
|
-
{ typ:
|
|
769
|
+
{ typ: ATTESTATION_JWT_TYP, alg: alg }, payload, key, alg);
|
|
748
770
|
}
|
|
749
771
|
|
|
750
772
|
/**
|
|
@@ -819,7 +841,7 @@ function buildClientAttestationPop(popts) {
|
|
|
819
841
|
payload.challenge = popts.challenge; // draft §5.2 — server nonce
|
|
820
842
|
}
|
|
821
843
|
return _signAttestationJws(
|
|
822
|
-
{ typ:
|
|
844
|
+
{ typ: ATTESTATION_POP_JWT_TYP, alg: alg }, payload, key, alg);
|
|
823
845
|
}
|
|
824
846
|
|
|
825
847
|
/**
|
|
@@ -878,7 +900,8 @@ async function verifyClientAttestation(attestationJwt, popJwt, vopts) {
|
|
|
878
900
|
"auth-oauth/attestation-no-expected-aud");
|
|
879
901
|
|
|
880
902
|
// 1. Attestation signature against the TRUSTED attester key.
|
|
881
|
-
var att = _verifyAttestationJws(attestationJwt, vopts.attesterJwk, "client-attestation"
|
|
903
|
+
var att = _verifyAttestationJws(attestationJwt, vopts.attesterJwk, "client-attestation",
|
|
904
|
+
ATTESTATION_JWT_TYP);
|
|
882
905
|
var ap = att.payload || {};
|
|
883
906
|
if (typeof ap.sub !== "string" || ap.sub.length === 0) {
|
|
884
907
|
throw new OAuthError("auth-oauth/attestation-no-sub",
|
|
@@ -912,7 +935,8 @@ async function verifyClientAttestation(attestationJwt, popJwt, vopts) {
|
|
|
912
935
|
}
|
|
913
936
|
|
|
914
937
|
// 2. PoP signature against the attestation's cnf key (NOT the attester).
|
|
915
|
-
var pop = _verifyAttestationJws(popJwt, ap.cnf.jwk, "client-attestation-pop"
|
|
938
|
+
var pop = _verifyAttestationJws(popJwt, ap.cnf.jwk, "client-attestation-pop",
|
|
939
|
+
ATTESTATION_POP_JWT_TYP);
|
|
916
940
|
var pp = pop.payload || {};
|
|
917
941
|
// aud MUST be THIS AS issuer (constant-time, exact). Attacker-replayed
|
|
918
942
|
// PoP minted for a different AS is refused (draft §8 step 7).
|
|
@@ -1123,6 +1147,16 @@ function create(opts) {
|
|
|
1123
1147
|
backchannelAuthenticationEndpoint:
|
|
1124
1148
|
opts.backchannelAuthenticationEndpoint ||
|
|
1125
1149
|
(preset && preset.backchannelAuthenticationEndpoint) || null,
|
|
1150
|
+
// _resolveEndpoint maps these three snake-case discovery keys, and the
|
|
1151
|
+
// introspect / register / device-grant primitives resolve through it. A
|
|
1152
|
+
// static (non-discovery) client must be able to supply them as opts —
|
|
1153
|
+
// introspectToken's own no-endpoint refusal tells operators to set
|
|
1154
|
+
// opts.introspectionEndpoint, so create() has to actually read it.
|
|
1155
|
+
introspectionEndpoint: opts.introspectionEndpoint || (preset && preset.introspectionEndpoint) || null,
|
|
1156
|
+
registrationEndpoint: opts.registrationEndpoint || (preset && preset.registrationEndpoint) || null,
|
|
1157
|
+
deviceAuthorizationEndpoint:
|
|
1158
|
+
opts.deviceAuthorizationEndpoint ||
|
|
1159
|
+
(preset && preset.deviceAuthorizationEndpoint) || null,
|
|
1126
1160
|
};
|
|
1127
1161
|
|
|
1128
1162
|
// Discovery + JWKS caches use b.cache.create + .wrap so concurrent
|
|
@@ -1746,20 +1780,43 @@ function create(opts) {
|
|
|
1746
1780
|
|
|
1747
1781
|
async function _normalizeTokens(raw, vopts) {
|
|
1748
1782
|
vopts = vopts || {};
|
|
1783
|
+
// RFC 6749 §3.3 — scope is space-separated, ONLY U+0020. `\s+` previously
|
|
1784
|
+
// matched U+0085 NEL, U+00A0 NBSP, etc., so a hostile AS returning
|
|
1785
|
+
// `scope: "admin<NEL>read"` would surface as `["admin", "read"]` and the
|
|
1786
|
+
// operator's scope allowlist saw two distinct scopes. Spec-strict split on
|
|
1787
|
+
// single-space keeps a non-token separator inside one token.
|
|
1788
|
+
//
|
|
1789
|
+
// §5.1 also fixes the PRESENT-vs-ABSENT distinction that a bare truthiness
|
|
1790
|
+
// test lost: an ABSENT scope ("OPTIONAL, if identical to the requested
|
|
1791
|
+
// scope") means the client got what it asked for → mirror the request; a
|
|
1792
|
+
// PRESENT scope is authoritative, INCLUDING the empty string, which grants
|
|
1793
|
+
// ZERO scopes. Coercing "" to the requested set (its falsy value slipped
|
|
1794
|
+
// the old `raw.scope ? …` test into the absent branch) would report a
|
|
1795
|
+
// downscoped-to-nothing grant as the full requested set — a scope-based
|
|
1796
|
+
// authorization guard downstream then treats denied scopes as granted. A
|
|
1797
|
+
// malformed non-string scope is treated as zero (fail closed), never as
|
|
1798
|
+
// the requested set.
|
|
1799
|
+
var grantedScope;
|
|
1800
|
+
if (typeof raw.scope === "string") {
|
|
1801
|
+
grantedScope = raw.scope.split(" ").filter(function (s) { return s.length > 0; });
|
|
1802
|
+
} else if (raw.scope === undefined) {
|
|
1803
|
+
// ONLY a truly ABSENT property (undefined) mirrors the request (RFC 6749
|
|
1804
|
+
// §3.3 "OPTIONAL, if identical to the requested scope"). A PRESENT but
|
|
1805
|
+
// malformed value — `null`, a number, an object — is NOT an omitted
|
|
1806
|
+
// scope; treating `{ "scope": null }` as absent would copy the full
|
|
1807
|
+
// requested set and report a grant the AS never made. Fall through to
|
|
1808
|
+
// zero (fail closed).
|
|
1809
|
+
grantedScope = scope.slice();
|
|
1810
|
+
} else {
|
|
1811
|
+
grantedScope = [];
|
|
1812
|
+
}
|
|
1749
1813
|
var tokens = {
|
|
1750
1814
|
accessToken: raw.access_token,
|
|
1751
1815
|
tokenType: raw.token_type || "Bearer",
|
|
1752
1816
|
expiresIn: raw.expires_in || null,
|
|
1753
1817
|
refreshToken: raw.refresh_token || null,
|
|
1754
1818
|
idToken: raw.id_token || null,
|
|
1755
|
-
|
|
1756
|
-
// `\s+` previously matched U+0085 NEL, U+00A0 NBSP, etc., so a
|
|
1757
|
-
// hostile AS returning `scope: "admin<NEL>read"` would
|
|
1758
|
-
// surface as `["admin", "read"]` and the operator's scope
|
|
1759
|
-
// allowlist saw two distinct scopes. Spec-strict split on
|
|
1760
|
-
// single-space + reject scope tokens that contain non-token
|
|
1761
|
-
// chars.
|
|
1762
|
-
scope: raw.scope ? raw.scope.split(" ").filter(function (s) { return s.length > 0; }) : scope.slice(),
|
|
1819
|
+
scope: grantedScope,
|
|
1763
1820
|
raw: raw,
|
|
1764
1821
|
};
|
|
1765
1822
|
if (tokens.idToken && isOidc) {
|
|
@@ -1970,6 +2027,16 @@ function create(opts) {
|
|
|
1970
2027
|
if (typeof payload.nbf === "number" && payload.nbf - skewSec > now) {
|
|
1971
2028
|
throw new OAuthError("auth-oauth/nbf-future", "ID token nbf is in the future");
|
|
1972
2029
|
}
|
|
2030
|
+
if (isOidc && !issuer) {
|
|
2031
|
+
// An OIDC id_token carries an `iss` that MUST be validated against a
|
|
2032
|
+
// configured expected issuer (OIDC Core §3.1.3.7). With no issuer set the
|
|
2033
|
+
// iss comparison below would be skipped entirely — the CVE-2026-23552
|
|
2034
|
+
// cross-realm acceptance this verifier exists to close. Fail closed
|
|
2035
|
+
// rather than accept an id_token whose issuer can't be authenticated.
|
|
2036
|
+
throw new OAuthError("auth-oauth/issuer-required",
|
|
2037
|
+
"verifyIdToken: an OIDC client must be configured with `issuer` to validate the " +
|
|
2038
|
+
"id_token's iss (OIDC Core 3.1.3.7 / cross-realm-JWT defense); pass issuer to b.auth.oauth.create()");
|
|
2039
|
+
}
|
|
1973
2040
|
if (issuer) {
|
|
1974
2041
|
// CVE-2026-23552 — cross-realm / cross-issuer JWT acceptance. The
|
|
1975
2042
|
// expected issuer is operator-supplied; payload.iss is attacker-
|
|
@@ -2859,6 +2926,16 @@ function create(opts) {
|
|
|
2859
2926
|
if (allowHttp) req.allowedProtocols = safeUrl.ALLOW_HTTP_ALL;
|
|
2860
2927
|
if (allowInternal !== null) req.allowInternal = allowInternal;
|
|
2861
2928
|
Object.assign(req, httpClientOpts);
|
|
2929
|
+
// RFC 8628 §3.5 / RFC 6749 §5.2 return the device-grant errors
|
|
2930
|
+
// (authorization_pending / slow_down and the terminal codes) as an
|
|
2931
|
+
// HTTP 400 whose body carries `error`. The loop below reads that body,
|
|
2932
|
+
// so the token request MUST NOT let b.httpClient reject the 4xx first —
|
|
2933
|
+
// the default buffer mode would throw before the pending/slow_down/
|
|
2934
|
+
// terminal handling runs, aborting the grant on the first poll (which
|
|
2935
|
+
// is almost always authorization_pending). Force always-resolve AFTER
|
|
2936
|
+
// merging httpClientOpts so an operator override cannot silently
|
|
2937
|
+
// reinstate buffer mode.
|
|
2938
|
+
req.responseMode = "always-resolve";
|
|
2862
2939
|
var res = await hc.request(req);
|
|
2863
2940
|
var text = res.body ? res.body.toString("utf8") : "";
|
|
2864
2941
|
var parsed;
|
|
@@ -190,26 +190,29 @@ async function _verifyProofJwt(proofJwt, expectedAud, expectedCNonce, expectedCl
|
|
|
190
190
|
throw new AuthError("auth-oid4vci/wrong-proof-aud",
|
|
191
191
|
"credential issuance: proof JWT aud \"" + payload.aud + "\" mismatch (expected \"" + expectedAud + "\")");
|
|
192
192
|
}
|
|
193
|
-
// c_nonce
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
|
|
193
|
+
// The c_nonce is the OID4VCI proof replay + holder-binding challenge
|
|
194
|
+
// (§7.2.1.1). Every access token is minted with a c_nonce in
|
|
195
|
+
// exchangePreAuthorizedCode, so a missing value at /credential means the
|
|
196
|
+
// c_nonce TTL elapsed (shorter than the access token's) — it MUST refuse
|
|
197
|
+
// and force the wallet to fetch a fresh one. There is NO issuance mode
|
|
198
|
+
// that legitimately skips the compare, so `expectedCNonce` is required to
|
|
199
|
+
// be a non-empty string. Fail closed on ANY other shape: a conforming
|
|
200
|
+
// b.cache signals a miss with `undefined`, but a store fronting Redis /
|
|
201
|
+
// a Map / a SQL row commonly signals a miss with `null`; the prior
|
|
202
|
+
// `!== null` guard let that null fall THROUGH the nonce compare entirely,
|
|
203
|
+
// silently disabling the replay defense (a forged proof with any nonce
|
|
204
|
+
// was then accepted). Treating undefined / null / non-string uniformly
|
|
205
|
+
// as "expired" closes that store-shape fail-open.
|
|
206
|
+
if (typeof expectedCNonce !== "string" || expectedCNonce.length === 0) {
|
|
202
207
|
throw new AuthError("auth-oid4vci/c-nonce-expired",
|
|
203
208
|
"credential issuance: c_nonce expected but missing/expired — wallet must request a fresh c_nonce (the /token response's c_nonce TTL elapsed before /credential was called)");
|
|
204
209
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
"credential issuance: proof JWT nonce mismatch (replay defense — wallet must use the c_nonce from the most recent issuer response)");
|
|
212
|
-
}
|
|
210
|
+
// Constant-time c_nonce compare — secret-shaped value vs
|
|
211
|
+
// attacker-controlled wallet payload.
|
|
212
|
+
if (typeof payload.nonce !== "string" ||
|
|
213
|
+
!timingSafeEqual(payload.nonce, expectedCNonce)) {
|
|
214
|
+
throw new AuthError("auth-oid4vci/wrong-proof-nonce",
|
|
215
|
+
"credential issuance: proof JWT nonce mismatch (replay defense — wallet must use the c_nonce from the most recent issuer response)");
|
|
213
216
|
}
|
|
214
217
|
if (typeof payload.iat !== "number") {
|
|
215
218
|
throw new AuthError("auth-oid4vci/no-proof-iat",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
var lazyRequire = require("../lazy-require");
|
|
60
60
|
var validateOpts = require("../validate-opts");
|
|
61
61
|
var safeJson = require("../safe-json");
|
|
62
|
+
var pick = require("../pick");
|
|
62
63
|
var nodeCrypto = require("node:crypto");
|
|
63
64
|
var bCrypto = require("../crypto");
|
|
64
65
|
var C = require("../constants");
|
|
@@ -240,11 +241,151 @@ function verifyEntityStatement(jwt, jwks, vopts) {
|
|
|
240
241
|
return parsed.claims;
|
|
241
242
|
}
|
|
242
243
|
|
|
244
|
+
// ---- Metadata-policy set-ops + cross-level merge (OIDF 1.0 section 6.1.5) ----
|
|
245
|
+
|
|
246
|
+
// Union of two arrays (dedupe, first-seen order). The single array set-op the
|
|
247
|
+
// `add` / `superset_of` operators and the cross-level merge both compose,
|
|
248
|
+
// rather than hand-rolling the shape per call site.
|
|
249
|
+
function _arrayUnion(a, b) {
|
|
250
|
+
var out = Array.isArray(a) ? a.slice() : [];
|
|
251
|
+
if (Array.isArray(b)) {
|
|
252
|
+
b.forEach(function (v) { if (out.indexOf(v) === -1) out.push(v); });
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Intersection of two arrays (values in both, a's order). The narrowing op the
|
|
258
|
+
// merge uses for `one_of` / `subset_of`: a subordinate can only narrow.
|
|
259
|
+
function _arrayIntersect(a, b) {
|
|
260
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return [];
|
|
261
|
+
return a.filter(function (v) { return b.indexOf(v) !== -1; });
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// a is a subset of b: every element of `a` is present in `b`. The set-op the
|
|
265
|
+
// OIDF 1.0 section 6.1.3 combination-consistency rules compose (add within
|
|
266
|
+
// subset_of, default within subset_of, superset_of within subset_of, ...).
|
|
267
|
+
function _arraySubset(a, b) {
|
|
268
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return false;
|
|
269
|
+
return a.every(function (v) { return b.indexOf(v) !== -1; });
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// View a metadata value as an array for the array policy operators. OAuth
|
|
273
|
+
// `scope` (and similar parameters) is a space-delimited string that OIDF 1.0
|
|
274
|
+
// section 6.1.3.1.8 processes as a string array, so a string is split on
|
|
275
|
+
// whitespace; an array is returned as-is; anything else yields null (the
|
|
276
|
+
// caller decides whether an absent / malformed value is a violation).
|
|
277
|
+
function _coerceOperandArray(val) {
|
|
278
|
+
if (Array.isArray(val)) return val;
|
|
279
|
+
if (typeof val === "string") return val.split(/\s+/).filter(Boolean);
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// OIDF 1.0 section 6.1.3 fixed operator processing order: the value-MODIFICATION
|
|
284
|
+
// operators (value, add, default) run first to produce the value, then the
|
|
285
|
+
// value-CHECK operators (one_of, subset_of, superset_of, essential) validate it.
|
|
286
|
+
var _OP_ORDER = ["value", "add", "default", "one_of", "subset_of", "superset_of", "essential"];
|
|
287
|
+
|
|
288
|
+
// Validate a merged claim's operator set for the two cross-level cases the
|
|
289
|
+
// fixed-order apply step cannot catch on its own. The apply step already runs
|
|
290
|
+
// every merged CHECK operator (one_of / subset_of / superset_of / essential)
|
|
291
|
+
// against the FINAL value the MODIFIER operators (value / add / default)
|
|
292
|
+
// produced -- coercing a space-delimited scope string to an array -- so a
|
|
293
|
+
// value, add, or default inconsistent with a co-present constraint is refused
|
|
294
|
+
// there against the merged (most-restrictive) constraint. This adds only what
|
|
295
|
+
// apply cannot see:
|
|
296
|
+
// (1) `value` + `add` where `add` would WIDEN the exact pin -- the union
|
|
297
|
+
// escapes `value`, and with no constraint operator present the apply step
|
|
298
|
+
// has nothing to reject it. `add` already within `value` is a no-op,
|
|
299
|
+
// allowed (OIDF 1.0 section 6.1.3.1.1).
|
|
300
|
+
// (2) a `one_of` whose cross-level intersection is EMPTY -- no value can ever
|
|
301
|
+
// satisfy the chain, a policy error per section 6.1.3.1.4 rather than a
|
|
302
|
+
// silent accept-when-absent.
|
|
303
|
+
// Same-operator value/default equality is checked during the merge itself.
|
|
304
|
+
function _assertPolicyCombination(claim, acc) {
|
|
305
|
+
function has(op) { return Object.prototype.hasOwnProperty.call(acc, op); }
|
|
306
|
+
function conflict(why) {
|
|
307
|
+
throw new AuthError("auth-openid-federation/policy-merge-conflict",
|
|
308
|
+
"metadata_policy['" + claim + "']: " + why +
|
|
309
|
+
" (a subordinate cannot widen a superior's constraint)");
|
|
310
|
+
}
|
|
311
|
+
if (has("value") && has("add")) {
|
|
312
|
+
var pinned = _coerceOperandArray(acc.value) || [acc.value];
|
|
313
|
+
if (!_arraySubset(acc.add, pinned)) {
|
|
314
|
+
conflict("`add` would widen the pinned `value`");
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (has("one_of") && acc.one_of.length === 0) {
|
|
318
|
+
conflict("`one_of` values are disjoint across the chain (no allowed value remains)");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Combine the metadata_policy blocks from EVERY chain level into ONE policy per
|
|
323
|
+
// OIDF 1.0 section 6.1.5.3, so a subordinate can only NARROW a superior's
|
|
324
|
+
// constraint, never override it, and the combined policy is applied ONCE. Two
|
|
325
|
+
// levels pinning a DIFFERENT `value` (or `default`) is a cross-level conflict
|
|
326
|
+
// that makes the chain invalid and throws -- the pre-merge sequential apply let
|
|
327
|
+
// a leaf-ward `value` silently OVERWRITE the anchor's pinned value, a trust
|
|
328
|
+
// downgrade (e.g. token_endpoint_auth_method private_key_jwt -> none) the anchor
|
|
329
|
+
// forbade. `blocks` are ordered superior-first (anchor policy first).
|
|
330
|
+
function _mergeMetadataPolicies(blocks) {
|
|
331
|
+
var merged = Object.create(null);
|
|
332
|
+
blocks.forEach(function (block) {
|
|
333
|
+
Object.keys(block).forEach(function (claim) {
|
|
334
|
+
if (pick.isPoisonedKey(claim)) {
|
|
335
|
+
throw new AuthError("auth-openid-federation/poisoned-policy-key",
|
|
336
|
+
"metadata_policy claim name \"" + claim + "\" is a prototype-pollution vector");
|
|
337
|
+
}
|
|
338
|
+
var rules = block[claim];
|
|
339
|
+
if (!rules || typeof rules !== "object") {
|
|
340
|
+
throw new AuthError("auth-openid-federation/bad-policy-rules",
|
|
341
|
+
"metadata_policy['" + claim + "'] must be an object");
|
|
342
|
+
}
|
|
343
|
+
var acc = merged[claim] || (merged[claim] = {});
|
|
344
|
+
Object.keys(rules).forEach(function (op) {
|
|
345
|
+
var v = rules[op];
|
|
346
|
+
if (op === "value" || op === "default") {
|
|
347
|
+
if (Object.prototype.hasOwnProperty.call(acc, op) &&
|
|
348
|
+
JSON.stringify(acc[op]) !== JSON.stringify(v)) {
|
|
349
|
+
throw new AuthError("auth-openid-federation/policy-merge-conflict",
|
|
350
|
+
"metadata_policy['" + claim + "']." + op + " conflicts across the chain (" +
|
|
351
|
+
JSON.stringify(acc[op]) + " vs " + JSON.stringify(v) +
|
|
352
|
+
"): a subordinate cannot override a superior's pinned " + op);
|
|
353
|
+
}
|
|
354
|
+
acc[op] = v;
|
|
355
|
+
} else if (op === "add" || op === "superset_of") {
|
|
356
|
+
if (!Array.isArray(v)) {
|
|
357
|
+
throw new AuthError("auth-openid-federation/bad-policy-" + (op === "add" ? "add" : "superset-of"),
|
|
358
|
+
"metadata_policy['" + claim + "']." + op + " requires an array");
|
|
359
|
+
}
|
|
360
|
+
acc[op] = _arrayUnion(acc[op], v);
|
|
361
|
+
} else if (op === "one_of" || op === "subset_of") {
|
|
362
|
+
if (!Array.isArray(v)) {
|
|
363
|
+
throw new AuthError("auth-openid-federation/bad-policy-" + (op === "one_of" ? "one-of" : "subset-of"),
|
|
364
|
+
"metadata_policy['" + claim + "']." + op + " requires an array");
|
|
365
|
+
}
|
|
366
|
+
acc[op] = Object.prototype.hasOwnProperty.call(acc, op) ? _arrayIntersect(acc[op], v) : v.slice();
|
|
367
|
+
} else if (op === "essential") {
|
|
368
|
+
acc[op] = acc[op] === true || v === true;
|
|
369
|
+
} else {
|
|
370
|
+
throw new AuthError("auth-openid-federation/unknown-policy-op",
|
|
371
|
+
"metadata_policy['" + claim + "'] unknown operator \"" + op + "\"");
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
Object.keys(merged).forEach(function (claim) { _assertPolicyCombination(claim, merged[claim]); });
|
|
377
|
+
return merged;
|
|
378
|
+
}
|
|
379
|
+
|
|
243
380
|
/**
|
|
244
|
-
* Apply
|
|
245
|
-
* return the resulting object. Pure — never mutates input.
|
|
381
|
+
* Apply an already-merged metadata_policy block to a metadata object and
|
|
382
|
+
* return the resulting object. Pure — never mutates input. Operators are
|
|
383
|
+
* applied in the OIDF 1.0 §6.1.3 fixed order (value, add, default, one_of,
|
|
384
|
+
* subset_of, superset_of, essential) so the value-CHECK operators validate the
|
|
385
|
+
* value the value-MODIFICATION operators produced; the combined policy's
|
|
386
|
+
* operator combination was validated during the merge (_assertPolicyCombination).
|
|
246
387
|
*
|
|
247
|
-
* Operators per OIDF §6.
|
|
388
|
+
* Operators per OIDF 1.0 §6.1.3:
|
|
248
389
|
* value — set claim to a fixed value (overrides subordinate)
|
|
249
390
|
* add — array claim: append values not already present
|
|
250
391
|
* default — provide a default if the claim is absent
|
|
@@ -254,14 +395,34 @@ function verifyEntityStatement(jwt, jwks, vopts) {
|
|
|
254
395
|
* essential — claim must be present (else throw)
|
|
255
396
|
*/
|
|
256
397
|
function _applyOnePolicy(metadata, policy) {
|
|
257
|
-
|
|
398
|
+
// Build the working copy from own, non-prototype-polluting keys only -- a
|
|
399
|
+
// metadata object carrying a "__proto__" / "constructor" / "prototype" own
|
|
400
|
+
// key (e.g. from JSON.parse) would otherwise set out's prototype via
|
|
401
|
+
// assignment; the merged policy's claim names are already poison-guarded.
|
|
402
|
+
var out = {};
|
|
403
|
+
Object.keys(metadata).forEach(function (mk) {
|
|
404
|
+
if (!pick.isPoisonedKey(mk)) out[mk] = metadata[mk];
|
|
405
|
+
});
|
|
258
406
|
Object.keys(policy).forEach(function (claimName) {
|
|
407
|
+
if (pick.isPoisonedKey(claimName)) return;
|
|
259
408
|
var rules = policy[claimName];
|
|
260
409
|
if (!rules || typeof rules !== "object") {
|
|
261
410
|
throw new AuthError("auth-openid-federation/bad-policy-rules",
|
|
262
411
|
"metadata_policy['" + claimName + "'] must be an object");
|
|
263
412
|
}
|
|
413
|
+
// Apply operators in the OIDF 1.0 section 6.1.3 fixed order so the
|
|
414
|
+
// value-CHECK operators (one_of/subset_of/superset_of/essential) validate
|
|
415
|
+
// the value AFTER the value-MODIFICATION operators (value/add/default) have
|
|
416
|
+
// produced it -- Object.keys order let a check run before the value it must
|
|
417
|
+
// guard was set. Any operator outside the fixed set is refused first.
|
|
264
418
|
Object.keys(rules).forEach(function (op) {
|
|
419
|
+
if (_OP_ORDER.indexOf(op) === -1) {
|
|
420
|
+
throw new AuthError("auth-openid-federation/unknown-policy-op",
|
|
421
|
+
"metadata_policy['" + claimName + "'] unknown operator \"" + op + "\"");
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
_OP_ORDER.forEach(function (op) {
|
|
425
|
+
if (!Object.prototype.hasOwnProperty.call(rules, op)) return;
|
|
265
426
|
var v = rules[op];
|
|
266
427
|
switch (op) {
|
|
267
428
|
case "value":
|
|
@@ -275,8 +436,8 @@ function _applyOnePolicy(metadata, policy) {
|
|
|
275
436
|
throw new AuthError("auth-openid-federation/bad-policy-add",
|
|
276
437
|
"metadata_policy['" + claimName + "'].add requires an array");
|
|
277
438
|
}
|
|
278
|
-
|
|
279
|
-
|
|
439
|
+
var _addResult = _arrayUnion(_coerceOperandArray(out[claimName]) || [], v);
|
|
440
|
+
out[claimName] = typeof out[claimName] === "string" ? _addResult.join(" ") : _addResult;
|
|
280
441
|
break;
|
|
281
442
|
case "one_of":
|
|
282
443
|
if (!Array.isArray(v)) {
|
|
@@ -294,8 +455,14 @@ function _applyOnePolicy(metadata, policy) {
|
|
|
294
455
|
throw new AuthError("auth-openid-federation/bad-policy-subset-of",
|
|
295
456
|
"metadata_policy['" + claimName + "'].subset_of requires an array");
|
|
296
457
|
}
|
|
297
|
-
if (
|
|
298
|
-
out[claimName]
|
|
458
|
+
if (out[claimName] !== undefined && out[claimName] !== null) {
|
|
459
|
+
var _subArr = _coerceOperandArray(out[claimName]);
|
|
460
|
+
if (_subArr === null) {
|
|
461
|
+
throw new AuthError("auth-openid-federation/policy-subset-of-failed",
|
|
462
|
+
"metadata_policy['" + claimName + "']: value " + JSON.stringify(out[claimName]) +
|
|
463
|
+
" is neither an array nor a space-delimited string; subset_of constrains an array-valued claim");
|
|
464
|
+
}
|
|
465
|
+
_subArr.forEach(function (val) {
|
|
299
466
|
if (v.indexOf(val) === -1) {
|
|
300
467
|
throw new AuthError("auth-openid-federation/policy-subset-of-failed",
|
|
301
468
|
"metadata_policy['" + claimName + "']: value \"" + JSON.stringify(val) +
|
|
@@ -309,8 +476,9 @@ function _applyOnePolicy(metadata, policy) {
|
|
|
309
476
|
throw new AuthError("auth-openid-federation/bad-policy-superset-of",
|
|
310
477
|
"metadata_policy['" + claimName + "'].superset_of requires an array");
|
|
311
478
|
}
|
|
479
|
+
var _supArr = _coerceOperandArray(out[claimName]) || [];
|
|
312
480
|
v.forEach(function (req) {
|
|
313
|
-
if (
|
|
481
|
+
if (_supArr.indexOf(req) === -1) {
|
|
314
482
|
throw new AuthError("auth-openid-federation/policy-superset-of-failed",
|
|
315
483
|
"metadata_policy['" + claimName + "']: missing required value \"" + req + "\"");
|
|
316
484
|
}
|
|
@@ -350,9 +518,11 @@ function _applyOnePolicy(metadata, policy) {
|
|
|
350
518
|
* own self-config metadata_policy is therefore ignored.
|
|
351
519
|
*
|
|
352
520
|
* The chain is leaf-first; each `chain[i].subordinate` is the statement
|
|
353
|
-
* signed by the superior directly above entity `i
|
|
354
|
-
*
|
|
355
|
-
*
|
|
521
|
+
* signed by the superior directly above entity `i`; every level's policy
|
|
522
|
+
* is merged into ONE combined policy so a subordinate can only NARROW a
|
|
523
|
+
* superior's constraint (a leaf-ward level pinning a different
|
|
524
|
+
* value/default refuses the chain as a trust downgrade), then applied
|
|
525
|
+
* once (OIDF 1.0 §6.1.5.3).
|
|
356
526
|
*
|
|
357
527
|
* @example
|
|
358
528
|
* var effective = b.auth.openidFederation.applyMetadataPolicy(
|
|
@@ -371,21 +541,27 @@ function applyMetadataPolicy(metadata, chain, kind) {
|
|
|
371
541
|
throw new AuthError("auth-openid-federation/bad-chain",
|
|
372
542
|
"applyMetadataPolicy: chain must be an array");
|
|
373
543
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
//
|
|
544
|
+
Object.keys(metadata).forEach(function (mk) {
|
|
545
|
+
if (pick.isPoisonedKey(mk)) {
|
|
546
|
+
throw new AuthError("auth-openid-federation/poisoned-metadata-key",
|
|
547
|
+
"applyMetadataPolicy: metadata key \"" + mk + "\" is a prototype-pollution vector");
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
// Gather each SUPERIOR-SIGNED subordinate statement's policy for this kind,
|
|
551
|
+
// superior-first (anchor policy first; the anchor node terminates the chain
|
|
552
|
+
// with no .subordinate, and the leaf's own self-config policy is never read),
|
|
553
|
+
// then MERGE every level into ONE combined policy so a subordinate can only
|
|
554
|
+
// NARROW a superior's constraint (OIDF 1.0 section 6.1.5.3) -- a leaf-ward
|
|
555
|
+
// level pinning a different value/default is a conflict that refuses the
|
|
556
|
+
// chain -- and apply the merged policy ONCE.
|
|
557
|
+
var blocks = [];
|
|
381
558
|
for (var i = chain.length - 1; i >= 0; i--) {
|
|
382
559
|
var stmt = chain[i];
|
|
383
560
|
if (!stmt || !stmt.subordinate) continue;
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
561
|
+
var mp = stmt.subordinate.metadata_policy;
|
|
562
|
+
if (mp && mp[kind]) blocks.push(mp[kind]);
|
|
387
563
|
}
|
|
388
|
-
return
|
|
564
|
+
return _applyOnePolicy(Object.assign({}, metadata), _mergeMetadataPolicies(blocks));
|
|
389
565
|
}
|
|
390
566
|
|
|
391
567
|
async function _defaultFetcher(url) {
|
|
@@ -593,6 +769,21 @@ async function buildTrustChain(opts) {
|
|
|
593
769
|
// The subordinate statement pins this entity's jwks — adopt the
|
|
594
770
|
// attested keys for the next link down, and reflect them on the node.
|
|
595
771
|
if (node.subordinate.jwks && Array.isArray(node.subordinate.jwks.keys)) {
|
|
772
|
+
// Bind the entity's OWN self-configuration to the superior-attested
|
|
773
|
+
// keys. resolveLeaf reads the effective metadata from the entity's
|
|
774
|
+
// self-config (chain[i].claims.metadata), and Phase 1 verified that
|
|
775
|
+
// config only against its OWN self-published jwks — which proves the
|
|
776
|
+
// document isn't garbled, NOT that a federation-attested key signed
|
|
777
|
+
// it. An attacker who controls the entity's .well-known endpoint (but
|
|
778
|
+
// not its attested signing key) can serve a self-signed config that
|
|
779
|
+
// carries forged metadata + attacker jwks and sails through the Phase 1
|
|
780
|
+
// self-verify; without this check the pinned keys never gate the very
|
|
781
|
+
// document whose metadata is trusted. Re-verify the config against the
|
|
782
|
+
// pinned keys so a config not signed by an attested key fails the whole
|
|
783
|
+
// chain (OIDF 1.0 §9 — the leaf/intermediate Entity Configuration is
|
|
784
|
+
// verified with the jwks pinned by its superior's Subordinate
|
|
785
|
+
// Statement, never with the config's self-declared jwks).
|
|
786
|
+
verifyEntityStatement(node.jwt, node.subordinate.jwks);
|
|
596
787
|
node.claims.jwks = node.subordinate.jwks;
|
|
597
788
|
attestedJwks = node.subordinate.jwks;
|
|
598
789
|
} else {
|
|
@@ -54,6 +54,7 @@ var zlib = require("node:zlib");
|
|
|
54
54
|
var nodeCrypto = require("node:crypto");
|
|
55
55
|
var pqcSoftware = require("../pqc-software");
|
|
56
56
|
var bCrypto = require("../crypto");
|
|
57
|
+
var C = require("../constants");
|
|
57
58
|
var { generateToken, timingSafeEqual } = bCrypto;
|
|
58
59
|
var { AuthError } = require("../framework-error");
|
|
59
60
|
|
|
@@ -703,6 +704,24 @@ function create(opts) {
|
|
|
703
704
|
}
|
|
704
705
|
var recipHok = _attr(scdHok, "Recipient");
|
|
705
706
|
if (!recipHok || recipHok !== opts.assertionConsumerServiceUrl) continue; // §3.1→§4.1.4.2 — Recipient is mandatory; absent fails the endpoint binding
|
|
707
|
+
// §3.1→§4.1.4.2 — a solicited response's SubjectConfirmationData
|
|
708
|
+
// InResponseTo MUST equal the stored AuthnRequest ID. The Bearer path
|
|
709
|
+
// below enforces this when the operator supplies expectedInResponseTo;
|
|
710
|
+
// holder-of-key is a sibling reader of the SAME SubjectConfirmationData
|
|
711
|
+
// and applies the identical replay check. Omitting it let an operator
|
|
712
|
+
// that opted into InResponseTo binding silently lose it on every HoK
|
|
713
|
+
// confirmation (possession-proof is a separate control, not a licence
|
|
714
|
+
// to skip the solicited-response correlation the operator requested).
|
|
715
|
+
var irtHok = _attr(scdHok, "InResponseTo");
|
|
716
|
+
if (vopts.expectedInResponseTo) {
|
|
717
|
+
if (irtHok === null || irtHok === undefined ||
|
|
718
|
+
!timingSafeEqual(irtHok, vopts.expectedInResponseTo)) {
|
|
719
|
+
throw new AuthError("auth-saml/bad-in-response-to",
|
|
720
|
+
"SubjectConfirmation InResponseTo does not match expected " +
|
|
721
|
+
"AuthnRequest ID (replay defense)");
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
matchedInResponseTo = irtHok;
|
|
706
725
|
hokOk = true;
|
|
707
726
|
break;
|
|
708
727
|
}
|
|
@@ -835,7 +854,7 @@ function create(opts) {
|
|
|
835
854
|
sessionIndex: sessionIndex,
|
|
836
855
|
attributes: attributes,
|
|
837
856
|
audience: audience,
|
|
838
|
-
inResponseTo: bearerOk ? matchedInResponseTo : null,
|
|
857
|
+
inResponseTo: (bearerOk || hokOk) ? matchedInResponseTo : null,
|
|
839
858
|
issuer: issuer,
|
|
840
859
|
};
|
|
841
860
|
}
|
|
@@ -1681,16 +1700,16 @@ function _decryptEncryptedAssertion(encAssertion, spPrivateKeyPem) {
|
|
|
1681
1700
|
"OAEP unwrap failed: " + ((eR && eR.message) || String(eR)));
|
|
1682
1701
|
}
|
|
1683
1702
|
} else if (keyAlg === "urn:blamejs:experimental:xmlenc:ml-kem-1024") {
|
|
1684
|
-
// Framework PQC
|
|
1685
|
-
//
|
|
1686
|
-
// b.
|
|
1687
|
-
//
|
|
1688
|
-
// the
|
|
1703
|
+
// Framework PQC key transport — the EncryptedKey CipherValue carries
|
|
1704
|
+
// a b.crypto envelope (ML-KEM-1024 KEM-only suite) whose plaintext IS
|
|
1705
|
+
// the content-encryption key. b.crypto.decrypt parses the envelope
|
|
1706
|
+
// magic + suite header, decapsulates with the SP's ML-KEM-1024 private
|
|
1707
|
+
// key, and returns the CEK bytes. `raw: true` keeps the CEK as a
|
|
1708
|
+
// Buffer (it is binary key material, not utf8 text); the SP private
|
|
1709
|
+
// key travels as the PEM the envelope opener expects.
|
|
1689
1710
|
try {
|
|
1690
|
-
cek = bCrypto.
|
|
1691
|
-
|
|
1692
|
-
privateKey: nodeCrypto.createPrivateKey({ key: spPrivateKeyPem, format: "pem" }),
|
|
1693
|
-
});
|
|
1711
|
+
cek = bCrypto.decrypt(wrappedKey.toString("base64"),
|
|
1712
|
+
{ privateKey: spPrivateKeyPem }, { raw: true });
|
|
1694
1713
|
} catch (eM) {
|
|
1695
1714
|
throw new AuthError("auth-saml/encrypted-key-unwrap-failed",
|
|
1696
1715
|
"ML-KEM-1024 unwrap failed: " + ((eM && eM.message) || String(eM)));
|
|
@@ -1744,17 +1763,16 @@ function _decryptEncryptedAssertion(encAssertion, spPrivateKeyPem) {
|
|
|
1744
1763
|
throw new AuthError("auth-saml/encrypted-content-too-short",
|
|
1745
1764
|
"XChaCha20-Poly1305 CipherValue too short");
|
|
1746
1765
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1766
|
+
// XMLEnc content wire is nonce(24) || ciphertext || Poly1305-tag(16).
|
|
1767
|
+
// b.crypto.decryptPacked reads a 1-byte format tag followed by that
|
|
1768
|
+
// exact 24-byte-nonce + (ciphertext||tag) tail, so prepending the
|
|
1769
|
+
// XChaCha20-Poly1305 format byte routes the content through the
|
|
1770
|
+
// framework's own AEAD (which verifies the Poly1305 tag) instead of a
|
|
1771
|
+
// hand-rolled cipher call.
|
|
1772
|
+
var packedContent = Buffer.concat([
|
|
1773
|
+
Buffer.from([C.FORMAT.XCHACHA20_POLY1305]), contentBlob]);
|
|
1750
1774
|
try {
|
|
1751
|
-
clearBytes = bCrypto.
|
|
1752
|
-
alg: "xchacha20-poly1305",
|
|
1753
|
-
key: cek,
|
|
1754
|
-
nonce: xnonce,
|
|
1755
|
-
ct: xct,
|
|
1756
|
-
tag: xtag,
|
|
1757
|
-
});
|
|
1775
|
+
clearBytes = bCrypto.decryptPacked(packedContent, cek);
|
|
1758
1776
|
} catch (eX) {
|
|
1759
1777
|
throw new AuthError("auth-saml/encrypted-content-tag-mismatch",
|
|
1760
1778
|
"XChaCha20-Poly1305 tag mismatch: " + ((eX && eX.message) || String(eX)));
|