@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,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.4",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "Three fail-open holes closed: a raw cross-border write could evade the data-residency gate by wedging a comment or eliding whitespace, safe decompression returned undecompressed bytes for an unknown algorithm name, and the shared anti-replay helper admitted a replay when its store signalled a duplicate with a non-boolean value",
|
|
6
|
+
"summary": "A raw SQL write submitted through b.db.runSql / b.db.prepare().run() could slip past the cross-border data-residency gate: the gate's write-detection matched tokens on whitespace boundaries, but SQL lets tokens abut with no whitespace when a comment or a quoted identifier sits between them, so INSERT/**/INTO, an INSERT whose quoted table name abuts INTO, and UPDATE/**/table all executed while the gate never engaged -- landing or moving a row across a residency boundary under a regulated posture. b.safeDecompress resolved its algorithm allowlist with a truthiness lookup, so an algorithm name that collides with an inherited object member (constructor, toString) reached the dispatch and returned the input undecompressed instead of refusing the unknown algorithm -- a fail-open for any caller that maps a client Content-Encoding onto the algorithm. And b.nonceStore.enforceReplay -- the anti-replay helper JWT and DPoP verification use -- detected a replay only when its store returned a literal false, so a store signalling a duplicate with another falsy value (a Redis SETNX null, a SQL INSERT rowcount of 0) let the replayed token through.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "Data-residency gate catches a raw write that hides behind a comment or elided whitespace",
|
|
13
|
+
"body": "The cross-border data-residency gate that guards raw SQL writes (b.db.runSql, b.db.prepare().run()) detected the write and extracted its target table with regexes that assume tokens are separated by whitespace. SQL does not require whitespace between tokens when a comment or a quoted-identifier boundary separates them, so three forms that every engine executes as ordinary writes slipped the detection entirely and the gate never engaged: an INSERT whose double-quoted table name abuts INTO with no space, an INSERT with a block comment wedged between INSERT and INTO, and the same for UPDATE and its table. Under a regulated residency posture a row could therefore be inserted or moved across a residency boundary with no tag check (CWE-863; a GDPR Chapter V transfer-restriction bypass). The gate now normalizes a parse-only copy of the statement through the new b.safeSql.normalizeForScan before matching -- collapsing comments to a space and inserting a boundary where a quoted token abuts a word character -- so every write is detected and gated regardless of how its tokens are spaced. The executed SQL is unchanged."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "Safe decompression refuses an unknown algorithm instead of returning the input undecompressed",
|
|
17
|
+
"body": "b.safeDecompress resolved opts.algorithm against its allowlist of supported codecs (gzip, deflate, deflate-raw, brotli) with a truthiness lookup on a plain object. An algorithm name that names an inherited object member -- constructor, toString, valueOf -- read back a truthy inherited value, slipped the unsupported-algorithm refusal, and reached the dispatch, where invoking the inherited member returned the raw input buffer. The primitive therefore silently returned undecompressed bytes with no error, contrary to its contract that any algorithm outside the allowlist is refused -- a fail-open for a consumer that maps a client-supplied Content-Encoding token onto the algorithm, which also sidesteps the decompression-bomb size and ratio caps. The allowlist is now resolved with an own-property check, so any unsupported name -- however it collides with a built-in member -- is refused."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"title": "Shared anti-replay helper fails closed on a non-boolean store result",
|
|
21
|
+
"body": "b.nonceStore.enforceReplay is the anti-replay helper that b.auth.jwt and b.auth.dpop route their replay defense through; it calls the store's checkAndInsert and treated the result as a replay only when it was the literal false. The recommended stores signal a duplicate with a different falsy value -- a Redis SET ... NX returns null and a SQL INSERT ... ON CONFLICT returns a rowcount of 0 -- so a store using either would have its duplicate signal missed and the replayed nonce admitted (a replay-protection bypass for a JWT or DPoP proof). enforceReplay now admits a nonce only on a truthy first-seen confirmation and treats every other result as a replay, matching the fail-closed check the framework's inline anti-replay consumers already use."
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"heading": "Added",
|
|
27
|
+
"items": [
|
|
28
|
+
{
|
|
29
|
+
"title": "b.safeSql.normalizeForScan",
|
|
30
|
+
"body": "A parse-only SQL normalizer that produces a copy whose token boundaries are real whitespace, so a scanner built with whitespace-anchored patterns cannot be evaded by a comment or a quoted-identifier boundary that lets two tokens abut. It collapses line and block comments to a single space and inserts a separating space where a quoted string or identifier follows a word character, in the same quote- and comment-aware single pass as the existing b.safeSql placeholder scanners (a comment marker inside a string literal is preserved, never collapsed). The executed SQL is never derived from this copy -- it only feeds a scanner."
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.5",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "A tampered or over-filtered backup can no longer silently wipe the live data directory on restore, DNSSEC-strict resolution stays enforced when a stale answer is served, and a family of guards that matched a name against a lookup table now reject a prototype-member name instead of misclassifying it",
|
|
6
|
+
"summary": "Restoring a backup whose manifest lists zero files -- because a tampered unsigned bundle stripped every entry, or an opts.filter matched nothing -- extracted an empty staging directory and swapped it over the live data directory: a silent, full data-directory wipe reported to the operator as a successful restore. The manifest validator now refuses an empty file list, and the restore path refuses to swap a zero-file extract over a non-empty data directory. Separately, b.network.dns.resolver's validate: true DNSSEC gate was skipped on the serve-stale path, so an upstream outage could downgrade a DNSSEC-strict lookup (including DANE TLSA resolution) to unauthenticated stale data; the gate now holds on the stale path too. And a group of guards resolved a host, scheme, tag, method, or agent name against a plain-object lookup table with a truthiness read, so a name colliding with an inherited object member (constructor) was misclassified -- over-rejected as reserved/forbidden, or, for the mail-server method catalogue, passed the catalogue gate unregistered. All now match against the table's own keys.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "Restore refuses a zero-file backup instead of wiping the data directory",
|
|
13
|
+
"body": "b.backupManifest.validate accepted a manifest with an empty files array. The bundle writer never emits one, but the validator is the single guard the restore path parses an untrusted manifest through, so a tampered unsigned bundle that stripped every file entry (while keeping the still-valid wrapped vault key, which needs no passphrase knowledge) parsed cleanly, extracted an empty staging directory, and had the atomic swap move that empty directory over the live data directory -- a silent, destructive wipe of every file, reported to the operator as a successful restore with a file count of zero. The validator now refuses an empty file list (fixing every consumer -- parse, create, serialize -- at once), so a tampered manifest is rejected before extraction. As defense in depth, b.restore.run now also refuses to swap a zero-file extract over a non-empty data directory, which additionally catches an opts.filter that matched no manifest entry; the swap is refused with the data directory left intact rather than destroyed."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "DNSSEC-strict resolution stays enforced on the serve-stale path",
|
|
17
|
+
"body": "b.network.dns.resolver's validate: true option refuses a response that is not DNSSEC-authenticated (AD=0), but the RFC 8767 serve-stale short-circuit returned a cached stale answer before that gate ran. An attacker who can force an upstream outage (denying the DoH endpoint) could therefore downgrade a DNSSEC-strict lookup -- including b.network.dns.resolver.queryTlsa for DANE, queryDs, or a CNAME chase -- to unauthenticated stale data cached earlier at AD=0, with the caller seeing a success rather than the documented validate-failed refusal. The AD-bit gate now applies on the serve-stale path too (the DNSSEC verdict is per-response), so a stale answer that was not authenticated is refused rather than served to a validating caller."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"title": "Name-lookup guards reject a prototype-member name instead of misclassifying it",
|
|
21
|
+
"body": "A group of guards tested whether a caller- or peer-supplied name was in a fixed table -- a reserved-HELO-name set, a reserved-local-host set, a dangerous-URL-scheme denylist, a reserved agent-name set, a Tiny-PS forbidden-element set, an HTML void-element set, and the mail-server method catalogue -- with a plain-object truthiness read (TABLE[name]) that walks the prototype chain. A name that collides with an inherited object member -- constructor is the one that survives a lowercased key -- read the inherited value as truthy and was misclassified: over-rejected as reserved or forbidden (b.mail.helo, b.guardListUnsubscribe, b.guardAgentRegistry, b.mailBimi, b.htmlBalance), or, for the mail-server method catalogue, passed the catalogue gate as if it were a registered method (a fail-open at registration). Every site now matches against the table's own keys with an own-property check, so a prototype-member name is treated as any other unknown name; supported names are unaffected."
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.6",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "PDF disarm now refuses JavaScript, launch actions, and polyglots even when an operator opt says allow, a renewed cluster lease no longer stretches its own expiry into the future, and a credential-issuance proof is refused when its replay nonce is absent",
|
|
6
|
+
"summary": "b.guardPdf.sanitize is documented to strip a PDF down to inert content and to refuse -- under every profile -- the JavaScript, launch-action, and polyglot classes it cannot safely neutralize. But its forced-reject override pinned only the exfiltration and encryption policies, omitting the JavaScript, launch-action, and polyglot policies; those default to reject, so the gap was invisible until an operator passed an explicit permissive opt, which then let sanitize hand back a live PDF still carrying JavaScript or a launch action. b.clusterProviderDb.renewLease computed a lease's time-to-live as the span between its acquire time and its expiry, but on renewal advanced only the expiry and left the acquire time frozen, so each renewal re-derived an ever-larger TTL and pushed the expiry unboundedly into the future -- a dead leader's lease then never lapsed and no follower could take over. And b.auth.oid4vci's issuer skipped the credential-proof replay/holder-binding nonce check when the expected nonce was null, the miss sentinel that a Redis-, Map-, or SQL-backed nonce store commonly returns, so a forged proof could mint a credential bound to an attacker-chosen key.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "PDF disarm refuses active content even against a permissive operator opt",
|
|
13
|
+
"body": "b.guardPdf.sanitize is the disarm-by-refusal primitive: it guarantees it never returns a PDF that still carries JavaScript, a launch/open action, an embedded file, or encryption, and that the JavaScript, launch-action, and polyglot classes are refused under every profile. To hold that guarantee regardless of the operator's configuration, sanitize builds a forced override that pins the relevant policies to reject -- but the override pinned only the embedded-file, open-action, magic, and encryption policies and omitted the JavaScript, launch-action, and polyglot policies. Because those three already default to reject in every shipped profile, the omission was invisible in normal use; an operator who passed an explicit permissive opt (javascriptPolicy, launchActionPolicy, or polyglotPolicy set to allow or audit) turned that opt back on inside sanitize and received a live PDF still carrying JavaScript or a launch action -- exactly the remote-code-execution and polyglot classes the primitive promises to refuse. The forced override now pins all three, so sanitize refuses them unconditionally; the overridable validate and gate entry points, which document these policies as operator-tunable, are unchanged."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "Cluster lease renewal keeps a bounded expiry so a dead leader can be taken over",
|
|
17
|
+
"body": "b.clusterProviderDb models a leader lease as a sliding window whose span -- expiry minus acquire time -- equals the configured lease TTL. renewLease recovered the TTL from that span but then advanced only the expiry while leaving the acquire time frozen at the original acquisition, so the next renewal measured a span that had grown by one renewal interval and re-derived an ever-larger TTL, pushing the expiry unboundedly into the future. A leader that renewed even a few times and then died left a lease whose expiry was far beyond the configured TTL, so it never lapsed within the takeover window and no follower could steal it -- the cluster could stall with no active leader. renewLease now slides both ends of the window forward on every renewal (acquire time and expiry both move to now and now-plus-TTL), keeping the span at the configured TTL so a lapsed leader's lease expires on schedule and bounded takeover works."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"title": "Credential-issuance proof is refused when its replay nonce is absent",
|
|
21
|
+
"body": "b.auth.oid4vci's issuer verifies the wallet's key-binding proof against the c_nonce it minted with the access token -- the challenge that binds the proof to this issuance and prevents replay. The verifier treated three states of the expected nonce differently: a string was compared, an undefined value (the miss sentinel b.cache returns) was refused, and a null value was treated as no check required. But a nonce store fronting Redis, a Map, or a SQL row -- all accepted through the documented store option -- commonly signals a miss with null, which fell straight through the comparison and disabled the replay and holder-binding defense entirely: after the short-lived c_nonce expired (while the access token was still valid, in batch issuance), an attacker holding that token could submit a proof signed by an arbitrary key with any nonce and have a credential minted bound to that attacker-controlled key. The verifier now requires the expected nonce to be a non-empty string and fails closed on any other value, so an absent or expired nonce is refused regardless of the store's miss sentinel."
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.7",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "A histogram exemplar's label name can no longer forge a line into the metrics scrape, the CSP report endpoint bounds how many reports one request can carry, and a cron field of the form N/step now fires on the whole repeating series instead of once",
|
|
6
|
+
"summary": "A histogram exemplar's label VALUES were scrubbed before rendering but its label NAMES were written verbatim into the OpenMetrics exposition, and a Prometheus label name -- unlike a value -- cannot be quoted or escaped, so a name containing a newline forged an entire metric line into every /metrics scrape (the label-name sibling of the exemplar value injection already closed). The CSP report endpoint processed an unbounded number of reports per request: a single unauthenticated POST within the body-size cap could pack well over a thousand tiny reports, each driving a full audit-chain append and report hook, an amplification vector now bounded by a per-request report cap. And the shared cron parser mis-read a field of the form N/step -- e.g. 5/15 -- as the single value N instead of the standard N, N+step, ... through the field maximum, so a job scheduled that way fired once per period instead of on the intended repeating series; a recurring queue job also silently dropped its configured retry limit when it re-enqueued the next occurrence.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "Metrics exemplar label names cannot inject a line into the scrape",
|
|
13
|
+
"body": "b.metrics histogram exemplars carry their own label set, stored through the same redaction step the regular labels use -- but that step scrubbed only the label VALUES (for credential shapes) and passed every label NAME through verbatim to the shared exposition renderer. A regular label name is validated against the Prometheus name grammar at registration and refused if undeclared, but the exemplar path had no equivalent gate, and because a label name cannot be quoted or escaped in the OpenMetrics wire format, an exemplar label name containing a newline (or a quote or brace) forged a complete, attacker-shaped metric line into every /metrics scrape -- reachable wherever an operator routes request-derived data into an exemplar label name (CWE-93). The exemplar redaction step now drops any label name that is not a valid Prometheus label name (length-bounded so a hostile oversized name cannot itself become a denial of service), matching the gate regular labels already get; valid names such as trace_id are unaffected. This closes the label-name sibling of the exemplar value injection fixed earlier."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "CSP report endpoint bounds the number of reports per request",
|
|
17
|
+
"body": "b.middleware.cspReport accepts a batch of reports in one POST (the Reporting API delivers them batched). The body-size cap bounded the request bytes but not the number of reports inside it, so a single unauthenticated request could carry well over a thousand small report objects, and the handler drove a full audit-chain append (a hash, a seal, and a serialized database insert) plus an operator report hook for every one of them -- a per-request amplification denial-of-service against an endpoint that is public by design. The endpoint now caps the batch length at a configurable maxReports (default 100, generous for a real browser batch): an over-cap batch is refused with 413 and the documented too-many-reports rejection reason, processing none of its reports, so the amplification is bounded while a normal browser report is unaffected."
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"heading": "Fixed",
|
|
23
|
+
"items": [
|
|
24
|
+
{
|
|
25
|
+
"title": "A cron field of the form N/step fires on the full repeating series",
|
|
26
|
+
"body": "The shared cron parser read a field of the form N/step -- a bare number followed by a step, such as 5/15 in the minute field -- as the single value N, dropping the step entirely, instead of the standard Vixie-cron meaning N, N+step, ... up to the field maximum (5/15 in minutes is 5, 20, 35, 50, the same way */15 is 0, 15, 30, 45). A schedule written that way therefore fired once per period instead of on the intended repeating series -- and a job that runs less often than intended (a rotation, a cleanup, a scan) is a silent operational-safety gap. The parser now anchors the range at the field maximum whenever a step is present, so N/step expands to the full series; a bare number with no step is still the single value N. The cron-recurring queue backends (local and Redis) parse through this shared code and inherit the fix."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"title": "A recurring queue job keeps its configured retry limit across occurrences",
|
|
30
|
+
"body": "A cron-recurring queue job re-enqueues itself for its next firing time and carried its priority, classification, and trace id forward -- but silently dropped the operator's configured maxAttempts, so every occurrence after the first reverted to the enqueue default retry budget rather than the one the operator set. Both queue backends now carry maxAttempts forward (guarded to a positive finite value, falling back to the enqueue default only when it is unset), so a recurring job's retry limit is stable across every occurrence."
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.8",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "The AI-Act transparency HTML emitters now escape every interpolated value, closing a reflected-XSS through a banner's language attribute and a script-context breakout through the JSON-LD disclosure",
|
|
6
|
+
"summary": "b.compliance.aiAct.transparency.htmlBanner rendered its lang value -- a free-form string that is typically a request locale, Accept-Language, or query parameter when the banner is server-rendered -- into a double-quoted HTML attribute by raw concatenation, so a lang containing a double quote broke out of the attribute and injected active content (reflected XSS). Only the element text was escaped before; the attribute values were not. And b.compliance.aiAct.transparency.jsonLdDisclosure embedded the watermark manifest (operator-supplied strings such as the model id and deployer name) inside a <script type=\"application/ld+json\"> element with raw JSON.stringify, which does not escape </script>; the HTML parser ends a script element at the first </script> regardless of its type, so a manifest value carrying that sequence terminated the block early and injected markup. Both emitters now escape at the sink -- every attribute value through the HTML-entity escaper and the JSON-LD payload through the script-safe serializer -- so no interpolated value can break out of its context.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "AI-Act transparency banner escapes its attribute values",
|
|
13
|
+
"body": "b.compliance.aiAct.transparency.htmlBanner builds a status banner whose lang attribute carries a free-form language value -- in a server-rendered banner that value commonly comes from the request (a locale, an Accept-Language header, or a query parameter). The banner escaped its visible text but concatenated the lang, article, and kind values into their double-quoted HTML attributes raw, so a lang value containing a double quote closed the attribute early and let the remainder inject an element or event handler into the page (reflected cross-site scripting, CWE-79). Every attribute value is now passed through the HTML-entity escaper before interpolation, matching the escaping the banner text already had, so a hostile value is rendered as inert text inside the attribute rather than breaking out of it; the escape-at-the-sink handling also covers the article and kind values even though their range is currently constrained."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "AI-Act JSON-LD disclosure cannot break out of its script element",
|
|
17
|
+
"body": "b.compliance.aiAct.transparency.jsonLdDisclosure emits the watermark manifest as JSON-LD inside a <script type=\"application/ld+json\"> element, serializing operator-supplied manifest strings (the model id, deployer name, prompt hash, and similar). It used raw JSON.stringify, which does not escape the sequence </script>; because an HTML parser terminates a script element at the first </script> regardless of the element's type, a manifest value containing </script> (or an HTML comment opener) ended the disclosure block early and injected arbitrary markup that the browser then parsed and could execute. The disclosure now serializes the manifest with the framework's script-safe serializer, which escapes <, >, & and the U+2028/U+2029 separators to their \\uXXXX form so the parsed JSON is unchanged but no substring can break out of the script context."
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../scripts/release-notes-schema.json",
|
|
3
|
+
"version": "0.17.9",
|
|
4
|
+
"date": "2026-07-17",
|
|
5
|
+
"headline": "A prototype-member regime name no longer voids a breach-notification clock into reporting a missed deadline as met, a planted plaintext file can no longer stand in for the sealed keyed-hash MAC key, and content-safety sanitization recomputes the integrity descriptor over the bytes actually delivered",
|
|
6
|
+
"summary": "The incident-report deadline clock resolved its per-regime statutory table by a plain-object lookup with no own-property check, so a regime name equal to an inherited object member (valueOf, toString, constructor) resolved to a prototype function instead of the default deadlines -- every due-by became NaN, and a notification filed long past a statutory wall was recorded on-time, reporting a missed regulatory deadline as met. The retention posture-floor lookup had the same defect. The vault's keyed-hash MAC key reader trusted the vault's documented pass-through of a non-sealed value, so a plaintext file substituted on disk was accepted as the secret MAC key without the vault passphrase. And the static file server and the upload finalizer both replaced the served/stored payload when a content-safety gate sanitized it but kept advertising the ORIGINAL bytes' ETag/SRI (static) and sha3/size descriptor (upload), so a client validating the integrity of the delivered body -- or an operator storing the reported hash as the dedup/integrity key -- got a digest that did not match what was actually delivered.",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"heading": "Security",
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"title": "Breach-notification and retention lookups reject a prototype-member name",
|
|
13
|
+
"body": "b.incident.report's deadline clock resolves the statutory deadline set for an incident's regime (GDPR 72h, NIS2 24h, DORA 4h initial, HIPAA 60 days, ...) by indexing a per-regime table with the operator-supplied regime string. The lookup used a truthiness check with no own-property guard, so a regime equal to an inherited object member -- valueOf, toString, constructor, hasOwnProperty -- resolved to the prototype function instead of falling back to the default deadlines. Every computed due-by then became NaN, and because a late comparison against NaN is never true, a notification filed long past the real statutory wall was recorded on-time (not late) and the clock's late count stayed zero -- a genuinely missed regulatory deadline reported to a regulator as met. b.retention's compliance-posture floor lookup (hipaa, pci-dss, gdpr, soc2) had the identical defect, resolving a prototype-member posture to an inherited function as the retention floor. Both now resolve the name through an own-property check, so a prototype-member name falls back to the default deadlines (incident-report) or is rejected as an unknown posture (retention); real regimes and postures are unaffected."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"title": "Vault refuses a non-sealed file as the keyed-hash MAC key",
|
|
17
|
+
"body": "b.vault derives a keyed-hash MAC key (used by field-level encryption's keyed derived-hash mode to keep an attacker with disk access from correlating low-entropy plaintexts) and seals it at rest. The reader loaded the sealed file and called the vault's unseal, which by its documented idempotent-read contract returns any value lacking the vault seal prefix verbatim -- so a plaintext 32-byte value planted on disk passed straight through and was accepted as the MAC key. In wrapped-vault mode this let an attacker with disk-write access but no vault passphrase (and therefore unable to forge a genuine seal) inject a known MAC key, downgrading the keyed derived-hash to an attacker-known key. The reader now requires the on-disk value to actually be sealed (carry the vault prefix) before unsealing, refusing a substituted plaintext or otherwise-unsealed file -- the same load-bearing prefix check the database key loader and the key-rotation pipeline already apply to their sealed key material."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"title": "Content-safety sanitization recomputes the served body's integrity descriptor",
|
|
21
|
+
"body": "When a content-safety gate returns a sanitize action it replaces the payload with the cleaned bytes. b.staticServe still emitted the strong ETag and subresource-integrity (SRI) header derived from the original file on disk, and b.fileUpload's finalizer still handed onFinalize (and recorded in the audit) the sha3 and size of the original assembled bytes -- so the integrity descriptor advertised for the delivered/stored bytes did not match them. A browser performing SRI verification of the sanitized static response would fail the check, a strong-validator or If-None-Match cache would be keyed to a representation the client never receives, and an operator storing the upload's reported sha3 as the integrity or dedup key of the stored (sanitized) file would record a hash that never matches it. Both now recompute the ETag/SRI (static) and the sha3/size descriptor (upload) over the bytes actually delivered whenever a gate sanitized the payload; an unsanitized response keeps the on-disk/reassembly digest, which already describes the delivered bytes."
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -74,6 +74,10 @@ var findings = engine.validate({
|
|
|
74
74
|
curationPages: curationPages,
|
|
75
75
|
parser: parser,
|
|
76
76
|
// optsResolver intentionally omitted — see comment block above.
|
|
77
|
+
// testDirs feeds the primitive-without-test check: every @primitive
|
|
78
|
+
// must be referenced from the test corpus (full dotted form, or
|
|
79
|
+
// namespace / owning-module reference plus a method invocation).
|
|
80
|
+
testDirs: [path.join(ROOT, "test")],
|
|
77
81
|
});
|
|
78
82
|
|
|
79
83
|
process.exit(_report(findings));
|
|
@@ -6,10 +6,17 @@
|
|
|
6
6
|
# ./scripts/vendor-update.sh --check # show outdated vendored packages
|
|
7
7
|
# ./scripts/vendor-update.sh --diff <package> # show vendored vs latest + changelog url
|
|
8
8
|
# ./scripts/vendor-update.sh --diff-all # diff every outdated package
|
|
9
|
+
# ./scripts/vendor-update.sh --refresh-data [entry] # refresh + re-sign vendored data files
|
|
10
|
+
# # (publicsuffix-list, SecLists-common-
|
|
11
|
+
# # passwords-top-10000, bimi-trust-anchors;
|
|
12
|
+
# # default: all)
|
|
9
13
|
#
|
|
10
14
|
# What it does:
|
|
11
15
|
# 1. installs the package(s) temporarily via npm
|
|
12
|
-
# 2. bundles with esbuild (CJS, server-side
|
|
16
|
+
# 2. bundles with esbuild (CJS, server-side, unminified — vendored
|
|
17
|
+
# bundles ship as reviewable source so operators can diff them
|
|
18
|
+
# against upstream; esbuild still tree-shakes and keeps upstream
|
|
19
|
+
# license comments)
|
|
13
20
|
# 3. copies native prebuilds where applicable (argon2)
|
|
14
21
|
# 4. updates lib/vendor/MANIFEST.json (version + bundledAt)
|
|
15
22
|
# 5. removes the temporarily-installed npm package
|
|
@@ -113,6 +120,250 @@ if [ "${1:-}" = "--diff-all" ]; then
|
|
|
113
120
|
exit 0
|
|
114
121
|
fi
|
|
115
122
|
|
|
123
|
+
# ---- refresh-data mode ----
|
|
124
|
+
#
|
|
125
|
+
# Vendored DATA files (not code bundles): fetch the upstream where one
|
|
126
|
+
# exists, re-append the in-payload integrity canary, and regenerate +
|
|
127
|
+
# re-sign the .data.js carrier via scripts/vendor-data-gen.js whenever
|
|
128
|
+
# the raw file changed. bimi-trust-anchors is operator-managed (no
|
|
129
|
+
# upstream to fetch) — it is re-signed only when the local .pem was
|
|
130
|
+
# edited per its file-header procedure. Runs of the CI vendor-currency
|
|
131
|
+
# gate that report the publicsuffix-list entry as stale are resolved by
|
|
132
|
+
# this mode. Requires the operator-local SLH-DSA signing key
|
|
133
|
+
# (.keys/vendor-data-private.pem; see scripts/vendor-data-keygen.js).
|
|
134
|
+
|
|
135
|
+
DATA_SIGNING_KEY=".keys/vendor-data-private.pem"
|
|
136
|
+
REFRESH_DATA_ANY_REGEN=false
|
|
137
|
+
|
|
138
|
+
fetch_upstream_raw() {
|
|
139
|
+
# $1 url, $2 dest tmp path, $3.. fixed strings that must all appear
|
|
140
|
+
# in the body (sanity gate — a truncated or error body must never
|
|
141
|
+
# reach the signer).
|
|
142
|
+
#
|
|
143
|
+
# NOTE for this function and everything refresh_data_entry calls:
|
|
144
|
+
# the entry functions run as `refresh_data_entry ... || exit 1`, and
|
|
145
|
+
# bash suspends errexit inside a function invoked under || — every
|
|
146
|
+
# state-changing command here must carry its own explicit failure
|
|
147
|
+
# handling; none may rely on `set -e`.
|
|
148
|
+
local url="$1" tmp="$2"
|
|
149
|
+
shift 2
|
|
150
|
+
if ! curl -fsSL --connect-timeout 30 --max-time 300 "$url" -o "$tmp"; then
|
|
151
|
+
echo "ERROR: fetch failed: $url"
|
|
152
|
+
rm -f "$tmp"
|
|
153
|
+
return 1
|
|
154
|
+
fi
|
|
155
|
+
if [ ! -s "$tmp" ]; then
|
|
156
|
+
echo "ERROR: fetched $url is empty — refusing to sign it"
|
|
157
|
+
rm -f "$tmp"
|
|
158
|
+
return 1
|
|
159
|
+
fi
|
|
160
|
+
local needle
|
|
161
|
+
for needle in "$@"; do
|
|
162
|
+
if ! grep -qF -- "$needle" "$tmp"; then
|
|
163
|
+
echo "ERROR: fetched $url failed the sanity check (missing '$needle') — refusing to sign it"
|
|
164
|
+
rm -f "$tmp"
|
|
165
|
+
return 1
|
|
166
|
+
fi
|
|
167
|
+
done
|
|
168
|
+
return 0
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
regen_data_module_if_changed() {
|
|
172
|
+
# $1 manifest key, $2 raw file, $3 .data.js carrier, $4 generator
|
|
173
|
+
# --name, $5 --source-url, $6 --license, $7 --canary ("" = none),
|
|
174
|
+
# $8 NOTICE component match string ("" = no dated NOTICE stamp)
|
|
175
|
+
#
|
|
176
|
+
# Regenerates when the raw payload no longer matches the carrier's
|
|
177
|
+
# recorded SHA-256 OR when the carrier itself fails four-layer
|
|
178
|
+
# verification (a payload-identical carrier with a corrupted
|
|
179
|
+
# signature block, a stripped header, or a signature from a rotated
|
|
180
|
+
# key must be re-signable through this documented path, not by
|
|
181
|
+
# reverse-engineering a manual generator invocation).
|
|
182
|
+
local key="$1" raw="$2" datajs="$3" name="$4" srcurl="$5" license="$6" canary="$7" noticekey="$8"
|
|
183
|
+
local rawsha datasha carrier_ok
|
|
184
|
+
rawsha=$(node -e "var c=require('node:crypto'),f=require('node:fs');console.log(c.createHash('sha256').update(f.readFileSync(process.argv[1])).digest('hex'))" "$raw" 2>/dev/null) || rawsha=""
|
|
185
|
+
if [ -z "$rawsha" ]; then
|
|
186
|
+
echo "ERROR: cannot hash $raw — file missing or unreadable"
|
|
187
|
+
return 1
|
|
188
|
+
fi
|
|
189
|
+
# Empty datasha (carrier missing, or its provenance header stripped)
|
|
190
|
+
# is a regeneration trigger, never a match.
|
|
191
|
+
datasha=$(node -e "var f=require('node:fs');var m=f.readFileSync(process.argv[1],'utf8').match(/^\/\/ SHA-256:\s+([0-9a-f]{64})/m);console.log(m?m[1]:'')" "$datajs" 2>/dev/null) || datasha=""
|
|
192
|
+
carrier_ok=$(BLAMEJS_VENDOR_DATA_DEFER_BOOT_VERIFY=1 \
|
|
193
|
+
BLAMEJS_VENDOR_DATA_DEFER_BOOT_VERIFY_REASON="vendor-update:per-entry-refresh-probe" \
|
|
194
|
+
node -e "try { require('./lib/vendor-data.js').get(process.argv[1]); console.log('ok'); } catch (e) { console.log('bad'); }" "$name" 2>/dev/null) || carrier_ok="bad"
|
|
195
|
+
if [ -n "$datasha" ] && [ "$rawsha" = "$datasha" ] && [ "$carrier_ok" = "ok" ]; then
|
|
196
|
+
echo " $name: carrier verified and matches the raw file — nothing to re-sign"
|
|
197
|
+
return 0
|
|
198
|
+
fi
|
|
199
|
+
if [ -n "$datasha" ] && [ "$rawsha" = "$datasha" ]; then
|
|
200
|
+
echo " $name: carrier fails verification — regenerating + re-signing"
|
|
201
|
+
else
|
|
202
|
+
echo " $name: raw file changed — regenerating + re-signing the carrier"
|
|
203
|
+
fi
|
|
204
|
+
local gen_args=(--src "$raw" --dst "$datajs" --name "$name" --source-url "$srcurl" --license "$license" --signing-key "$DATA_SIGNING_KEY")
|
|
205
|
+
if [ -n "$canary" ]; then gen_args+=(--canary "$canary"); fi
|
|
206
|
+
node scripts/vendor-data-gen.js "${gen_args[@]}" || return 1
|
|
207
|
+
node -e "
|
|
208
|
+
var fs = require('fs');
|
|
209
|
+
var m = JSON.parse(fs.readFileSync('$MANIFEST', 'utf8'));
|
|
210
|
+
var key = process.argv[1];
|
|
211
|
+
if (m.packages[key]) {
|
|
212
|
+
m.packages[key].bundledAt = process.argv[2] + 'T00:00:00Z';
|
|
213
|
+
fs.writeFileSync('$MANIFEST', JSON.stringify(m, null, 2) + '\n');
|
|
214
|
+
console.log(' MANIFEST.json: ' + key + ' bundledAt -> ' + process.argv[2]);
|
|
215
|
+
}
|
|
216
|
+
" "$key" "$DATE" || { echo "ERROR: MANIFEST.json bundledAt update failed for $key"; return 1; }
|
|
217
|
+
if [ -n "$noticekey" ]; then
|
|
218
|
+
node -e "
|
|
219
|
+
var fs = require('fs');
|
|
220
|
+
var sep = Array(81).join('-');
|
|
221
|
+
var noticeKey = process.argv[1];
|
|
222
|
+
var date = process.argv[2];
|
|
223
|
+
var blocks = fs.readFileSync('NOTICE', 'utf8').split(sep);
|
|
224
|
+
var touched = false;
|
|
225
|
+
for (var i = 0; i < blocks.length; i++) {
|
|
226
|
+
if (blocks[i].indexOf('Component:') === -1 || blocks[i].indexOf(noticeKey) === -1) continue;
|
|
227
|
+
var next = blocks[i].replace(/\(bundled \d{4}-\d{2}-\d{2}\)/, '(bundled ' + date + ')');
|
|
228
|
+
if (next !== blocks[i]) { blocks[i] = next; touched = true; }
|
|
229
|
+
}
|
|
230
|
+
if (touched) {
|
|
231
|
+
fs.writeFileSync('NOTICE', blocks.join(sep));
|
|
232
|
+
console.log(' NOTICE: ' + noticeKey + ' bundled date -> ' + date);
|
|
233
|
+
}
|
|
234
|
+
" "$noticekey" "$DATE" || { echo "ERROR: NOTICE date update failed for $noticekey"; return 1; }
|
|
235
|
+
fi
|
|
236
|
+
REFRESH_DATA_ANY_REGEN=true
|
|
237
|
+
return 0
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
refresh_data_entry() {
|
|
241
|
+
local key="$1" tmp
|
|
242
|
+
case "$key" in
|
|
243
|
+
publicsuffix-list)
|
|
244
|
+
tmp="lib/vendor/public-suffix-list.dat.refresh-tmp"
|
|
245
|
+
fetch_upstream_raw "https://publicsuffix.org/list/public_suffix_list.dat" "$tmp" \
|
|
246
|
+
"===END PRIVATE DOMAINS===" "// VERSION:" "// COMMIT:" || return 1
|
|
247
|
+
{ printf '\n// ===BEGIN blamejs canary===\n'
|
|
248
|
+
printf '// Honeytoken — vendor-data integrity defense (lib/vendor-data.js).\n'
|
|
249
|
+
printf '_blamejs_canary_v0_9_8_.local\n'
|
|
250
|
+
printf '// ===END blamejs canary===\n'; } >> "$tmp"
|
|
251
|
+
# Directional freshness guard: the list is CDN-served and an edge
|
|
252
|
+
# can return an OLDER cached copy than the snapshot already
|
|
253
|
+
# vendored (publication reaches edges at different times). The
|
|
254
|
+
# VERSION header is a sortable UTC timestamp — never replace the
|
|
255
|
+
# local file with a fetch whose VERSION is older than the local
|
|
256
|
+
# one; a genuinely newer local copy is what the CI currency gate
|
|
257
|
+
# already treats as current.
|
|
258
|
+
local fetchv localv
|
|
259
|
+
fetchv=$(grep -m1 '^// VERSION:' "$tmp" | awk '{print $3}') || fetchv=""
|
|
260
|
+
localv=$(grep -m1 '^// VERSION:' "lib/vendor/public-suffix-list.dat" 2>/dev/null | awk '{print $3}') || localv=""
|
|
261
|
+
if [ -n "$fetchv" ] && [ -n "$localv" ] && [[ "$fetchv" < "$localv" ]]; then
|
|
262
|
+
echo " public-suffix-list: fetched copy ($fetchv) is older than the vendored one ($localv) — lagging CDN edge; keeping the local file"
|
|
263
|
+
rm -f "$tmp"
|
|
264
|
+
elif cmp -s "$tmp" "lib/vendor/public-suffix-list.dat"; then
|
|
265
|
+
echo " public-suffix-list: upstream unchanged"
|
|
266
|
+
rm -f "$tmp"
|
|
267
|
+
else
|
|
268
|
+
mv "$tmp" "lib/vendor/public-suffix-list.dat" || { echo "ERROR: could not replace lib/vendor/public-suffix-list.dat"; return 1; }
|
|
269
|
+
echo " public-suffix-list: raw file refreshed from upstream"
|
|
270
|
+
fi
|
|
271
|
+
regen_data_module_if_changed "publicsuffix-list" \
|
|
272
|
+
"lib/vendor/public-suffix-list.dat" \
|
|
273
|
+
"lib/vendor/public-suffix-list.data.js" \
|
|
274
|
+
"public-suffix-list" \
|
|
275
|
+
"https://publicsuffix.org/list/public_suffix_list.dat" \
|
|
276
|
+
"MPL-2.0 (Mozilla Public Suffix List)" \
|
|
277
|
+
"_blamejs_canary_v0_9_8_.local" \
|
|
278
|
+
"publicsuffix-list"
|
|
279
|
+
;;
|
|
280
|
+
SecLists-common-passwords-top-10000)
|
|
281
|
+
tmp="lib/vendor/common-passwords-top-10000.txt.refresh-tmp"
|
|
282
|
+
fetch_upstream_raw "https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10k-most-common.txt" "$tmp" \
|
|
283
|
+
"password" || return 1
|
|
284
|
+
if [ "$(grep -c . "$tmp")" -lt 9000 ]; then
|
|
285
|
+
echo "ERROR: fetched password list has fewer than 9000 lines — refusing to sign it"
|
|
286
|
+
rm -f "$tmp"
|
|
287
|
+
return 1
|
|
288
|
+
fi
|
|
289
|
+
printf '\n_blamejs_canary_password_2026_05_13_blamejs_internal_\n' >> "$tmp"
|
|
290
|
+
if cmp -s "$tmp" "lib/vendor/common-passwords-top-10000.txt"; then
|
|
291
|
+
echo " common-passwords-top-10000: upstream unchanged"
|
|
292
|
+
rm -f "$tmp"
|
|
293
|
+
else
|
|
294
|
+
mv "$tmp" "lib/vendor/common-passwords-top-10000.txt" || { echo "ERROR: could not replace lib/vendor/common-passwords-top-10000.txt"; return 1; }
|
|
295
|
+
echo " common-passwords-top-10000: raw file refreshed from upstream"
|
|
296
|
+
fi
|
|
297
|
+
regen_data_module_if_changed "SecLists-common-passwords-top-10000" \
|
|
298
|
+
"lib/vendor/common-passwords-top-10000.txt" \
|
|
299
|
+
"lib/vendor/common-passwords-top-10000.data.js" \
|
|
300
|
+
"common-passwords-top-10000" \
|
|
301
|
+
"https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt" \
|
|
302
|
+
"CC-BY-3.0 (SecLists / Daniel Miessler)" \
|
|
303
|
+
"_blamejs_canary_password_2026_05_13_blamejs_internal_" \
|
|
304
|
+
"SecLists"
|
|
305
|
+
;;
|
|
306
|
+
bimi-trust-anchors)
|
|
307
|
+
# Operator-managed — never fetched. Re-signs only when the local
|
|
308
|
+
# .pem was edited per the refresh procedure in its file header.
|
|
309
|
+
regen_data_module_if_changed "bimi-trust-anchors" \
|
|
310
|
+
"lib/vendor/bimi-trust-anchors.pem" \
|
|
311
|
+
"lib/vendor/bimi-trust-anchors.data.js" \
|
|
312
|
+
"bimi-trust-anchors" \
|
|
313
|
+
"https://bimigroup.org/resources/vmc-trust-anchors.pem" \
|
|
314
|
+
"Public domain (BIMI Group VMC trust anchors)" \
|
|
315
|
+
"" \
|
|
316
|
+
""
|
|
317
|
+
;;
|
|
318
|
+
*)
|
|
319
|
+
echo "ERROR: unknown data entry: $key"
|
|
320
|
+
echo " valid: publicsuffix-list, SecLists-common-passwords-top-10000, bimi-trust-anchors"
|
|
321
|
+
return 1
|
|
322
|
+
;;
|
|
323
|
+
esac
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if [ "${1:-}" = "--refresh-data" ]; then
|
|
327
|
+
if [ ! -f "$DATA_SIGNING_KEY" ]; then
|
|
328
|
+
echo "ERROR: $DATA_SIGNING_KEY not found — the vendored-data SLH-DSA signing"
|
|
329
|
+
echo " key is operator-local. Generate a keypair with"
|
|
330
|
+
echo " scripts/vendor-data-keygen.js (shipping a new PUBLIC key is a"
|
|
331
|
+
echo " lib/vendor-data.js change and a breaking data-integrity event)."
|
|
332
|
+
exit 1
|
|
333
|
+
fi
|
|
334
|
+
# A Ctrl-C'd or failed fetch must not leave a partial download inside
|
|
335
|
+
# the shipped lib/vendor/ tree (the printed next step is `git add
|
|
336
|
+
# lib/vendor/`). Belt: this trap. Braces: *.refresh-tmp is gitignored.
|
|
337
|
+
trap 'rm -f lib/vendor/*.refresh-tmp' EXIT
|
|
338
|
+
echo "=== Refreshing vendored data files ==="
|
|
339
|
+
if [ -n "${2:-}" ]; then
|
|
340
|
+
refresh_data_entry "$2" || exit 1
|
|
341
|
+
else
|
|
342
|
+
refresh_data_entry "publicsuffix-list" || exit 1
|
|
343
|
+
refresh_data_entry "SecLists-common-passwords-top-10000" || exit 1
|
|
344
|
+
refresh_data_entry "bimi-trust-anchors" || exit 1
|
|
345
|
+
fi
|
|
346
|
+
if [ "$REFRESH_DATA_ANY_REGEN" = true ]; then
|
|
347
|
+
echo ""
|
|
348
|
+
echo "=== Refreshing MANIFEST.json sha256 hashes ==="
|
|
349
|
+
node scripts/refresh-vendor-manifest.js || { echo "Manifest hash refresh failed."; exit 1; }
|
|
350
|
+
fi
|
|
351
|
+
echo ""
|
|
352
|
+
echo "=== Verifying vendored data (dual-hash + SLH-DSA + canary) ==="
|
|
353
|
+
node -e "require('./lib/vendor-data.js').verifyAll(); console.log(' vendor-data verifyAll: OK');" || exit 1
|
|
354
|
+
if [ "$REFRESH_DATA_ANY_REGEN" = true ]; then
|
|
355
|
+
echo ""
|
|
356
|
+
echo "Next steps:"
|
|
357
|
+
echo " 1. node scripts/check-vendor-currency.js"
|
|
358
|
+
echo " 2. node test/smoke.js"
|
|
359
|
+
echo " 3. git add lib/vendor/ lib/vendor/MANIFEST.json NOTICE && git commit"
|
|
360
|
+
else
|
|
361
|
+
echo ""
|
|
362
|
+
echo "Nothing changed — every vendored data file already matches upstream."
|
|
363
|
+
fi
|
|
364
|
+
exit 0
|
|
365
|
+
fi
|
|
366
|
+
|
|
116
367
|
# ---- update mode ----
|
|
117
368
|
PKG="${1:?Usage: vendor-update.sh <package> [version]}"
|
|
118
369
|
VER="${2:-latest}"
|
|
@@ -128,8 +379,9 @@ fi
|
|
|
128
379
|
case "$PKG" in
|
|
129
380
|
"@noble/ciphers")
|
|
130
381
|
echo 'export { xchacha20poly1305 } from "@noble/ciphers/chacha.js";' > _entry.mjs
|
|
131
|
-
npx esbuild _entry.mjs --bundle --format=cjs --
|
|
382
|
+
npx esbuild _entry.mjs --bundle --format=cjs --platform=node --outfile=lib/vendor/noble-ciphers.cjs
|
|
132
383
|
rm _entry.mjs
|
|
384
|
+
BUNDLER_DESC="esbuild --format=cjs --platform=node"
|
|
133
385
|
sed -i "1s|^|// XChaCha20-Poly1305 — vendored from @noble/ciphers v${INSTALLED_VER} by Paul Miller\n// License: MIT — https://github.com/paulmillr/noble-ciphers\n// Bundled with esbuild. Exports: xchacha20poly1305\n|" lib/vendor/noble-ciphers.cjs
|
|
134
386
|
;;
|
|
135
387
|
|
|
@@ -138,8 +390,9 @@ case "$PKG" in
|
|
|
138
390
|
export { ristretto255_oprf } from "@noble/curves/ed25519.js";
|
|
139
391
|
export { p256_oprf, p384_oprf, p521_oprf } from "@noble/curves/nist.js";
|
|
140
392
|
ENTRY
|
|
141
|
-
npx esbuild _entry.mjs --bundle --format=cjs --
|
|
393
|
+
npx esbuild _entry.mjs --bundle --format=cjs --platform=node --outfile=lib/vendor/noble-curves.cjs
|
|
142
394
|
rm _entry.mjs
|
|
395
|
+
BUNDLER_DESC="esbuild --format=cjs --platform=node"
|
|
143
396
|
sed -i "1s|^|// @noble/curves v${INSTALLED_VER} — vendored from Paul Miller\n// License: MIT — https://github.com/paulmillr/noble-curves\n// Bundled with esbuild. Exports the RFC 9497 OPRF suites:\n// ristretto255_oprf (ristretto255-SHA512), p256_oprf (P-256-SHA256),\n// p384_oprf (P-384-SHA384), p521_oprf (P-521-SHA512) — each with\n// oprf / voprf / poprf modes. Backs b.crypto.oprf.\n|" lib/vendor/noble-curves.cjs
|
|
144
397
|
;;
|
|
145
398
|
|
|
@@ -149,15 +402,22 @@ export { ml_kem512, ml_kem768, ml_kem1024 } from "@noble/post-quantum/ml-kem.js"
|
|
|
149
402
|
export { ml_dsa44, ml_dsa65, ml_dsa87 } from "@noble/post-quantum/ml-dsa.js";
|
|
150
403
|
export { slh_dsa_sha2_128f, slh_dsa_sha2_192f, slh_dsa_sha2_256f, slh_dsa_shake_128f, slh_dsa_shake_192f, slh_dsa_shake_256f } from "@noble/post-quantum/slh-dsa.js";
|
|
151
404
|
ENTRY
|
|
152
|
-
npx esbuild _entry.mjs --bundle --format=cjs --
|
|
405
|
+
npx esbuild _entry.mjs --bundle --format=cjs --platform=node --outfile=lib/vendor/noble-post-quantum.cjs
|
|
153
406
|
rm _entry.mjs
|
|
407
|
+
BUNDLER_DESC="esbuild --format=cjs --platform=node"
|
|
154
408
|
sed -i "1s|^|// @noble/post-quantum v${INSTALLED_VER} — vendored from Paul Miller\n// License: MIT — https://github.com/paulmillr/noble-post-quantum\n// Bundled with esbuild. Exports: ml_kem512 / ml_kem768 / ml_kem1024 (FIPS 203 KEM),\n// ml_dsa44 / ml_dsa65 / ml_dsa87 (FIPS 204 lattice signatures),\n// slh_dsa_sha2_*f / slh_dsa_shake_*f (FIPS 205 hash signatures).\n|" lib/vendor/noble-post-quantum.cjs
|
|
155
409
|
;;
|
|
156
410
|
|
|
157
411
|
"@simplewebauthn/server")
|
|
412
|
+
# reflect-metadata (pulled in via @peculiar/x509) resolves to its upstream
|
|
413
|
+
# ./lite entry: identical metadata API and cross-copy registry, but built
|
|
414
|
+
# for runtimes with native globalThis / Map / Set / WeakMap — it has none
|
|
415
|
+
# of the legacy global-object probes (Function("return this") / indirect
|
|
416
|
+
# eval) that can never execute on the Node versions the framework supports.
|
|
158
417
|
echo "module.exports = require(\"@simplewebauthn/server\");" > _entry.cjs
|
|
159
|
-
npx esbuild _entry.cjs --bundle --format=cjs --platform=node --
|
|
418
|
+
npx esbuild _entry.cjs --bundle --format=cjs --platform=node --alias:reflect-metadata=reflect-metadata/lite --external:crypto --external:node:crypto --outfile=lib/vendor/simplewebauthn-server.cjs
|
|
160
419
|
rm _entry.cjs
|
|
420
|
+
BUNDLER_DESC="esbuild --format=cjs --platform=node --alias:reflect-metadata=reflect-metadata/lite --external:crypto --external:node:crypto"
|
|
161
421
|
sed -i "1s|^|// @simplewebauthn/server v${INSTALLED_VER} — vendored. License: MIT\n// https://github.com/MasterKale/SimpleWebAuthn\n|" lib/vendor/simplewebauthn-server.cjs
|
|
162
422
|
;;
|
|
163
423
|
|
|
@@ -174,11 +434,25 @@ ENTRY
|
|
|
174
434
|
# ASN.1 schema package, packed into one CJS file. lib/mtls-ca.js loads the
|
|
175
435
|
# bundle via the default engine in lib/mtls-engine-default.js for CA gen,
|
|
176
436
|
# client-cert signing, and PKCS#12 packaging — no openssl CLI at runtime.
|
|
437
|
+
#
|
|
438
|
+
# Version argument: "latest" (default) bundles the newest @peculiar/x509 +
|
|
439
|
+
# pkijs; the MANIFEST version form "<x509ver>+pkijs-<pkijsver>" (e.g.
|
|
440
|
+
# "2.0.0+pkijs-3.4.0") rebundles those exact component versions.
|
|
441
|
+
X509_REQ="latest"
|
|
442
|
+
PKIJS_REQ="latest"
|
|
443
|
+
if [ "$VER" != "latest" ]; then
|
|
444
|
+
X509_REQ="${VER%%+pkijs-*}"
|
|
445
|
+
PKIJS_REQ="${VER##*+pkijs-}"
|
|
446
|
+
if [ -z "$X509_REQ" ] || [ -z "$PKIJS_REQ" ] || [ "$X509_REQ" = "$VER" ]; then
|
|
447
|
+
echo "ERROR: peculiar-pki version must be 'latest' or '<x509ver>+pkijs-<pkijsver>' (e.g. 2.0.0+pkijs-3.4.0)"
|
|
448
|
+
exit 1
|
|
449
|
+
fi
|
|
450
|
+
fi
|
|
177
451
|
npm install --no-save --ignore-scripts \
|
|
178
452
|
reflect-metadata \
|
|
179
453
|
pvutils pvtsutils asn1js \
|
|
180
454
|
"@peculiar/asn1-schema" "@peculiar/asn1-x509" "@peculiar/asn1-ecc" "@peculiar/asn1-rsa" \
|
|
181
|
-
"@peculiar/x509" pkijs 2>/dev/null
|
|
455
|
+
"@peculiar/x509@${X509_REQ}" "pkijs@${PKIJS_REQ}" 2>/dev/null
|
|
182
456
|
X509_VER=$(node -e "console.log(require('./node_modules/@peculiar/x509/package.json').version)")
|
|
183
457
|
PKIJS_VER=$(node -e "console.log(require('./node_modules/pkijs/package.json').version)")
|
|
184
458
|
echo "Installed: @peculiar/x509@$X509_VER, pkijs@$PKIJS_VER"
|
|
@@ -197,10 +471,17 @@ export const pkijs = pkijsLib;
|
|
|
197
471
|
export const x509 = x509Lib;
|
|
198
472
|
export const crypto = webcrypto;
|
|
199
473
|
ENTRY
|
|
200
|
-
|
|
474
|
+
# reflect-metadata resolves to its upstream ./lite entry: identical
|
|
475
|
+
# metadata API and cross-copy registry, but built for runtimes with native
|
|
476
|
+
# globalThis / Map / Set / WeakMap — it has none of the legacy
|
|
477
|
+
# global-object probes (Function("return this") / indirect eval) that can
|
|
478
|
+
# never execute on the Node versions the framework supports.
|
|
479
|
+
npx esbuild _pki-entry.mjs --bundle --format=cjs --platform=node \
|
|
480
|
+
--alias:reflect-metadata=reflect-metadata/lite \
|
|
201
481
|
--external:node:crypto --external:crypto \
|
|
202
482
|
--outfile=lib/vendor/pki.cjs
|
|
203
483
|
rm _pki-entry.mjs
|
|
484
|
+
BUNDLER_DESC="esbuild --format=cjs --platform=node --alias:reflect-metadata=reflect-metadata/lite --external:node:crypto --external:crypto"
|
|
204
485
|
sed -i "1s|^|// Peculiar PKI — vendored @peculiar/x509 v${X509_VER} + pkijs v${PKIJS_VER}\n// License: MIT. Bundled with esbuild.\n// Exports: { pkijs, x509, crypto (node:webcrypto bound) }\n// Includes: reflect-metadata, pvutils, pvtsutils, asn1js, @peculiar/asn1-*\n// Used by lib/mtls-engine-default.js for pure-JS CA + PKCS#12 operations.\n|" lib/vendor/pki.cjs
|
|
205
486
|
INSTALLED_VER="${X509_VER}+pkijs-${PKIJS_VER}"
|
|
206
487
|
# Structured SBOM component versions, derived from the ACTUALLY-INSTALLED
|
|
@@ -222,14 +503,17 @@ esac
|
|
|
222
503
|
# Update MANIFEST.json. COMPONENT_VERSIONS_JSON (set only for meta-bundles that
|
|
223
504
|
# carry a structured components[] sub-object, e.g. peculiar-pki) is passed via
|
|
224
505
|
# the environment so its JSON braces/quotes don't fight the bash interpolation
|
|
225
|
-
# into the inline node script.
|
|
226
|
-
|
|
506
|
+
# into the inline node script. BUNDLER_DESC records the esbuild invocation that
|
|
507
|
+
# actually produced the artifact, so the manifest's bundler field can never
|
|
508
|
+
# drift from the command in the case-block above.
|
|
509
|
+
COMPONENT_VERSIONS_JSON="${COMPONENT_VERSIONS_JSON:-}" BUNDLER_DESC="${BUNDLER_DESC:-}" node -e "
|
|
227
510
|
var fs = require('fs');
|
|
228
511
|
var m = JSON.parse(fs.readFileSync('$MANIFEST', 'utf8'));
|
|
229
512
|
var pkg = '$PKG';
|
|
230
513
|
if (m.packages[pkg]) {
|
|
231
514
|
m.packages[pkg].version = '$INSTALLED_VER';
|
|
232
515
|
m.packages[pkg].bundledAt = '$DATE';
|
|
516
|
+
if (process.env.BUNDLER_DESC) { m.packages[pkg].bundler = process.env.BUNDLER_DESC; }
|
|
233
517
|
// Derive structured SBOM component versions from the ACTUALLY-INSTALLED
|
|
234
518
|
// packages (issue #366) so components[].version — the field CycloneDX / Trivy
|
|
235
519
|
// / Grype key on — can never drift from the bundled version string.
|