@blamejs/blamejs-shop 0.5.12 → 0.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/sales-tax-filings.js +143 -0
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -4,12 +4,19 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* b.contentCredentials — SB-942 / AB-853 / C2PA manifest builder, the
|
|
6
6
|
* COSE_Sign1 interop wrapper with its RFC 3161 sigTst2 countersignature,
|
|
7
|
-
* and the CAWG identity assertion.
|
|
7
|
+
* and the CAWG identity assertion. Also drives the error paths: validation
|
|
8
|
+
* refusals, malformed-input rejections, fail-closed verdicts across
|
|
9
|
+
* build / sign / verify / signCose / verifyCose / the identity assertion,
|
|
10
|
+
* and the GB 45438-2025 CAC implicit-label gate.
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
13
|
var helpers = require("../helpers");
|
|
14
|
+
var dbHelpers = require("../helpers/db");
|
|
11
15
|
var b = helpers.b;
|
|
12
16
|
var check = helpers.check;
|
|
17
|
+
var fs = helpers.fs;
|
|
18
|
+
var os = helpers.os;
|
|
19
|
+
var path = helpers.path;
|
|
13
20
|
var asn1 = require("../../lib/asn1-der");
|
|
14
21
|
var nodeCrypto = require("node:crypto");
|
|
15
22
|
|
|
@@ -53,7 +60,7 @@ function _makeTsaCert() {
|
|
|
53
60
|
// self-signed (issuer null). Used to assemble a real [leaf, intermediate,
|
|
54
61
|
// root] chain so the identity-assertion chain walk is exercised through
|
|
55
62
|
// an intermediate CA, not only a direct-root / self-signed leaf.
|
|
56
|
-
function _makeCert(cn, issuer, isCa) {
|
|
63
|
+
function _makeCert(cn, issuer, isCa, val) {
|
|
57
64
|
var kp = nodeCrypto.generateKeyPairSync("rsa", { modulusLength: 2048 });
|
|
58
65
|
var spki = kp.publicKey.export({ type: "spki", format: "der" });
|
|
59
66
|
var subjName = _certName(cn);
|
|
@@ -63,7 +70,12 @@ function _makeCert(cn, issuer, isCa) {
|
|
|
63
70
|
var version = asn1.writeContextExplicit(0, asn1.writeInteger(Buffer.from([2])));
|
|
64
71
|
var serial = asn1.writeInteger(Buffer.from([0x2b]));
|
|
65
72
|
var now = Date.now();
|
|
66
|
-
|
|
73
|
+
// Default validity is a wide now-1d..now+10y window; `val` ({ from, to } in
|
|
74
|
+
// epoch-ms) lets a caller mint an already-expired cert so the chain walk's
|
|
75
|
+
// per-cert and anchor validity-window rejections are exercised.
|
|
76
|
+
var vFrom = val && val.from != null ? val.from : now - 86400000;
|
|
77
|
+
var vTo = val && val.to != null ? val.to : now + 86400000 * 3650;
|
|
78
|
+
var validity = asn1.writeSequence([_utcTime(new Date(vFrom)), _utcTime(new Date(vTo))]);
|
|
67
79
|
var tbsChildren = [version, serial, sigAlgId, issuerName, validity, subjName, spki];
|
|
68
80
|
// Issuer (root / intermediate) certs carry basicConstraints cA:TRUE so the
|
|
69
81
|
// chain walk's cA enforcement (x509Chain.issuerValidlyIssued) accepts them;
|
|
@@ -132,6 +144,598 @@ function _timestampedRoundTrip(manifest, pair) {
|
|
|
132
144
|
return { req: req, attached: attached, cert: cert, token: token, anchorPem: anchorPem };
|
|
133
145
|
}
|
|
134
146
|
|
|
147
|
+
// ---- error-path fixtures ----
|
|
148
|
+
|
|
149
|
+
var cc = b.contentCredentials;
|
|
150
|
+
|
|
151
|
+
// Capture the error a thrower raises (or null when it does not throw) —
|
|
152
|
+
// one definition so the many config-time refusal checks below don't each
|
|
153
|
+
// re-roll a `threw = null; try {} catch {}` block.
|
|
154
|
+
function _err(fn) {
|
|
155
|
+
try { fn(); return null; } catch (e) { return e; }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
var VALID_BUILD = {
|
|
159
|
+
provider: "Acme AI Inc.", system: "acme-image-v3",
|
|
160
|
+
systemVersion: "3.2.1", contentId: "img-001",
|
|
161
|
+
};
|
|
162
|
+
function _buildOpts(overrides) {
|
|
163
|
+
return Object.assign({}, VALID_BUILD, overrides);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Error-path + adversarial-input checks: the validation refusals,
|
|
167
|
+
// malformed-input rejections, wrong-state protocol errors, and
|
|
168
|
+
// fail-closed verdicts the round-trip checks in run() never reach —
|
|
169
|
+
// bad build opts, missing required fields, signCose timestamp-posture
|
|
170
|
+
// and reuse-signature refusals, verifyCose malformed-CBOR / bad hashAlg
|
|
171
|
+
// / wrong-key verdicts, CAWG identity-assertion shape + trust-resolution
|
|
172
|
+
// refusals, and the GB 45438-2025 CAC implicit-label gate.
|
|
173
|
+
async function runErrorPaths() {
|
|
174
|
+
var e;
|
|
175
|
+
|
|
176
|
+
// ---- build() / _validateBuildOpts adversarial input ----
|
|
177
|
+
check("build(null) rejected as bad-opts",
|
|
178
|
+
(e = _err(function () { cc.build(null); })) && e.code === "content-credentials/bad-opts");
|
|
179
|
+
check("build('str') rejected as bad-opts",
|
|
180
|
+
(e = _err(function () { cc.build("nope"); })) && e.code === "content-credentials/bad-opts");
|
|
181
|
+
|
|
182
|
+
check("build missing system rejected",
|
|
183
|
+
(e = _err(function () { cc.build({ provider: "x", systemVersion: "1.0.0", contentId: "y" }); })) &&
|
|
184
|
+
e.code === "MISSING_SYSTEM");
|
|
185
|
+
check("build missing systemVersion rejected",
|
|
186
|
+
(e = _err(function () { cc.build({ provider: "x", system: "s", contentId: "y" }); })) &&
|
|
187
|
+
e.code === "MISSING_SYSTEMVERSION");
|
|
188
|
+
check("build missing contentId rejected",
|
|
189
|
+
(e = _err(function () { cc.build({ provider: "x", system: "s", systemVersion: "1.0.0" }); })) &&
|
|
190
|
+
e.code === "MISSING_CONTENTID");
|
|
191
|
+
|
|
192
|
+
check("build provider over 256 chars rejected",
|
|
193
|
+
(e = _err(function () { cc.build(_buildOpts({ provider: "a".repeat(257) })); })) &&
|
|
194
|
+
e.code === "content-credentials/bad-provider");
|
|
195
|
+
check("build system with illegal chars rejected",
|
|
196
|
+
(e = _err(function () { cc.build(_buildOpts({ system: "has space!" })); })) &&
|
|
197
|
+
e.code === "content-credentials/bad-system");
|
|
198
|
+
check("build systemVersion over 64 chars rejected",
|
|
199
|
+
(e = _err(function () { cc.build(_buildOpts({ systemVersion: "1.0.0-" + "a".repeat(60) })); })) &&
|
|
200
|
+
e.code === "content-credentials/bad-version");
|
|
201
|
+
check("build contentId with illegal chars rejected",
|
|
202
|
+
(e = _err(function () { cc.build(_buildOpts({ contentId: "bad id!" })); })) &&
|
|
203
|
+
e.code === "content-credentials/bad-content-id");
|
|
204
|
+
check("build contentSha3 wrong length rejected",
|
|
205
|
+
(e = _err(function () { cc.build(_buildOpts({ contentSha3: "abc123" })); })) &&
|
|
206
|
+
e.code === "content-credentials/bad-content-hash");
|
|
207
|
+
check("build contentSha3 non-hex rejected",
|
|
208
|
+
(e = _err(function () { cc.build(_buildOpts({ contentSha3: "z".repeat(128) })); })) &&
|
|
209
|
+
e.code === "content-credentials/bad-content-hash");
|
|
210
|
+
|
|
211
|
+
// Valid optional fields flow through (providerContact / sha3 / visibleDisclosure).
|
|
212
|
+
var mFull = cc.build(_buildOpts({
|
|
213
|
+
providerContact: "https://acme.example/contact",
|
|
214
|
+
contentType: "image/png", contentSha3: "a".repeat(128),
|
|
215
|
+
visibleDisclosure: "AI-generated by Acme",
|
|
216
|
+
}));
|
|
217
|
+
check("build carries optional contentSha3", mFull.content.sha3_512 === "a".repeat(128));
|
|
218
|
+
check("build carries providerContact", mFull.provider.contact === "https://acme.example/contact");
|
|
219
|
+
check("build carries visibleDisclosure", mFull.visibleDisclosure === "AI-generated by Acme");
|
|
220
|
+
|
|
221
|
+
// Adversarial numeric generatedAt (NaN) must not yield a manifest whose
|
|
222
|
+
// ISO timestamp is a broken value — either a clean rejection or a valid
|
|
223
|
+
// ISO string is acceptable; an unparseable generatedAtIso is not.
|
|
224
|
+
var nanRes = null, nanErr = null;
|
|
225
|
+
try { nanRes = cc.build(_buildOpts({ generatedAt: NaN })); } catch (ne) { nanErr = ne; }
|
|
226
|
+
check("build NaN generatedAt: rejected or valid ISO (no Invalid-Date manifest)",
|
|
227
|
+
nanErr !== null || (nanRes && !isNaN(Date.parse(nanRes.generatedAtIso))));
|
|
228
|
+
|
|
229
|
+
// ---- required() ----
|
|
230
|
+
check("required(null) returns opts-required",
|
|
231
|
+
JSON.stringify(cc.required(null)) === JSON.stringify(["opts-required"]));
|
|
232
|
+
check("required('str') returns opts-required",
|
|
233
|
+
JSON.stringify(cc.required("x")) === JSON.stringify(["opts-required"]));
|
|
234
|
+
var reqNonString = cc.required({ provider: 123, system: "s", systemVersion: "1.0.0", contentId: "c" });
|
|
235
|
+
check("required treats non-string provider as missing",
|
|
236
|
+
reqNonString.length === 1 && reqNonString[0] === "missing-provider");
|
|
237
|
+
|
|
238
|
+
// ---- sign() ----
|
|
239
|
+
var pair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
240
|
+
var manifest = cc.build(VALID_BUILD);
|
|
241
|
+
|
|
242
|
+
check("sign(null) rejected as bad-manifest",
|
|
243
|
+
(e = _err(function () { cc.sign(null, { privateKeyPem: pair.privateKey }); })) &&
|
|
244
|
+
e.code === "content-credentials/bad-manifest");
|
|
245
|
+
check("sign missing privateKeyPem rejected",
|
|
246
|
+
(e = _err(function () { cc.sign(manifest, {}); })) && e.code === "BAD_KEY");
|
|
247
|
+
check("sign no opts rejected",
|
|
248
|
+
(e = _err(function () { cc.sign(manifest); })) && e.code === "BAD_KEY");
|
|
249
|
+
|
|
250
|
+
// ---- verify() fail-closed verdicts (never throws) ----
|
|
251
|
+
var env = cc.sign(manifest, { privateKeyPem: pair.privateKey, audit: false });
|
|
252
|
+
check("verify(null) returns envelope-shape", cc.verify(null, pair.publicKey, { audit: false }).reason === "envelope-shape");
|
|
253
|
+
check("verify({}) returns envelope-shape", cc.verify({}, pair.publicKey, { audit: false }).reason === "envelope-shape");
|
|
254
|
+
check("verify empty signature returns envelope-shape",
|
|
255
|
+
cc.verify({ manifest: manifest, signature: "" }, pair.publicKey, { audit: false }).reason === "envelope-shape");
|
|
256
|
+
check("verify non-string key returns public-key-required",
|
|
257
|
+
cc.verify(env, 123, { audit: false }).reason === "public-key-required");
|
|
258
|
+
check("verify empty key returns public-key-required",
|
|
259
|
+
cc.verify(env, "", { audit: false }).reason === "public-key-required");
|
|
260
|
+
|
|
261
|
+
// A cryptographically valid signature over a payload that is NOT a
|
|
262
|
+
// complete SB-942 manifest must still fail the required-field gate.
|
|
263
|
+
var envPartial = cc.sign({ foo: "bar" }, { privateKeyPem: pair.privateKey, audit: false });
|
|
264
|
+
var vPartial = cc.verify(envPartial, pair.publicKey, { audit: false });
|
|
265
|
+
check("verify valid-sig-but-incomplete-manifest returns missing-required",
|
|
266
|
+
vPartial.valid === false && vPartial.reason.indexOf("missing-required") === 0);
|
|
267
|
+
|
|
268
|
+
// ---- signCose() config-time refusals ----
|
|
269
|
+
check("signCose(null) rejected as bad-manifest",
|
|
270
|
+
(e = _err(function () { cc.signCose(null, { privateKeyPem: pair.privateKey }); })) &&
|
|
271
|
+
e.code === "content-credentials/bad-manifest");
|
|
272
|
+
check("signCose missing privateKeyPem rejected",
|
|
273
|
+
(e = _err(function () { cc.signCose(manifest, { alg: "ml-dsa-87", timestamp: false, timestampOptOutReason: "x" }); })) &&
|
|
274
|
+
e.code === "BAD_KEY");
|
|
275
|
+
check("signCose timestamp as string rejected",
|
|
276
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: "soon" }); })) &&
|
|
277
|
+
e.code === "content-credentials/bad-timestamp");
|
|
278
|
+
check("signCose timestamp as array rejected",
|
|
279
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: [] }); })) &&
|
|
280
|
+
e.code === "content-credentials/bad-timestamp");
|
|
281
|
+
check("signCose timestamp with unknown key rejected",
|
|
282
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: { bogus: 1 } }); })) &&
|
|
283
|
+
/unknown option/.test(e.message));
|
|
284
|
+
check("signCose timestamp.token non-Buffer rejected",
|
|
285
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: { token: "not-a-buffer" } }); })) &&
|
|
286
|
+
e.code === "content-credentials/bad-timestamp-token");
|
|
287
|
+
check("signCose timestamp.signature empty rejected",
|
|
288
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: { token: Buffer.from([1]), signature: "" } }); })) &&
|
|
289
|
+
e.code === "content-credentials/bad-reuse-signature");
|
|
290
|
+
|
|
291
|
+
// An inherited Object.prototype member as the alg must not slip the COSE
|
|
292
|
+
// alg-registry check. `constructor` / `__proto__` survive `.toLowerCase()`
|
|
293
|
+
// and are truthy prototype-chain lookups, so an `in`-based guard would
|
|
294
|
+
// accept them and emit a signature under a bogus COSE alg id (fail-open).
|
|
295
|
+
check("signCose alg 'constructor' rejected (inherited member, not fail-open)",
|
|
296
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, alg: "constructor", timestamp: false, timestampOptOutReason: "x" }); })) &&
|
|
297
|
+
e.code === "content-credentials/bad-alg");
|
|
298
|
+
check("signCose alg '__proto__' rejected (inherited member, not fail-open)",
|
|
299
|
+
(e = _err(function () { cc.signCose(manifest, { privateKeyPem: pair.privateKey, alg: "__proto__", timestamp: false, timestampOptOutReason: "x" }); })) &&
|
|
300
|
+
e.code === "content-credentials/bad-alg");
|
|
301
|
+
|
|
302
|
+
// Reused (pinned) signature that does not verify against this manifest+key
|
|
303
|
+
// is refused — a stale or foreign signature can't be re-embedded.
|
|
304
|
+
check("signCose reuse-signature that does not verify is refused",
|
|
305
|
+
(e = _err(function () {
|
|
306
|
+
cc.signCose(manifest, { privateKeyPem: pair.privateKey,
|
|
307
|
+
timestamp: { token: Buffer.from([1, 2, 3]), signature: nodeCrypto.randomBytes(32).toString("base64") } });
|
|
308
|
+
})) && e.code === "content-credentials/reuse-signature-mismatch");
|
|
309
|
+
|
|
310
|
+
// certChain emission — single-cert and multi-cert branches (bytes are
|
|
311
|
+
// carried opaquely; a non-Buffer entry is rejected, not silently kept).
|
|
312
|
+
var coseSingle = cc.signCose(manifest, {
|
|
313
|
+
privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x",
|
|
314
|
+
certChain: [Buffer.from([1, 2, 3])], audit: false,
|
|
315
|
+
});
|
|
316
|
+
var coseMulti = cc.signCose(manifest, {
|
|
317
|
+
privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x",
|
|
318
|
+
certChain: [Buffer.from([1, 2, 3]), Buffer.from([4, 5, 6])], audit: false,
|
|
319
|
+
});
|
|
320
|
+
check("signCose single-cert certChain produces COSE bytes", Buffer.isBuffer(coseSingle.coseSign1));
|
|
321
|
+
check("signCose multi-cert certChain grows COSE bytes", coseMulti.coseSign1.length > coseSingle.coseSign1.length);
|
|
322
|
+
check("signCose non-Buffer certChain entry is rejected (throws)",
|
|
323
|
+
_err(function () {
|
|
324
|
+
cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: false,
|
|
325
|
+
timestampOptOutReason: "x", certChain: ["not a buffer"] });
|
|
326
|
+
}) !== null);
|
|
327
|
+
|
|
328
|
+
// ---- verifyCose() fail-closed verdicts (never throws) ----
|
|
329
|
+
var optout = cc.signCose(manifest, {
|
|
330
|
+
privateKeyPem: pair.privateKey, alg: "ml-dsa-87",
|
|
331
|
+
timestamp: false, timestampOptOutReason: "no TSA in test", audit: false,
|
|
332
|
+
});
|
|
333
|
+
check("verifyCose bad timestampHashAlg returns bad-tst-hash verdict",
|
|
334
|
+
cc.verifyCose(optout.coseSign1, pair.publicKey, { timestampHashAlg: "MD5", audit: false }).reason === "content-credentials/bad-tst-hash");
|
|
335
|
+
check("verifyCose non-CBOR (0x00) returns cose-malformed verdict",
|
|
336
|
+
cc.verifyCose(Buffer.from([0x00]), pair.publicKey, { audit: false }).reason === "content-credentials/cose-malformed");
|
|
337
|
+
check("verifyCose undecodable CBOR (0xff) returns cose-malformed verdict",
|
|
338
|
+
cc.verifyCose(Buffer.from([0xff]), pair.publicKey, { audit: false }).reason === "content-credentials/cose-malformed");
|
|
339
|
+
var otherPair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
340
|
+
var vWrongKey = cc.verifyCose(optout.coseSign1, otherPair.publicKey, { requireTimestamp: false, audit: false });
|
|
341
|
+
check("verifyCose wrong key returns signature-mismatch verdict",
|
|
342
|
+
vWrongKey.valid === false && vWrongKey.reason === "signature-mismatch");
|
|
343
|
+
|
|
344
|
+
// ---- attachIdentityAssertion() config-time refusals ----
|
|
345
|
+
var refs = [{ label: "c2pa.actions", data: { action: "c2pa.created" } }];
|
|
346
|
+
check("attach() no args rejected (bad binding)",
|
|
347
|
+
(e = _err(function () { cc.attachIdentityAssertion(); })) && e.code === "content-credentials/bad-identity-binding");
|
|
348
|
+
check("attach subject non-object rejected",
|
|
349
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: "nope", referencedAssertions: refs, privateKeyPem: pair.privateKey }); })) &&
|
|
350
|
+
e.code === "content-credentials/bad-identity-subject");
|
|
351
|
+
check("attach subject array rejected",
|
|
352
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: [], referencedAssertions: refs, privateKeyPem: pair.privateKey }); })) &&
|
|
353
|
+
e.code === "content-credentials/bad-identity-subject");
|
|
354
|
+
check("attach subject empty object rejected",
|
|
355
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: {}, referencedAssertions: refs, privateKeyPem: pair.privateKey }); })) &&
|
|
356
|
+
e.code === "content-credentials/bad-identity-subject");
|
|
357
|
+
check("attach referencedAssertions non-array rejected",
|
|
358
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: { name: "x" }, referencedAssertions: "nope", privateKeyPem: pair.privateKey }); })) &&
|
|
359
|
+
e.code === "content-credentials/bad-referenced-assertions");
|
|
360
|
+
check("attach referencedAssertions empty rejected",
|
|
361
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: { name: "x" }, referencedAssertions: [], privateKeyPem: pair.privateKey }); })) &&
|
|
362
|
+
e.code === "content-credentials/bad-referenced-assertions");
|
|
363
|
+
check("attach missing privateKeyPem rejected",
|
|
364
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: { name: "x" }, referencedAssertions: refs }); })) &&
|
|
365
|
+
e.code === "BAD_KEY");
|
|
366
|
+
check("attach unknown opt key rejected",
|
|
367
|
+
(e = _err(function () { cc.attachIdentityAssertion({ binding: "x509", subject: { name: "x" }, referencedAssertions: refs, privateKeyPem: pair.privateKey, bogus: 1 }); })) &&
|
|
368
|
+
/unknown option/.test(e.message));
|
|
369
|
+
|
|
370
|
+
// ---- verifyIdentityAssertion() fail-closed verdicts (never throws) ----
|
|
371
|
+
var ia = cc.attachIdentityAssertion({
|
|
372
|
+
binding: "x509", subject: { name: "Acme Newsroom" },
|
|
373
|
+
referencedAssertions: refs, privateKeyPem: pair.privateKey, audit: false,
|
|
374
|
+
});
|
|
375
|
+
check("verifyIdentity null assertion returns assertion-shape",
|
|
376
|
+
cc.verifyIdentityAssertion(null, pair.publicKey, { referencedAssertions: refs }).reason === "assertion-shape");
|
|
377
|
+
check("verifyIdentity missing signer_payload returns assertion-shape",
|
|
378
|
+
cc.verifyIdentityAssertion({ signature: "x" }, pair.publicKey, { referencedAssertions: refs }).reason === "assertion-shape");
|
|
379
|
+
check("verifyIdentity non-string key returns public-key-required",
|
|
380
|
+
cc.verifyIdentityAssertion(ia, 123, { referencedAssertions: refs }).reason === "public-key-required");
|
|
381
|
+
check("verifyIdentity bad signer_payload binding returns signer-payload-shape",
|
|
382
|
+
cc.verifyIdentityAssertion({ signer_payload: { binding: "bogus", referenced_assertions: [] }, signature: "AA==" }, pair.publicKey, { referencedAssertions: refs }).reason === "signer-payload-shape");
|
|
383
|
+
check("verifyIdentity missing referencedAssertions opt returns referenced-assertions-required",
|
|
384
|
+
cc.verifyIdentityAssertion(ia, pair.publicKey, { audit: false }).reason === "referenced-assertions-required");
|
|
385
|
+
check("verifyIdentity referencedAssertions count mismatch returns count-mismatch",
|
|
386
|
+
cc.verifyIdentityAssertion(ia, pair.publicKey, { referencedAssertions: [refs[0], { label: "b" }], audit: false }).reason === "referenced-assertions-count-mismatch");
|
|
387
|
+
|
|
388
|
+
// x509 trust-resolution reason branches (self-asserted -> verified:false).
|
|
389
|
+
var vNoChain = cc.verifyIdentityAssertion(ia, pair.publicKey, {
|
|
390
|
+
referencedAssertions: refs, identityTrustAnchorsPem: "anchor-pem", audit: false,
|
|
391
|
+
});
|
|
392
|
+
check("verifyIdentity anchor but no chain -> verified:false no-cert-chain",
|
|
393
|
+
vNoChain.valid === true && vNoChain.verified === false && vNoChain.reason === "no-cert-chain");
|
|
394
|
+
var vBadAnchors = cc.verifyIdentityAssertion(ia, pair.publicKey, {
|
|
395
|
+
referencedAssertions: refs, identityCertChainPem: "chain-pem", identityTrustAnchorsPem: "", audit: false,
|
|
396
|
+
});
|
|
397
|
+
check("verifyIdentity empty trust anchor -> verified:false bad-trust-anchors",
|
|
398
|
+
vBadAnchors.verified === false && vBadAnchors.reason === "bad-trust-anchors");
|
|
399
|
+
var vBadChain = cc.verifyIdentityAssertion(ia, pair.publicKey, {
|
|
400
|
+
referencedAssertions: refs, identityCertChainPem: "not a pem", identityTrustAnchorsPem: "also not a pem", audit: false,
|
|
401
|
+
});
|
|
402
|
+
check("verifyIdentity unparseable chain cert -> verified:false bad-chain-cert",
|
|
403
|
+
vBadChain.verified === false && vBadChain.reason === "bad-chain-cert");
|
|
404
|
+
|
|
405
|
+
// ---- cacImplicitLabel() GB 45438-2025 gate ----
|
|
406
|
+
var CAC_VALID = {
|
|
407
|
+
providerName: "Example AI", providerCode: "91110000600037341A",
|
|
408
|
+
contentId: "asset-2026-05-17-abc123", contentKind: "image",
|
|
409
|
+
generatedAt: "2026-05-17T20:00:00Z",
|
|
410
|
+
};
|
|
411
|
+
function _cac(overrides) { return Object.assign({}, CAC_VALID, overrides); }
|
|
412
|
+
|
|
413
|
+
var label = cc.cacImplicitLabel(CAC_VALID);
|
|
414
|
+
check("cacImplicitLabel valid returns frozen AIGC block",
|
|
415
|
+
Object.isFrozen(label) && label.aigcMarker === "AIGC" && label.providerCode === "91110000600037341A");
|
|
416
|
+
check("cacImplicitLabel(null) rejected",
|
|
417
|
+
(e = _err(function () { cc.cacImplicitLabel(null); })) && e.code === "cac-implicit-label/bad-opts");
|
|
418
|
+
check("cacImplicitLabel missing providerName rejected",
|
|
419
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ providerName: undefined })); })) &&
|
|
420
|
+
e.code === "cac-implicit-label/bad-provider-name");
|
|
421
|
+
check("cacImplicitLabel oversize providerName rejected",
|
|
422
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ providerName: "a".repeat(257) })); })) &&
|
|
423
|
+
e.code === "cac-implicit-label/oversize-provider-name");
|
|
424
|
+
check("cacImplicitLabel bad providerCode rejected",
|
|
425
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ providerCode: "123" })); })) &&
|
|
426
|
+
e.code === "cac-implicit-label/bad-provider-code");
|
|
427
|
+
check("cacImplicitLabel illegal contentId rejected",
|
|
428
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ contentId: "bad id!" })); })) &&
|
|
429
|
+
e.code === "cac-implicit-label/bad-content-id");
|
|
430
|
+
check("cacImplicitLabel unknown contentKind rejected",
|
|
431
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ contentKind: "hologram" })); })) &&
|
|
432
|
+
e.code === "cac-implicit-label/bad-content-kind");
|
|
433
|
+
check("cacImplicitLabel non-ISO generatedAt rejected",
|
|
434
|
+
(e = _err(function () { cc.cacImplicitLabel(_cac({ generatedAt: "yesterday" })); })) &&
|
|
435
|
+
e.code === "cac-implicit-label/bad-generated-at");
|
|
436
|
+
|
|
437
|
+
// ---- cacImplicitLabelRead() parser ----
|
|
438
|
+
check("cacImplicitLabelRead object input",
|
|
439
|
+
cc.cacImplicitLabelRead(Object.assign({ aigcMarker: "AIGC" }, CAC_VALID)).aigcMarker === "AIGC");
|
|
440
|
+
check("cacImplicitLabelRead string input",
|
|
441
|
+
cc.cacImplicitLabelRead(JSON.stringify(Object.assign({ aigcMarker: "AIGC" }, CAC_VALID))).contentKind === "image");
|
|
442
|
+
check("cacImplicitLabelRead Buffer input",
|
|
443
|
+
cc.cacImplicitLabelRead(Buffer.from(JSON.stringify(Object.assign({ aigcMarker: "AIGC" }, CAC_VALID)))).providerCode === "91110000600037341A");
|
|
444
|
+
check("cacImplicitLabelRead malformed JSON string rejected",
|
|
445
|
+
(e = _err(function () { cc.cacImplicitLabelRead("{not json"); })) && e.code === "cac-implicit-label/bad-json");
|
|
446
|
+
check("cacImplicitLabelRead malformed JSON Buffer rejected",
|
|
447
|
+
(e = _err(function () { cc.cacImplicitLabelRead(Buffer.from("{not json")); })) && e.code === "cac-implicit-label/bad-json");
|
|
448
|
+
check("cacImplicitLabelRead numeric input rejected",
|
|
449
|
+
(e = _err(function () { cc.cacImplicitLabelRead(42); })) && e.code === "cac-implicit-label/bad-input");
|
|
450
|
+
check("cacImplicitLabelRead missing AIGC marker rejected",
|
|
451
|
+
(e = _err(function () { cc.cacImplicitLabelRead({ providerName: "x" }); })) &&
|
|
452
|
+
e.code === "cac-implicit-label/missing-aigc-marker");
|
|
453
|
+
check("cacImplicitLabelRead re-applies field gate",
|
|
454
|
+
(e = _err(function () { cc.cacImplicitLabelRead(Object.assign({ aigcMarker: "AIGC" }, CAC_VALID, { providerCode: "BAD" })); })) &&
|
|
455
|
+
e.code === "cac-implicit-label/bad-provider-code");
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Default-on audit branches: every build / sign / verify / signCose /
|
|
459
|
+
// verifyCose and the CAWG identity assertion carries an `audit !== false`
|
|
460
|
+
// emit block the audit:false round-trips never execute. Drive each through
|
|
461
|
+
// the REAL audit sink (setupTestDb wires the encrypted db + audit chain)
|
|
462
|
+
// and assert durable rows land — the emit does real work, not a no-op —
|
|
463
|
+
// covering both the success and the fail-closed "denied" audit paths.
|
|
464
|
+
async function runAuditOnPaths() {
|
|
465
|
+
var tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-cc-audit-"));
|
|
466
|
+
await dbHelpers.setupTestDb(tmpDir);
|
|
467
|
+
try {
|
|
468
|
+
var pair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
469
|
+
var manifest = cc.build(VALID_BUILD);
|
|
470
|
+
|
|
471
|
+
// sign() + verify() audit-on (verify called with opts omitted → opts:{}).
|
|
472
|
+
var env = cc.sign(manifest, { privateKeyPem: pair.privateKey });
|
|
473
|
+
check("audit-on verify still valid", cc.verify(env, pair.publicKey).valid === true);
|
|
474
|
+
|
|
475
|
+
// signCose audit-on: opt-out (warning outcome), request, and attach.
|
|
476
|
+
cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "no TSA in audit test" });
|
|
477
|
+
cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: {} });
|
|
478
|
+
var rt = _timestampedRoundTrip(manifest, pair);
|
|
479
|
+
var attachedAudited = cc.signCose(manifest, {
|
|
480
|
+
privateKeyPem: pair.privateKey, alg: "ml-dsa-87",
|
|
481
|
+
timestamp: { token: rt.token, signature: rt.req.timestampRequest.signature },
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// verifyCose audit-on: success (1054-1066), signature-mismatch (967-969),
|
|
485
|
+
// timestamp-required (1017-1019), timestamp-invalid (1027-1029), and
|
|
486
|
+
// missing-required (1047-1049) denied-audit blocks.
|
|
487
|
+
var vc = cc.verifyCose(attachedAudited.coseSign1, pair.publicKey, {
|
|
488
|
+
timestampNonce: rt.req.timestampRequest.nonce, timestampTrustAnchorsPem: [rt.anchorPem],
|
|
489
|
+
});
|
|
490
|
+
check("audit-on verifyCose success", vc.valid === true);
|
|
491
|
+
var otherPair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
492
|
+
cc.verifyCose(attachedAudited.coseSign1, otherPair.publicKey, { requireTimestamp: false });
|
|
493
|
+
var optout = cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x", audit: false });
|
|
494
|
+
cc.verifyCose(optout.coseSign1, pair.publicKey); // token-less → timestamp-required (opts omitted → opts:{})
|
|
495
|
+
cc.verifyCose(rt.attached.coseSign1, pair.publicKey, { timestampNonce: nodeCrypto.randomBytes(8) }); // wrong nonce → timestamp-invalid
|
|
496
|
+
var incompleteCose = cc.signCose({ provider: { name: "x" } }, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x", audit: false });
|
|
497
|
+
cc.verifyCose(incompleteCose.coseSign1, pair.publicKey, { requireTimestamp: false }); // missing-required
|
|
498
|
+
|
|
499
|
+
// attachIdentityAssertion + verifyIdentityAssertion audit-on (success/
|
|
500
|
+
// warning + signature-mismatch + assertion-hash-mismatch denied audits).
|
|
501
|
+
var refs = [{ label: "c2pa.actions", data: { action: "c2pa.created" } }];
|
|
502
|
+
var ia = cc.attachIdentityAssertion({ binding: "x509", subject: { name: "Acme Newsroom" }, referencedAssertions: refs, privateKeyPem: pair.privateKey });
|
|
503
|
+
cc.verifyIdentityAssertion(ia, pair.publicKey, { referencedAssertions: refs }); // self-asserted → warning
|
|
504
|
+
cc.verifyIdentityAssertion(ia, otherPair.publicKey, { referencedAssertions: refs }); // wrong key → denied
|
|
505
|
+
cc.verifyIdentityAssertion(ia, pair.publicKey, { referencedAssertions: [{ label: "x", data: { other: 1 } }] }); // transplant → denied
|
|
506
|
+
// x509 chained to a trusted anchor → verified:true, audit outcome "success".
|
|
507
|
+
var trustCert = _makeTsaCert();
|
|
508
|
+
var trustPem = new nodeCrypto.X509Certificate(trustCert.certDer).toString();
|
|
509
|
+
var iaVerified = cc.verifyIdentityAssertion(ia, pair.publicKey, { referencedAssertions: refs, identityCertChainPem: trustPem, identityTrustAnchorsPem: trustPem });
|
|
510
|
+
check("audit-on identity verified:true (x509 chained)", iaVerified.verified === true);
|
|
511
|
+
|
|
512
|
+
await b.audit.flush();
|
|
513
|
+
var signedRows = await b.audit.query({ action: "contentcredentials.signed" });
|
|
514
|
+
var verifiedRows = await b.audit.query({ action: "contentcredentials.verified" });
|
|
515
|
+
var signedCoseRows = await b.audit.query({ action: "contentcredentials.signed_cose" });
|
|
516
|
+
var verifiedCoseRows = await b.audit.query({ action: "contentcredentials.verified_cose" });
|
|
517
|
+
var identAttachRows = await b.audit.query({ action: "contentcredentials.identity_attached" });
|
|
518
|
+
var identVerifyRows = await b.audit.query({ action: "contentcredentials.identity_verified" });
|
|
519
|
+
check("audit-on: b.contentCredentials.sign emits a durable row", signedRows.length >= 1);
|
|
520
|
+
check("audit-on: b.contentCredentials.verify emits a durable row", verifiedRows.length >= 1);
|
|
521
|
+
check("audit-on: b.contentCredentials.signCose emits durable rows (optout/request/attach)", signedCoseRows.length >= 3);
|
|
522
|
+
check("audit-on: b.contentCredentials.verifyCose emits durable rows (success + denied)", verifiedCoseRows.length >= 4);
|
|
523
|
+
check("audit-on: b.contentCredentials.attachIdentityAssertion emits a durable row", identAttachRows.length >= 1);
|
|
524
|
+
check("audit-on: b.contentCredentials.verifyIdentityAssertion emits durable rows", identVerifyRows.length >= 3);
|
|
525
|
+
} finally {
|
|
526
|
+
await dbHelpers.teardownTestDb(tmpDir);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// CBOR + COSE_Sign1 encode/decode edge branches: the large-length CBOR
|
|
531
|
+
// paths, the malformed-COSE structural rejections, the empty / non-decodable
|
|
532
|
+
// protected header, and the config-time input branches (numeric generatedAt,
|
|
533
|
+
// non-string signature, reuse-signature key mismatch) the happy-path
|
|
534
|
+
// round-trips never reach.
|
|
535
|
+
async function runCoseEdgeCases() {
|
|
536
|
+
var pair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
537
|
+
var manifest = cc.build(VALID_BUILD);
|
|
538
|
+
|
|
539
|
+
// build(): a valid numeric generatedAt flows through the pinned-timestamp
|
|
540
|
+
// branch rather than defaulting to Date.now().
|
|
541
|
+
var pinned = cc.build(_buildOpts({ generatedAt: Date.UTC(2026, 4, 8) }));
|
|
542
|
+
check("build honors a valid numeric generatedAt",
|
|
543
|
+
pinned.generatedAt === Date.UTC(2026, 4, 8) && pinned.generatedAtIso === "2026-05-08T00:00:00.000Z");
|
|
544
|
+
|
|
545
|
+
// verify(): a non-string (numeric) signature is truthy but Buffer.from(n)
|
|
546
|
+
// throws → the base64 catch returns signature-base64-bad, never crashes.
|
|
547
|
+
check("verify numeric signature returns signature-base64-bad",
|
|
548
|
+
cc.verify({ manifest: manifest, signature: 12345 }, pair.publicKey, { audit: false }).reason === "signature-base64-bad");
|
|
549
|
+
|
|
550
|
+
// signCose reuse mode with a malformed private-key PEM: _publicKeyFromPrivatePem
|
|
551
|
+
// catches the createPublicKey throw and returns false → reuse mismatch.
|
|
552
|
+
check("signCose reuse-mode with unparseable PEM refused as reuse-signature-mismatch",
|
|
553
|
+
(function () {
|
|
554
|
+
var er = _err(function () {
|
|
555
|
+
cc.signCose(manifest, { privateKeyPem: "-----BEGIN PRIVATE KEY-----\nnope\n-----END PRIVATE KEY-----",
|
|
556
|
+
timestamp: { token: Buffer.from([1]), signature: "AAAA" } });
|
|
557
|
+
});
|
|
558
|
+
return er && er.code === "content-credentials/reuse-signature-mismatch";
|
|
559
|
+
})());
|
|
560
|
+
|
|
561
|
+
// signCose with opts omitted defaults opts to {} then rejects the missing key.
|
|
562
|
+
check("signCose with no opts rejected as BAD_KEY",
|
|
563
|
+
(function () { var er = _err(function () { cc.signCose(manifest); }); return er && er.code === "BAD_KEY"; })());
|
|
564
|
+
|
|
565
|
+
// signCose attach WITHOUT a re-pinned signature signs fresh (the
|
|
566
|
+
// reuseSignature==null branch) and still emits a timestamped COSE.
|
|
567
|
+
var attachFresh = cc.signCose(manifest, {
|
|
568
|
+
privateKeyPem: pair.privateKey, timestamp: { token: Buffer.from([1, 2, 3]) }, audit: false,
|
|
569
|
+
});
|
|
570
|
+
check("signCose attach without reuse-signature signs fresh + timestamped",
|
|
571
|
+
attachFresh.timestamped === true && Buffer.isBuffer(attachFresh.coseSign1));
|
|
572
|
+
|
|
573
|
+
// Large certChain crosses the CBOR array-header length thresholds
|
|
574
|
+
// (24 → 1-byte count header, 300 → 2-byte count header).
|
|
575
|
+
function _dummyChain(n) { var a = []; for (var i = 0; i < n; i += 1) a.push(Buffer.from([i & 0xff])); return a; }
|
|
576
|
+
var cose24 = cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x", certChain: _dummyChain(24), audit: false });
|
|
577
|
+
var cose300 = cc.signCose(manifest, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x", certChain: _dummyChain(300), audit: false });
|
|
578
|
+
check("signCose 24-cert chain (CBOR 1-byte array header) emits COSE bytes", Buffer.isBuffer(cose24.coseSign1));
|
|
579
|
+
check("signCose 300-cert chain (CBOR 2-byte array header) grows the COSE bytes", cose300.coseSign1.length > cose24.coseSign1.length);
|
|
580
|
+
|
|
581
|
+
// A cert chain at the CBOR array-count ceiling (65536 entries) overflows the
|
|
582
|
+
// 2-byte array-header range: _cborArrayHeader refuses it fail-closed with a
|
|
583
|
+
// typed cbor-overflow error rather than emitting a truncated length header
|
|
584
|
+
// that would silently misframe the x5chain array. Every fixed protocol
|
|
585
|
+
// codepoint (tag 18, labels 1/33/35, ≤2-entry maps) stays well below this
|
|
586
|
+
// ceiling, so an operator-supplied absurd chain is the only path here.
|
|
587
|
+
var overflowErr = _err(function () {
|
|
588
|
+
b.contentCredentials.signCose(manifest, {
|
|
589
|
+
privateKeyPem: pair.privateKey, timestamp: false,
|
|
590
|
+
timestampOptOutReason: "x", certChain: _dummyChain(65536), audit: false,
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
check("signCose certChain at the CBOR array ceiling (65536) refused as cbor-overflow",
|
|
594
|
+
overflowErr && overflowErr.code === "content-credentials/cbor-overflow");
|
|
595
|
+
|
|
596
|
+
// A >1 MiB manifest payload crosses the 4-byte CBOR byte-string length
|
|
597
|
+
// path AND, on verify, exceeds the safeJson payload cap so claims parse
|
|
598
|
+
// is caught (claims:null) → the required-field gate fails it closed.
|
|
599
|
+
var huge = cc.build(_buildOpts({ visibleDisclosure: "a".repeat(1100000) }));
|
|
600
|
+
var coseHuge = cc.signCose(huge, { privateKeyPem: pair.privateKey, timestamp: false, timestampOptOutReason: "x", audit: false });
|
|
601
|
+
check("signCose >1 MiB payload produces a multi-MiB COSE (4-byte length header)", coseHuge.coseSign1.length > 1048576);
|
|
602
|
+
var vHuge = cc.verifyCose(coseHuge.coseSign1, pair.publicKey, { requireTimestamp: false, audit: false });
|
|
603
|
+
check("verifyCose oversized payload fails closed (claims unrecoverable → missing-required)",
|
|
604
|
+
vHuge.valid === false && vHuge.claims === null && vHuge.reason.indexOf("missing-required") === 0);
|
|
605
|
+
|
|
606
|
+
// Malformed COSE_Sign1 shapes decode but fail the structural gate in
|
|
607
|
+
// _decodeCoseSign1 → cose-malformed verdict (never a throw).
|
|
608
|
+
function _vc(bytes) { return cc.verifyCose(bytes, pair.publicKey, { requireTimestamp: false, audit: false }); }
|
|
609
|
+
check("verifyCose 3-element array rejected as cose-malformed",
|
|
610
|
+
_vc(Buffer.from([0x83, 0x01, 0x02, 0x03])).reason === "content-credentials/cose-malformed");
|
|
611
|
+
check("verifyCose non-bytestring protected header rejected as cose-malformed",
|
|
612
|
+
_vc(Buffer.from([0x84, 0x01, 0xA0, 0x40, 0x40])).reason === "content-credentials/cose-malformed");
|
|
613
|
+
check("verifyCose non-map unprotected header rejected as cose-malformed",
|
|
614
|
+
_vc(Buffer.from([0x84, 0x40, 0x40, 0x40, 0x40])).reason === "content-credentials/cose-malformed");
|
|
615
|
+
|
|
616
|
+
// Well-formed COSE shape with an EMPTY protected header → alg decode yields
|
|
617
|
+
// an empty map (algName null); with a NON-DECODABLE protected header → the
|
|
618
|
+
// alg decode catch (algName null). Both then fail the signature check
|
|
619
|
+
// (garbage signature) → signature-mismatch, not a throw.
|
|
620
|
+
var vEmptyProt = _vc(Buffer.from([0x84, 0x40, 0xA0, 0x41, 0x00, 0x41, 0x00]));
|
|
621
|
+
check("verifyCose empty protected header → signature-mismatch (alg null)",
|
|
622
|
+
vEmptyProt.valid === false && vEmptyProt.reason === "signature-mismatch" && vEmptyProt.alg === null);
|
|
623
|
+
var vBadProt = _vc(Buffer.from([0x84, 0x41, 0xFF, 0xA0, 0x41, 0x00, 0x41, 0x00]));
|
|
624
|
+
check("verifyCose non-decodable protected header → signature-mismatch (alg null)",
|
|
625
|
+
vBadProt.valid === false && vBadProt.reason === "signature-mismatch" && vBadProt.alg === null);
|
|
626
|
+
|
|
627
|
+
// verifyCose signature verify THROWS on a malformed (non-empty) public-key
|
|
628
|
+
// PEM → the catch sets sigOk false → signature-mismatch.
|
|
629
|
+
var vBadKey = cc.verifyCose(Buffer.from([0x84, 0x40, 0xA0, 0x41, 0x00, 0x41, 0x00]),
|
|
630
|
+
"-----BEGIN PUBLIC KEY-----\nnotvalid\n-----END PUBLIC KEY-----", { requireTimestamp: false, audit: false });
|
|
631
|
+
check("verifyCose malformed public key PEM → signature-mismatch (verify throw caught)",
|
|
632
|
+
vBadKey.valid === false && vBadKey.reason === "signature-mismatch");
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// _verifyIdentityX509Chain error branches: the certificate-parse failures,
|
|
636
|
+
// expired-cert rejections, and broken-linkage refusals a valid chain never
|
|
637
|
+
// reaches. Each surfaces as verified:false with a specific reason while
|
|
638
|
+
// valid stays true (the signature + hash-binding are intact).
|
|
639
|
+
async function runX509ChainErrorBranches() {
|
|
640
|
+
var pair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
641
|
+
var refs = [{ label: "c2pa.actions", data: { action: "c2pa.created" } }];
|
|
642
|
+
var ia = cc.attachIdentityAssertion({
|
|
643
|
+
binding: "x509", subject: { name: "Acme Newsroom" },
|
|
644
|
+
referencedAssertions: refs, privateKeyPem: pair.privateKey, audit: false,
|
|
645
|
+
});
|
|
646
|
+
function _vi(trustOpts) {
|
|
647
|
+
return cc.verifyIdentityAssertion(ia, pair.publicKey,
|
|
648
|
+
Object.assign({ referencedAssertions: refs, audit: false }, trustOpts));
|
|
649
|
+
}
|
|
650
|
+
var DAY = 86400000;
|
|
651
|
+
var now = Date.now();
|
|
652
|
+
|
|
653
|
+
// Valid chain leaf but an unparseable trust anchor → bad-anchor-cert
|
|
654
|
+
// (the chain parses first, then the anchor parse throws).
|
|
655
|
+
var leaf = _makeCert("Acme Leaf", null, false);
|
|
656
|
+
check("verifyIdentity valid chain + garbage anchor → bad-anchor-cert",
|
|
657
|
+
_vi({ identityCertChainPem: leaf.pem, identityTrustAnchorsPem: "not-a-pem" }).reason === "bad-anchor-cert");
|
|
658
|
+
|
|
659
|
+
// An expired leaf in the presented chain → leaf-expired.
|
|
660
|
+
var expiredLeaf = _makeCert("Expired Leaf", null, false, { from: now - DAY * 10, to: now - DAY * 5 });
|
|
661
|
+
check("verifyIdentity expired leaf cert → leaf-expired",
|
|
662
|
+
_vi({ identityCertChainPem: expiredLeaf.pem, identityTrustAnchorsPem: leaf.pem }).reason === "leaf-expired");
|
|
663
|
+
|
|
664
|
+
// A chain whose presented intermediate did NOT issue the leaf → broken-chain.
|
|
665
|
+
var root = _makeCert("Chain Root", null, true);
|
|
666
|
+
var inter = _makeCert("Chain Intermediate", { name: root.name, key: root.key }, true);
|
|
667
|
+
var leafSigned = _makeCert("Chain Leaf", { name: inter.name, key: inter.key }, false);
|
|
668
|
+
var rogueInter = _makeCert("Rogue Intermediate", null, true);
|
|
669
|
+
check("verifyIdentity leaf not issued by presented intermediate → broken-chain",
|
|
670
|
+
_vi({ identityCertChainPem: [leafSigned.pem, rogueInter.pem], identityTrustAnchorsPem: root.pem }).reason === "broken-chain");
|
|
671
|
+
|
|
672
|
+
// Chain links to an EXPIRED trust anchor → anchor-expired (the chain certs
|
|
673
|
+
// are valid; only the anchor's own validity window has passed).
|
|
674
|
+
var expiredRoot = _makeCert("Expired Root", null, true, { from: now - DAY * 10, to: now - DAY * 5 });
|
|
675
|
+
var leafOfExpired = _makeCert("Leaf of Expired Root", { name: expiredRoot.name, key: expiredRoot.key }, false);
|
|
676
|
+
check("verifyIdentity chain to expired anchor → anchor-expired",
|
|
677
|
+
_vi({ identityCertChainPem: leafOfExpired.pem, identityTrustAnchorsPem: expiredRoot.pem }).reason === "anchor-expired");
|
|
678
|
+
|
|
679
|
+
// An expired NON-leaf cert in the presented chain → chain-cert-expired
|
|
680
|
+
// (the per-cert validity loop rejects at index !== 0, before linkage).
|
|
681
|
+
var validLeaf2 = _makeCert("Valid Leaf 2", null, false);
|
|
682
|
+
var expiredCa = _makeCert("Expired CA", null, true, { from: now - DAY * 10, to: now - DAY * 5 });
|
|
683
|
+
check("verifyIdentity expired non-leaf chain cert → chain-cert-expired",
|
|
684
|
+
_vi({ identityCertChainPem: [validLeaf2.pem, expiredCa.pem], identityTrustAnchorsPem: leaf.pem }).reason === "chain-cert-expired");
|
|
685
|
+
|
|
686
|
+
// Trust anchors supplied as an ARRAY (not a single PEM string) still resolve
|
|
687
|
+
// — the [leaf, intermediate] chain verifies to the array-form root anchor.
|
|
688
|
+
var arrRoot = _makeCert("Array Anchor Root", null, true);
|
|
689
|
+
var arrInter = _makeCert("Array Anchor Intermediate", { name: arrRoot.name, key: arrRoot.key }, true);
|
|
690
|
+
var arrLeaf = _makeCert("Array Anchor Leaf", { name: arrInter.name, key: arrInter.key }, false);
|
|
691
|
+
var vArr = _vi({ identityCertChainPem: [arrLeaf.pem, arrInter.pem], identityTrustAnchorsPem: [arrRoot.pem] });
|
|
692
|
+
check("verifyIdentity array-form trust anchor verifies", vArr.valid === true && vArr.verified === true);
|
|
693
|
+
|
|
694
|
+
// A trust anchor of the wrong type (neither PEM string nor array) →
|
|
695
|
+
// bad-trust-anchors (the anchor-normalization null branch).
|
|
696
|
+
check("verifyIdentity wrong-type trust anchor → bad-trust-anchors",
|
|
697
|
+
_vi({ identityCertChainPem: leaf.pem, identityTrustAnchorsPem: 12345 }).reason === "bad-trust-anchors");
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// CAWG identity-assertion + GB 45438-2025 CAC-label input branches the
|
|
701
|
+
// happy-path checks miss: a non-string assertion signature, a malformed
|
|
702
|
+
// verification key, the opts-omitted default, and the contentId length ceiling.
|
|
703
|
+
async function runIdentityAndCacEdge() {
|
|
704
|
+
var pair = b.crypto.generateSigningKeyPair("ml-dsa-87");
|
|
705
|
+
var refs = [{ label: "c2pa.actions", data: { action: "c2pa.created" } }];
|
|
706
|
+
|
|
707
|
+
// A structurally valid signer_payload with a NON-STRING signature: the
|
|
708
|
+
// shape gate passes, then Buffer.from(number) throws → signature-base64-bad.
|
|
709
|
+
var spShaped = { signer_payload: { binding: "x509", subject: { name: "n" }, referenced_assertions: [] }, signature: 12345 };
|
|
710
|
+
check("verifyIdentity numeric signature returns signature-base64-bad",
|
|
711
|
+
cc.verifyIdentityAssertion(spShaped, pair.publicKey, { referencedAssertions: refs, audit: false }).reason === "signature-base64-bad");
|
|
712
|
+
|
|
713
|
+
var ia = cc.attachIdentityAssertion({
|
|
714
|
+
binding: "x509", subject: { name: "n" }, referencedAssertions: refs,
|
|
715
|
+
privateKeyPem: pair.privateKey, audit: false,
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
// A malformed (non-empty) verification key makes b.crypto.verify throw →
|
|
719
|
+
// the catch sets sigOk false → signature-mismatch (fail closed, no throw).
|
|
720
|
+
check("verifyIdentity malformed key → signature-mismatch (verify throw caught)",
|
|
721
|
+
cc.verifyIdentityAssertion(ia, "-----BEGIN PUBLIC KEY-----\nnope\n-----END PUBLIC KEY-----",
|
|
722
|
+
{ referencedAssertions: refs, audit: false }).reason === "signature-mismatch");
|
|
723
|
+
|
|
724
|
+
// verifyIdentityAssertion with opts omitted defaults opts to {} then fails
|
|
725
|
+
// the required-referencedAssertions gate (never throws).
|
|
726
|
+
check("verifyIdentity with no opts → referenced-assertions-required",
|
|
727
|
+
cc.verifyIdentityAssertion(ia, pair.publicKey).reason === "referenced-assertions-required");
|
|
728
|
+
|
|
729
|
+
// cacImplicitLabel contentId over the 128-char ceiling → bad-content-id
|
|
730
|
+
// (the length branch, distinct from the illegal-character branch).
|
|
731
|
+
var e;
|
|
732
|
+
check("cacImplicitLabel over-long contentId (>128) rejected as bad-content-id",
|
|
733
|
+
(e = _err(function () {
|
|
734
|
+
cc.cacImplicitLabel({ providerName: "P", providerCode: "91110000600037341A",
|
|
735
|
+
contentId: "a".repeat(129), contentKind: "image", generatedAt: "2026-05-17T20:00:00Z" });
|
|
736
|
+
})) && e.code === "cac-implicit-label/bad-content-id");
|
|
737
|
+
}
|
|
738
|
+
|
|
135
739
|
async function run() {
|
|
136
740
|
check("build is fn", typeof b.contentCredentials.build === "function");
|
|
137
741
|
check("sign is fn", typeof b.contentCredentials.sign === "function");
|
|
@@ -383,6 +987,12 @@ async function run() {
|
|
|
383
987
|
try { b.contentCredentials.attachIdentityAssertion({ binding: "made-up", subject: { name: "x" }, referencedAssertions: refs, privateKeyPem: orgPair.privateKey }); }
|
|
384
988
|
catch (e) { threw = e; }
|
|
385
989
|
check("attachIdentityAssertion: bad binding refused", threw && threw.code === "content-credentials/bad-identity-binding");
|
|
990
|
+
|
|
991
|
+
await runErrorPaths();
|
|
992
|
+
await runCoseEdgeCases();
|
|
993
|
+
await runX509ChainErrorBranches();
|
|
994
|
+
await runIdentityAndCacEdge();
|
|
995
|
+
await runAuditOnPaths();
|
|
386
996
|
}
|
|
387
997
|
|
|
388
998
|
module.exports = { run: run };
|