@blamejs/blamejs-shop 0.4.56 → 0.4.57
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 +426 -366
- package/lib/vendor/blamejs/.github/codeql/codeql-config.yml +25 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/ci.yml +13 -13
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +8 -7
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +2 -2
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +1 -1
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +1381 -4
- package/lib/vendor/blamejs/eslint.config.mjs +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +4 -1
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +5 -2
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +4 -1
- package/lib/vendor/blamejs/fuzz/guard-text.fuzz.js +20 -0
- package/lib/vendor/blamejs/index.js +2 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +7 -23
- package/lib/vendor/blamejs/lib/acme.js +6 -5
- package/lib/vendor/blamejs/lib/agent-event-bus.js +5 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +2 -5
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +2 -5
- package/lib/vendor/blamejs/lib/agent-saga.js +3 -5
- package/lib/vendor/blamejs/lib/agent-tenant.js +2 -5
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +2 -15
- package/lib/vendor/blamejs/lib/ai-capability.js +1 -6
- package/lib/vendor/blamejs/lib/ai-dp.js +1 -5
- package/lib/vendor/blamejs/lib/ai-input.js +2 -2
- package/lib/vendor/blamejs/lib/ai-pref.js +3 -8
- package/lib/vendor/blamejs/lib/ai-quota.js +3 -14
- package/lib/vendor/blamejs/lib/api-key.js +37 -28
- package/lib/vendor/blamejs/lib/archive-adapters.js +2 -4
- package/lib/vendor/blamejs/lib/archive-entry-policy.js +32 -0
- package/lib/vendor/blamejs/lib/archive-read.js +5 -17
- package/lib/vendor/blamejs/lib/archive-tar-read.js +5 -16
- package/lib/vendor/blamejs/lib/archive.js +2 -10
- package/lib/vendor/blamejs/lib/arg-parser.js +7 -6
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +2 -6
- package/lib/vendor/blamejs/lib/atomic-file.js +108 -31
- package/lib/vendor/blamejs/lib/audit-chain.js +133 -53
- package/lib/vendor/blamejs/lib/audit-daily-review.js +24 -14
- package/lib/vendor/blamejs/lib/audit-emit.js +82 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +257 -0
- package/lib/vendor/blamejs/lib/audit.js +84 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +5 -27
- package/lib/vendor/blamejs/lib/auth/dpop.js +23 -35
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +9 -15
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +26 -8
- package/lib/vendor/blamejs/lib/auth/jwt.js +13 -15
- package/lib/vendor/blamejs/lib/auth/lockout.js +6 -25
- package/lib/vendor/blamejs/lib/auth/oauth.js +67 -45
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +55 -32
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +3 -2
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +6 -6
- package/lib/vendor/blamejs/lib/auth/passkey.js +3 -3
- package/lib/vendor/blamejs/lib/auth/password.js +7 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +37 -27
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +1 -1
- package/lib/vendor/blamejs/lib/auth/status-list.js +7 -7
- package/lib/vendor/blamejs/lib/auth/step-up.js +6 -12
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +6 -37
- package/lib/vendor/blamejs/lib/backup/bundle.js +11 -18
- package/lib/vendor/blamejs/lib/backup/index.js +14 -47
- package/lib/vendor/blamejs/lib/bounded-map.js +112 -1
- package/lib/vendor/blamejs/lib/breach-deadline.js +1 -11
- package/lib/vendor/blamejs/lib/cache.js +7 -18
- package/lib/vendor/blamejs/lib/cbor.js +2 -1
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +8 -9
- package/lib/vendor/blamejs/lib/cert.js +3 -10
- package/lib/vendor/blamejs/lib/chain-writer.js +162 -47
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/client-hints.js +7 -9
- package/lib/vendor/blamejs/lib/cloud-events.js +40 -31
- package/lib/vendor/blamejs/lib/cluster-storage.js +2 -38
- package/lib/vendor/blamejs/lib/cms-codec.js +2 -1
- package/lib/vendor/blamejs/lib/codepoint-class.js +67 -1
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +1 -6
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -11
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +2 -14
- package/lib/vendor/blamejs/lib/compliance.js +2 -9
- package/lib/vendor/blamejs/lib/config-drift.js +2 -12
- package/lib/vendor/blamejs/lib/content-digest.js +10 -8
- package/lib/vendor/blamejs/lib/cookies.js +5 -11
- package/lib/vendor/blamejs/lib/cose.js +19 -11
- package/lib/vendor/blamejs/lib/cra-report.js +1 -11
- package/lib/vendor/blamejs/lib/crypto-field.js +5 -10
- package/lib/vendor/blamejs/lib/crypto.js +120 -3
- package/lib/vendor/blamejs/lib/csp.js +235 -3
- package/lib/vendor/blamejs/lib/daemon.js +42 -41
- package/lib/vendor/blamejs/lib/data-act.js +19 -9
- package/lib/vendor/blamejs/lib/db-query.js +6 -40
- package/lib/vendor/blamejs/lib/db.js +34 -12
- package/lib/vendor/blamejs/lib/dbsc.js +5 -6
- package/lib/vendor/blamejs/lib/ddl-change-control.js +18 -14
- package/lib/vendor/blamejs/lib/deprecate.js +4 -5
- package/lib/vendor/blamejs/lib/did.js +6 -2
- package/lib/vendor/blamejs/lib/dsr.js +8 -12
- package/lib/vendor/blamejs/lib/external-db-migrate.js +21 -22
- package/lib/vendor/blamejs/lib/external-db.js +14 -26
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +12 -8
- package/lib/vendor/blamejs/lib/fdx.js +22 -18
- package/lib/vendor/blamejs/lib/file-upload.js +80 -66
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +5 -8
- package/lib/vendor/blamejs/lib/framework-error.js +12 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +19 -0
- package/lib/vendor/blamejs/lib/fsm.js +7 -12
- package/lib/vendor/blamejs/lib/gate-contract.js +869 -38
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +4 -13
- package/lib/vendor/blamejs/lib/graphql-federation.js +1 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +2 -1
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +9 -30
- package/lib/vendor/blamejs/lib/guard-auth.js +23 -80
- package/lib/vendor/blamejs/lib/guard-cidr.js +20 -96
- package/lib/vendor/blamejs/lib/guard-csv.js +135 -196
- package/lib/vendor/blamejs/lib/guard-domain.js +23 -106
- package/lib/vendor/blamejs/lib/guard-dsn.js +16 -13
- package/lib/vendor/blamejs/lib/guard-email.js +46 -53
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +2 -1
- package/lib/vendor/blamejs/lib/guard-filename.js +12 -60
- package/lib/vendor/blamejs/lib/guard-graphql.js +28 -75
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +15 -2
- package/lib/vendor/blamejs/lib/guard-html.js +65 -117
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +2 -1
- package/lib/vendor/blamejs/lib/guard-image.js +280 -77
- package/lib/vendor/blamejs/lib/guard-imap-command.js +8 -9
- package/lib/vendor/blamejs/lib/guard-json.js +87 -103
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +20 -88
- package/lib/vendor/blamejs/lib/guard-jwt.js +32 -114
- package/lib/vendor/blamejs/lib/guard-list-id.js +2 -7
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -7
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +2 -1
- package/lib/vendor/blamejs/lib/guard-mail-query.js +5 -3
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +6 -7
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +5 -4
- package/lib/vendor/blamejs/lib/guard-markdown.js +76 -110
- package/lib/vendor/blamejs/lib/guard-message-id.js +5 -6
- package/lib/vendor/blamejs/lib/guard-mime.js +20 -99
- package/lib/vendor/blamejs/lib/guard-oauth.js +19 -73
- package/lib/vendor/blamejs/lib/guard-pdf.js +65 -72
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +12 -13
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +2 -1
- package/lib/vendor/blamejs/lib/guard-regex.js +24 -99
- package/lib/vendor/blamejs/lib/guard-saga-config.js +2 -1
- package/lib/vendor/blamejs/lib/guard-shell.js +22 -87
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +8 -11
- package/lib/vendor/blamejs/lib/guard-sql.js +15 -13
- package/lib/vendor/blamejs/lib/guard-stream-args.js +2 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +95 -140
- package/lib/vendor/blamejs/lib/guard-template.js +23 -80
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +2 -1
- package/lib/vendor/blamejs/lib/guard-text.js +592 -0
- package/lib/vendor/blamejs/lib/guard-time.js +27 -95
- package/lib/vendor/blamejs/lib/guard-uuid.js +21 -93
- package/lib/vendor/blamejs/lib/guard-xml.js +76 -106
- package/lib/vendor/blamejs/lib/guard-yaml.js +24 -60
- package/lib/vendor/blamejs/lib/http-client-cache.js +5 -12
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +2 -4
- package/lib/vendor/blamejs/lib/http-client.js +8 -21
- package/lib/vendor/blamejs/lib/http-message-signature.js +3 -2
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +5 -7
- package/lib/vendor/blamejs/lib/i18n.js +83 -26
- package/lib/vendor/blamejs/lib/inbox.js +8 -8
- package/lib/vendor/blamejs/lib/incident-report.js +3 -21
- package/lib/vendor/blamejs/lib/ip-utils.js +49 -6
- package/lib/vendor/blamejs/lib/jobs.js +3 -2
- package/lib/vendor/blamejs/lib/keychain.js +6 -18
- package/lib/vendor/blamejs/lib/legal-hold.js +6 -15
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +44 -112
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +16 -80
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +20 -92
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +8 -3
- package/lib/vendor/blamejs/lib/mail-arf.js +3 -2
- package/lib/vendor/blamejs/lib/mail-auth.js +40 -66
- package/lib/vendor/blamejs/lib/mail-bimi.js +19 -39
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
- package/lib/vendor/blamejs/lib/mail-dav.js +8 -35
- package/lib/vendor/blamejs/lib/mail-deploy.js +6 -9
- package/lib/vendor/blamejs/lib/mail-dkim.js +19 -38
- package/lib/vendor/blamejs/lib/mail-greylist.js +15 -26
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -3
- package/lib/vendor/blamejs/lib/mail-journal.js +2 -1
- package/lib/vendor/blamejs/lib/mail-mdn.js +4 -3
- package/lib/vendor/blamejs/lib/mail-rbl.js +5 -8
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -2
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +33 -20
- package/lib/vendor/blamejs/lib/mail-server-imap.js +32 -87
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +35 -51
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +29 -83
- package/lib/vendor/blamejs/lib/mail-server-mx.js +33 -74
- package/lib/vendor/blamejs/lib/mail-server-net.js +177 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +30 -83
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +30 -6
- package/lib/vendor/blamejs/lib/mail-server-submission.js +34 -73
- package/lib/vendor/blamejs/lib/mail-server-tls.js +89 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +7 -8
- package/lib/vendor/blamejs/lib/mail-store.js +3 -2
- package/lib/vendor/blamejs/lib/mail.js +6 -11
- package/lib/vendor/blamejs/lib/markup-escape.js +31 -0
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +54 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +26 -23
- package/lib/vendor/blamejs/lib/mcp.js +1 -1
- package/lib/vendor/blamejs/lib/mdoc.js +11 -12
- package/lib/vendor/blamejs/lib/metrics.js +32 -30
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -23
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +11 -22
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -7
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +31 -48
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +7 -10
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +2 -10
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +13 -2
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -26
- package/lib/vendor/blamejs/lib/middleware/deny-response.js +19 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +7 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +4 -20
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +20 -28
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +3 -2
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +9 -1
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -6
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +12 -27
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -7
- package/lib/vendor/blamejs/lib/migrations.js +4 -13
- package/lib/vendor/blamejs/lib/mime-parse.js +34 -17
- package/lib/vendor/blamejs/lib/module-loader.js +44 -0
- package/lib/vendor/blamejs/lib/money.js +105 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +116 -36
- package/lib/vendor/blamejs/lib/network-byte-quota.js +4 -18
- package/lib/vendor/blamejs/lib/network-dane.js +8 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +97 -6
- package/lib/vendor/blamejs/lib/network-dnssec.js +16 -16
- package/lib/vendor/blamejs/lib/network-heartbeat.js +3 -2
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +29 -41
- package/lib/vendor/blamejs/lib/network-tls.js +40 -42
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -11
- package/lib/vendor/blamejs/lib/nonce-store.js +81 -3
- package/lib/vendor/blamejs/lib/numeric-bounds.js +22 -8
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +5 -45
- package/lib/vendor/blamejs/lib/object-store/gcs.js +8 -71
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -5
- package/lib/vendor/blamejs/lib/object-store/http-request.js +128 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +9 -77
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -25
- package/lib/vendor/blamejs/lib/observability.js +95 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +7 -3
- package/lib/vendor/blamejs/lib/otel-export.js +7 -10
- package/lib/vendor/blamejs/lib/outbox.js +43 -37
- package/lib/vendor/blamejs/lib/pagination.js +11 -15
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +5 -4
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +10 -4
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +11 -9
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +2 -2
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +7 -6
- package/lib/vendor/blamejs/lib/pick.js +63 -5
- package/lib/vendor/blamejs/lib/pipl-cn.js +69 -59
- package/lib/vendor/blamejs/lib/privacy-pass.js +8 -6
- package/lib/vendor/blamejs/lib/problem-details.js +2 -5
- package/lib/vendor/blamejs/lib/pubsub.js +4 -8
- package/lib/vendor/blamejs/lib/redact.js +2 -1
- package/lib/vendor/blamejs/lib/render.js +4 -2
- package/lib/vendor/blamejs/lib/request-helpers.js +133 -6
- package/lib/vendor/blamejs/lib/restore.js +5 -22
- package/lib/vendor/blamejs/lib/retention.js +3 -5
- package/lib/vendor/blamejs/lib/safe-async.js +457 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +137 -6
- package/lib/vendor/blamejs/lib/safe-decompress.js +2 -1
- package/lib/vendor/blamejs/lib/safe-dns.js +2 -1
- package/lib/vendor/blamejs/lib/safe-ical.js +12 -26
- package/lib/vendor/blamejs/lib/safe-json.js +7 -8
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +6 -5
- package/lib/vendor/blamejs/lib/safe-mime.js +25 -29
- package/lib/vendor/blamejs/lib/safe-redirect.js +2 -5
- package/lib/vendor/blamejs/lib/safe-schema.js +7 -6
- package/lib/vendor/blamejs/lib/safe-sql.js +126 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +12 -26
- package/lib/vendor/blamejs/lib/sandbox-worker.js +9 -2
- package/lib/vendor/blamejs/lib/sandbox.js +3 -2
- package/lib/vendor/blamejs/lib/scheduler.js +5 -12
- package/lib/vendor/blamejs/lib/sec-cyber.js +82 -37
- package/lib/vendor/blamejs/lib/seeders.js +4 -11
- package/lib/vendor/blamejs/lib/self-update.js +92 -69
- package/lib/vendor/blamejs/lib/session-device-binding.js +112 -66
- package/lib/vendor/blamejs/lib/session.js +194 -6
- package/lib/vendor/blamejs/lib/sql.js +225 -78
- package/lib/vendor/blamejs/lib/sse.js +6 -10
- package/lib/vendor/blamejs/lib/static.js +136 -98
- package/lib/vendor/blamejs/lib/storage.js +4 -2
- package/lib/vendor/blamejs/lib/structured-fields.js +275 -16
- package/lib/vendor/blamejs/lib/tenant-quota.js +2 -20
- package/lib/vendor/blamejs/lib/tsa.js +11 -15
- package/lib/vendor/blamejs/lib/validate-opts.js +154 -8
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +30 -48
- package/lib/vendor/blamejs/lib/vault-aad.js +3 -2
- package/lib/vendor/blamejs/lib/vc.js +2 -7
- package/lib/vendor/blamejs/lib/vex.js +35 -13
- package/lib/vendor/blamejs/lib/web-push-vapid.js +23 -20
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +706 -0
- package/lib/vendor/blamejs/lib/webhook.js +43 -18
- package/lib/vendor/blamejs/lib/websocket-channels.js +9 -7
- package/lib/vendor/blamejs/lib/websocket.js +7 -3
- package/lib/vendor/blamejs/lib/worm.js +2 -3
- package/lib/vendor/blamejs/lib/ws-client.js +8 -10
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.13.json +81 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +1 -1
- package/lib/vendor/blamejs/test/00-primitives.js +136 -7
- package/lib/vendor/blamejs/test/10-state.js +9 -3
- package/lib/vendor/blamejs/test/30-chain.js +40 -0
- package/lib/vendor/blamejs/test/helpers/check.js +18 -0
- package/lib/vendor/blamejs/test/helpers/db.js +4 -0
- package/lib/vendor/blamejs/test/helpers/index.js +1 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +8 -1
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +1 -1
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +2 -1
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +55 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-object-store-adapter.test.js +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/bounded-map.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/chain-writer-multichain.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +2788 -3214
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-resolve-opts.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +9 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract-content-gate.test.js +290 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-gate-disposition-coverage.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-text.test.js +365 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mime-parse.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-revocation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-release.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-memory-getorinsert.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +2 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/session-valid-from.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/validate-opts-shape.test.js +235 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +374 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +75 -8
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* guard-text — general-purpose UTF-8 free-text content-safety primitive
|
|
4
|
+
* (b.guardText).
|
|
5
|
+
*
|
|
6
|
+
* Covers: required guard-family surface (NAME / KIND / MIME_TYPES /
|
|
7
|
+
* EXTENSIONS / PROFILES / COMPLIANCE_POSTURES / validate / sanitize / gate /
|
|
8
|
+
* buildProfile / compliancePosture / loadRulePack / INTEGRATION_FIXTURES +
|
|
9
|
+
* GuardTextError); the codepoint threat catalog (bidi override / C0 control /
|
|
10
|
+
* null byte / zero-width / Unicode Tags / mixed-script confusable);
|
|
11
|
+
* byte-accurate maxBytes on multibyte input; multibyte legitimate-script
|
|
12
|
+
* preservation; sanitize strip + amplification cap; non-repairable confusable;
|
|
13
|
+
* the gate serve→audit-only→sanitize→refuse decision chain; operator rules;
|
|
14
|
+
* profile + posture composition; registration in b.guardAll.allGuards().
|
|
15
|
+
*
|
|
16
|
+
* Hostile codepoints are constructed via String.fromCharCode so this test
|
|
17
|
+
* source stays pure ASCII (the guard-family source-purity invariant).
|
|
18
|
+
*
|
|
19
|
+
* Run standalone: node test/layer-0-primitives/guard-text.test.js
|
|
20
|
+
* Or via smoke: node test/smoke.js
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
var helpers = require("../helpers");
|
|
24
|
+
var b = helpers.b;
|
|
25
|
+
var check = helpers.check;
|
|
26
|
+
|
|
27
|
+
// Hostile codepoints, built numerically.
|
|
28
|
+
var RLO = String.fromCharCode(0x202E); // RIGHT-TO-LEFT OVERRIDE (bidi)
|
|
29
|
+
var LRO = String.fromCharCode(0x202D); // LEFT-TO-RIGHT OVERRIDE (bidi)
|
|
30
|
+
var NUL = String.fromCharCode(0x00); // null byte
|
|
31
|
+
var BELL = String.fromCharCode(0x07); // C0 control
|
|
32
|
+
var ZWSP = String.fromCharCode(0x200B); // ZERO WIDTH SPACE
|
|
33
|
+
var ZWNJ = String.fromCharCode(0x200C); // ZERO WIDTH NON-JOINER
|
|
34
|
+
var TAGA = String.fromCodePoint(0xE0041); // Unicode Tags block "A" (ASCII smuggling; astral — needs fromCodePoint)
|
|
35
|
+
var CYR_A = String.fromCharCode(0x0430); // Cyrillic small a (confusable with Latin a)
|
|
36
|
+
|
|
37
|
+
// ---- surface ----
|
|
38
|
+
|
|
39
|
+
function testSurface() {
|
|
40
|
+
check("guardText is an object", typeof b.guardText === "object");
|
|
41
|
+
check("guardText.NAME === text", b.guardText.NAME === "text");
|
|
42
|
+
check("guardText.KIND === content", b.guardText.KIND === "content");
|
|
43
|
+
check("guardText.MIME_TYPES includes text/plain",
|
|
44
|
+
b.guardText.MIME_TYPES.indexOf("text/plain") !== -1);
|
|
45
|
+
check("guardText.EXTENSIONS includes .txt",
|
|
46
|
+
b.guardText.EXTENSIONS.indexOf(".txt") !== -1);
|
|
47
|
+
check("guardText.validate is a function", typeof b.guardText.validate === "function");
|
|
48
|
+
check("guardText.sanitize is a function", typeof b.guardText.sanitize === "function");
|
|
49
|
+
check("guardText.gate is a function", typeof b.guardText.gate === "function");
|
|
50
|
+
check("guardText.buildProfile is a function", typeof b.guardText.buildProfile === "function");
|
|
51
|
+
check("guardText.compliancePosture is a function",
|
|
52
|
+
typeof b.guardText.compliancePosture === "function");
|
|
53
|
+
check("guardText.loadRulePack is a function", typeof b.guardText.loadRulePack === "function");
|
|
54
|
+
check("guardText.INTEGRATION_FIXTURES is an object",
|
|
55
|
+
typeof b.guardText.INTEGRATION_FIXTURES === "object");
|
|
56
|
+
check("guardText.GuardTextError is a function",
|
|
57
|
+
typeof b.guardText.GuardTextError === "function");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function testProfilesAndPostures() {
|
|
61
|
+
var p = Object.keys(b.guardText.PROFILES);
|
|
62
|
+
check("PROFILES has strict/balanced/permissive",
|
|
63
|
+
p.indexOf("strict") !== -1 && p.indexOf("balanced") !== -1 && p.indexOf("permissive") !== -1);
|
|
64
|
+
var c = Object.keys(b.guardText.COMPLIANCE_POSTURES);
|
|
65
|
+
check("POSTURES has hipaa/pci-dss/gdpr/soc2",
|
|
66
|
+
c.indexOf("hipaa") !== -1 && c.indexOf("pci-dss") !== -1 &&
|
|
67
|
+
c.indexOf("gdpr") !== -1 && c.indexOf("soc2") !== -1);
|
|
68
|
+
// buildProfile composes overlays without mutating the frozen preset.
|
|
69
|
+
var prof = b.guardText.buildProfile({ baseProfile: "strict", overrides: { maxBytes: 1024 } });
|
|
70
|
+
check("buildProfile overlays maxBytes", prof.maxBytes === 1024);
|
|
71
|
+
check("buildProfile keeps strict bidi reject", prof.bidiPolicy === "reject");
|
|
72
|
+
// compliancePosture resolves a known posture.
|
|
73
|
+
var hipaa = b.guardText.compliancePosture("hipaa");
|
|
74
|
+
check("compliancePosture hipaa bidi reject", hipaa.bidiPolicy === "reject");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function testRegisteredInGuardAll() {
|
|
78
|
+
var names = b.guardAll.allGuards().map(function (g) { return g.NAME; });
|
|
79
|
+
check("text registered in b.guardAll.allGuards()", names.indexOf("text") !== -1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function testGdprPostureMatchesBalancedTier() {
|
|
83
|
+
// text is a content guard: gdpr maps to the balanced tier, whose maxBytes
|
|
84
|
+
// is 4 MiB. A hand-rolled partial posture omitting maxBytes silently
|
|
85
|
+
// backfills the strict 1 MiB cap from DEFAULTS — an incoherent hybrid. The
|
|
86
|
+
// routed posture inherits the full balanced tier, so maxBytes is 4194304.
|
|
87
|
+
var gdpr = b.guardText.COMPLIANCE_POSTURES.gdpr;
|
|
88
|
+
check("gdpr posture maxBytes is balanced-tier 4 MiB", gdpr.maxBytes === 4194304);
|
|
89
|
+
// Consumer-path proof: a 2 MiB input (between the strict 1 MiB and balanced
|
|
90
|
+
// 4 MiB caps) validates OK under the gdpr posture. Under the strict-backfill
|
|
91
|
+
// hybrid it was rejected as too-large.
|
|
92
|
+
var twoMiB = "a".repeat(2 * 1024 * 1024);
|
|
93
|
+
var rv = b.guardText.validate(twoMiB, { compliancePosture: "gdpr" });
|
|
94
|
+
check("2 MiB text validates OK under gdpr posture", rv.ok === true);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ---- validate: each threat class ----
|
|
98
|
+
|
|
99
|
+
function testValidateBenign() {
|
|
100
|
+
var rv = b.guardText.validate("a perfectly ordinary review", { profile: "strict" });
|
|
101
|
+
check("benign text ok", rv.ok === true);
|
|
102
|
+
check("benign text has no issues", rv.issues.length === 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function testValidateBidi() {
|
|
106
|
+
var rv = b.guardText.validate("review " + RLO + "txt.exe", { profile: "strict" });
|
|
107
|
+
check("bidi override not ok", rv.ok === false);
|
|
108
|
+
check("bidi override kind",
|
|
109
|
+
rv.issues.some(function (i) { return i.kind === "bidi-override"; }));
|
|
110
|
+
// LRO is also a bidi override.
|
|
111
|
+
var rv2 = b.guardText.validate("a" + LRO + "b", { profile: "strict" });
|
|
112
|
+
check("LRO bidi override not ok", rv2.ok === false);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function testValidateControl() {
|
|
116
|
+
var rv = b.guardText.validate("log line" + BELL + "injection", { profile: "strict" });
|
|
117
|
+
check("control char not ok", rv.ok === false);
|
|
118
|
+
check("control char kind",
|
|
119
|
+
rv.issues.some(function (i) { return i.kind === "control-char"; }));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function testValidateNullByte() {
|
|
123
|
+
var rv = b.guardText.validate("name" + NUL + "truncate", { profile: "strict" });
|
|
124
|
+
check("null byte not ok", rv.ok === false);
|
|
125
|
+
check("null byte kind",
|
|
126
|
+
rv.issues.some(function (i) { return i.kind === "null-byte"; }));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function testValidateZeroWidth() {
|
|
130
|
+
var rv = b.guardText.validate("hid" + ZWSP + "den", { profile: "strict" });
|
|
131
|
+
check("zero-width not ok", rv.ok === false);
|
|
132
|
+
check("zero-width kind",
|
|
133
|
+
rv.issues.some(function (i) { return i.kind === "zero-width"; }));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function testValidateUnicodeTags() {
|
|
137
|
+
// ASCII-smuggling: an invisible Tags-block instruction (prompt injection).
|
|
138
|
+
var rv = b.guardText.validate("hello" + TAGA + "world", { profile: "strict" });
|
|
139
|
+
check("unicode-tags not ok", rv.ok === false);
|
|
140
|
+
check("unicode-tags kind critical",
|
|
141
|
+
rv.issues.some(function (i) {
|
|
142
|
+
return i.kind === "unicode-tags" && i.severity === "critical";
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function testValidateConfusableStrictRefuses() {
|
|
147
|
+
// A Latin word with one Cyrillic letter swapped in (UTS #39 confusable).
|
|
148
|
+
var rv = b.guardText.validate("p" + CYR_A + "ypal", { profile: "strict" });
|
|
149
|
+
check("mixed-script confusable not ok under strict", rv.ok === false);
|
|
150
|
+
check("confusable kind",
|
|
151
|
+
rv.issues.some(function (i) { return i.kind === "mixed-script-confusable"; }));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function testValidateConfusableAuditOnlyUnderPermissive() {
|
|
155
|
+
// permissive: confusablePolicy "allow" -> not even reported.
|
|
156
|
+
var rv = b.guardText.validate("p" + CYR_A + "ypal", { profile: "permissive" });
|
|
157
|
+
check("confusable suppressed under permissive (allow)", rv.ok === true);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function testValidateMaxBytesByteAccurate() {
|
|
161
|
+
// "€" is 3 UTF-8 bytes; 2 of them = 6 bytes > 5. text.length would be 2.
|
|
162
|
+
var rv = b.guardText.validate("€€", { profile: "strict", maxBytes: 5 });
|
|
163
|
+
check("maxBytes measured in bytes not chars", rv.ok === false);
|
|
164
|
+
check("too-large kind",
|
|
165
|
+
rv.issues.some(function (i) { return i.kind === "too-large"; }));
|
|
166
|
+
// 1 euro = 3 bytes <= 5 passes.
|
|
167
|
+
var rv2 = b.guardText.validate("€", { profile: "strict", maxBytes: 5 });
|
|
168
|
+
check("single euro within byte budget ok", rv2.ok === true);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function testValidateMaxBytesInfinityThrows() {
|
|
172
|
+
var threw = false;
|
|
173
|
+
try { b.guardText.validate("x", { profile: "strict", maxBytes: Infinity }); }
|
|
174
|
+
catch (e) { threw = e && e.code === "text.bad-opt"; }
|
|
175
|
+
check("maxBytes Infinity throws config-time", threw === true);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function testValidateMultibyteScriptsPreservedAsBenign() {
|
|
179
|
+
// Legitimate single-script multilingual text is NOT an issue — the guard
|
|
180
|
+
// imposes no grammar. Each is its own script (no mixing).
|
|
181
|
+
check("Han text benign", b.guardText.validate("你好世界", { profile: "strict" }).ok === true);
|
|
182
|
+
check("Arabic text benign", b.guardText.validate("مرحبا", { profile: "strict" }).ok === true);
|
|
183
|
+
check("emoji benign", b.guardText.validate("great product 👍", { profile: "strict" }).ok === true);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function testValidateBufferInput() {
|
|
187
|
+
var rv = b.guardText.validate(Buffer.from("plain bytes", "utf8"), { profile: "strict" });
|
|
188
|
+
check("Buffer input validates", rv.ok === true);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ---- encoding validity (byte → codepoint layer) ----
|
|
192
|
+
|
|
193
|
+
function testValidateInvalidEncoding() {
|
|
194
|
+
// Overlong encoding of "/" (0x2F) as C0 AF — the classic UTF-8 filter bypass;
|
|
195
|
+
// a lossy toString would launder it into U+FFFD.
|
|
196
|
+
var overlong = Buffer.from([0x2F, 0xC0, 0xAF, 0x2F]);
|
|
197
|
+
var rv = b.guardText.validate(overlong, { profile: "strict" });
|
|
198
|
+
check("overlong UTF-8 flagged invalid-encoding", rv.ok === false &&
|
|
199
|
+
rv.issues.some(function (i) { return i.kind === "invalid-encoding"; }));
|
|
200
|
+
// Truncated multibyte (lead byte, no continuation).
|
|
201
|
+
var trunc = b.guardText.validate(Buffer.from([0x41, 0xE2, 0x82]), { profile: "strict" });
|
|
202
|
+
check("truncated UTF-8 flagged", trunc.ok === false);
|
|
203
|
+
// Well-formed multibyte passes the encoding check.
|
|
204
|
+
check("valid UTF-8 (euro) passes encoding",
|
|
205
|
+
b.guardText.validate(Buffer.from("€10", "utf8"), { profile: "strict" }).ok === true);
|
|
206
|
+
// permissive audits (does not reject) malformed encoding.
|
|
207
|
+
var perm = b.guardText.validate(Buffer.from([0xC0, 0xAF]), { profile: "permissive" });
|
|
208
|
+
check("permissive encoding policy is audit (warn, ok stays by that axis)",
|
|
209
|
+
perm.issues.some(function (i) { return i.kind === "invalid-encoding" && i.severity === "warn"; }));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ---- keyspace bounds ----
|
|
213
|
+
|
|
214
|
+
function testValidateAsciiOnly() {
|
|
215
|
+
var rv = b.guardText.validate("café", { profile: "strict", asciiOnly: true });
|
|
216
|
+
check("asciiOnly flags non-ASCII", rv.ok === false &&
|
|
217
|
+
rv.issues.some(function (i) { return i.kind === "non-ascii"; }));
|
|
218
|
+
check("asciiOnly allows pure ASCII",
|
|
219
|
+
b.guardText.validate("plain ascii", { profile: "strict", asciiOnly: true }).ok === true);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function testValidateMaxCodepoint() {
|
|
223
|
+
var astral = "hi " + String.fromCodePoint(0x1F600);
|
|
224
|
+
var rv = b.guardText.validate(astral, { profile: "strict", maxCodepoint: 0xFFFF });
|
|
225
|
+
check("maxCodepoint flags astral codepoint", rv.ok === false &&
|
|
226
|
+
rv.issues.some(function (i) { return i.kind === "codepoint-out-of-range"; }));
|
|
227
|
+
check("maxCodepoint allows within ceiling",
|
|
228
|
+
b.guardText.validate("你好", { profile: "strict", maxCodepoint: 0xFFFF }).ok === true);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function testGateRefuseInvalidEncoding() {
|
|
232
|
+
var overlong = Buffer.from([0x2F, 0xC0, 0xAF]);
|
|
233
|
+
var v = await b.guardText.gate({ profile: "strict" }).check({ bytes: overlong });
|
|
234
|
+
check("gate refuses malformed UTF-8", v.action === "refuse");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ---- sanitize ----
|
|
238
|
+
|
|
239
|
+
function testSanitizeStripsInvisibles() {
|
|
240
|
+
var clean = b.guardText.sanitize("nice" + ZWSP + "re" + ZWNJ + "view", { profile: "balanced" });
|
|
241
|
+
check("sanitize strips zero-width", clean.indexOf(ZWSP) === -1 && clean.indexOf(ZWNJ) === -1);
|
|
242
|
+
check("sanitize result text intact", clean === "nicereview");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function testSanitizeStripsBidiControlNullTags() {
|
|
246
|
+
var dirty = "a" + RLO + "b" + BELL + "c" + NUL + "d" + TAGA + "e";
|
|
247
|
+
var clean = b.guardText.sanitize(dirty, { profile: "balanced" });
|
|
248
|
+
check("sanitize strips bidi", clean.indexOf(RLO) === -1);
|
|
249
|
+
check("sanitize strips control", clean.indexOf(BELL) === -1);
|
|
250
|
+
check("sanitize strips null", clean.indexOf(NUL) === -1);
|
|
251
|
+
check("sanitize strips tags", clean.indexOf(TAGA) === -1);
|
|
252
|
+
check("sanitize preserves letters", clean === "abcde");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function testSanitizePreservesMultibyte() {
|
|
256
|
+
var clean = b.guardText.sanitize("你好" + ZWSP + "世界", { profile: "balanced" });
|
|
257
|
+
check("sanitize preserves Han, strips zwsp", clean === "你好世界");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function testSanitizeAmplificationContract() {
|
|
261
|
+
// Sanitize is shrinking by contract: stripping can only remove, never grow.
|
|
262
|
+
var clean = b.guardText.sanitize("hello world", { profile: "balanced" });
|
|
263
|
+
check("sanitize never grows output", clean.length <= "hello world".length);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ---- gate decision chain ----
|
|
267
|
+
|
|
268
|
+
async function testGateServe() {
|
|
269
|
+
var v = await b.guardText.gate({ profile: "strict" })
|
|
270
|
+
.check({ bytes: Buffer.from("ordinary text", "utf8") });
|
|
271
|
+
check("gate serve on benign", v.action === "serve");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function testGateRefuseBidiStrict() {
|
|
275
|
+
var v = await b.guardText.gate({ profile: "strict" })
|
|
276
|
+
.check({ bytes: Buffer.from("ok " + RLO + "danger", "utf8") });
|
|
277
|
+
check("gate refuse on bidi under strict", v.action === "refuse" && v.ok === false);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function testGateSanitizeBalanced() {
|
|
281
|
+
// balanced strips invisibles -> sanitize action with cleaned bytes.
|
|
282
|
+
var v = await b.guardText.gate({ profile: "balanced" })
|
|
283
|
+
.check({ bytes: Buffer.from("nice" + ZWSP + "review", "utf8") });
|
|
284
|
+
check("gate sanitize under balanced", v.action === "sanitize");
|
|
285
|
+
check("gate sanitize returns cleaned bytes",
|
|
286
|
+
Buffer.isBuffer(v.sanitized) && v.sanitized.toString("utf8") === "nicereview");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function testGateAuditOnlyConfusable() {
|
|
290
|
+
// balanced confusablePolicy "audit" -> warn-only -> audit-only, not refuse.
|
|
291
|
+
var v = await b.guardText.gate({ profile: "balanced" })
|
|
292
|
+
.check({ bytes: Buffer.from("p" + CYR_A + "ypal", "utf8") });
|
|
293
|
+
check("gate audit-only on balanced confusable", v.action === "audit-only");
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async function testGateRefuseConfusableStrict() {
|
|
297
|
+
// strict confusablePolicy "reject" -> high severity, non-repairable -> refuse.
|
|
298
|
+
var v = await b.guardText.gate({ profile: "strict" })
|
|
299
|
+
.check({ bytes: Buffer.from("p" + CYR_A + "ypal", "utf8") });
|
|
300
|
+
check("gate refuse on strict confusable", v.action === "refuse");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function testGateOperatorRule() {
|
|
304
|
+
var gate = b.guardText.gate({
|
|
305
|
+
profile: "permissive",
|
|
306
|
+
operatorRules: [{
|
|
307
|
+
id: "no-profanity", severity: "high",
|
|
308
|
+
detect: function (c) { return /badword/.test(c.bytes); },
|
|
309
|
+
reason: "operator profanity filter",
|
|
310
|
+
}],
|
|
311
|
+
});
|
|
312
|
+
var v = await gate.check({ bytes: Buffer.from("this has badword in it", "utf8") });
|
|
313
|
+
check("operator rule fires -> refuse", v.action === "refuse");
|
|
314
|
+
check("operator rule issue surfaced",
|
|
315
|
+
v.issues.some(function (i) { return i.kind === "no-profanity"; }));
|
|
316
|
+
// A throwing operator rule is skipped, never crashes the gate.
|
|
317
|
+
var gate2 = b.guardText.gate({
|
|
318
|
+
profile: "permissive",
|
|
319
|
+
operatorRules: [{ id: "boom", detect: function () { throw new Error("rule bug"); } }],
|
|
320
|
+
});
|
|
321
|
+
var v2 = await gate2.check({ bytes: Buffer.from("clean text", "utf8") });
|
|
322
|
+
check("throwing operator rule does not crash gate", v2.action === "serve");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async function run() {
|
|
326
|
+
testSurface();
|
|
327
|
+
testProfilesAndPostures();
|
|
328
|
+
testRegisteredInGuardAll();
|
|
329
|
+
testGdprPostureMatchesBalancedTier();
|
|
330
|
+
testValidateBenign();
|
|
331
|
+
testValidateBidi();
|
|
332
|
+
testValidateControl();
|
|
333
|
+
testValidateNullByte();
|
|
334
|
+
testValidateZeroWidth();
|
|
335
|
+
testValidateUnicodeTags();
|
|
336
|
+
testValidateConfusableStrictRefuses();
|
|
337
|
+
testValidateConfusableAuditOnlyUnderPermissive();
|
|
338
|
+
testValidateMaxBytesByteAccurate();
|
|
339
|
+
testValidateMaxBytesInfinityThrows();
|
|
340
|
+
testValidateMultibyteScriptsPreservedAsBenign();
|
|
341
|
+
testValidateBufferInput();
|
|
342
|
+
testValidateInvalidEncoding();
|
|
343
|
+
testValidateAsciiOnly();
|
|
344
|
+
testValidateMaxCodepoint();
|
|
345
|
+
await testGateRefuseInvalidEncoding();
|
|
346
|
+
testSanitizeStripsInvisibles();
|
|
347
|
+
testSanitizeStripsBidiControlNullTags();
|
|
348
|
+
testSanitizePreservesMultibyte();
|
|
349
|
+
testSanitizeAmplificationContract();
|
|
350
|
+
await testGateServe();
|
|
351
|
+
await testGateRefuseBidiStrict();
|
|
352
|
+
await testGateSanitizeBalanced();
|
|
353
|
+
await testGateAuditOnlyConfusable();
|
|
354
|
+
await testGateRefuseConfusableStrict();
|
|
355
|
+
await testGateOperatorRule();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
module.exports = { run: run };
|
|
359
|
+
|
|
360
|
+
if (require.main === module) {
|
|
361
|
+
run().then(
|
|
362
|
+
function () { console.log("[guard-text] OK — " + helpers.getChecks() + " checks passed"); process.exit(0); },
|
|
363
|
+
function (e) { console.error("FAIL:", e && e.stack || e); process.exit(1); }
|
|
364
|
+
);
|
|
365
|
+
}
|
|
@@ -134,6 +134,39 @@ function testGuardXmlElementCap() {
|
|
|
134
134
|
rv.issues.some(function (i) { return i.kind === "element-cap"; }));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
function testGuardXmlByteCap() {
|
|
138
|
+
// The cap is named in BYTES; it must measure UTF-8 bytes, not UTF-16
|
|
139
|
+
// code units. "é" is one .length unit but two UTF-8 bytes, so a string
|
|
140
|
+
// whose .length is under the cap can still exceed it in bytes.
|
|
141
|
+
var multibyte = "é".repeat(40); // .length === 40, Buffer.byteLength === 80
|
|
142
|
+
var rv = b.guardXml.validate(multibyte, { profile: "strict", maxBytes: 50 });
|
|
143
|
+
var cap = rv.issues.filter(function (i) { return i.kind === "too-large"; });
|
|
144
|
+
check("multibyte input over the byte cap is refused",
|
|
145
|
+
rv.ok === false && cap.length === 1 &&
|
|
146
|
+
cap[0].ruleId === "xml.too-large" &&
|
|
147
|
+
/80 bytes exceeds maxBytes 50/.test(cap[0].snippet));
|
|
148
|
+
|
|
149
|
+
// ASCII under the cap must NOT trip too-large.
|
|
150
|
+
var underAscii = "a".repeat(40);
|
|
151
|
+
var rvUnder = b.guardXml.validate(underAscii, { profile: "strict", maxBytes: 50 });
|
|
152
|
+
check("ASCII input under the byte cap is not flagged too-large",
|
|
153
|
+
!rvUnder.issues.some(function (i) { return i.kind === "too-large"; }));
|
|
154
|
+
|
|
155
|
+
// ASCII over the cap still trips too-large.
|
|
156
|
+
var overAscii = "a".repeat(60);
|
|
157
|
+
var rvOver = b.guardXml.validate(overAscii, { profile: "strict", maxBytes: 50 });
|
|
158
|
+
check("ASCII input over the byte cap is refused",
|
|
159
|
+
rvOver.issues.some(function (i) { return i.kind === "too-large"; }));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function testGuardXmlBadInputRuleId() {
|
|
163
|
+
var rv = b.guardXml.validate(12345, { profile: "strict" });
|
|
164
|
+
check("non-string input carries xml.bad-input ruleId",
|
|
165
|
+
rv.issues.some(function (i) {
|
|
166
|
+
return i.kind === "bad-input" && i.ruleId === "xml.bad-input";
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
|
|
137
170
|
function testGuardXmlClean() {
|
|
138
171
|
var rv = b.guardXml.validate(
|
|
139
172
|
'<?xml version="1.0"?><root><name>alice</name><age>30</age></root>',
|
|
@@ -193,6 +226,8 @@ async function run() {
|
|
|
193
226
|
testGuardXmlCdata();
|
|
194
227
|
testGuardXmlBidiNull();
|
|
195
228
|
testGuardXmlElementCap();
|
|
229
|
+
testGuardXmlByteCap();
|
|
230
|
+
testGuardXmlBadInputRuleId();
|
|
196
231
|
testGuardXmlClean();
|
|
197
232
|
testGuardXmlSanitizeRefusesCritical();
|
|
198
233
|
testGuardXmlCompliancePosture();
|
|
@@ -128,6 +128,41 @@ function testGuardYamlBidiNull() {
|
|
|
128
128
|
rvNull.issues.some(function (issue) { return issue.kind === "null-byte"; }));
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function testGuardYamlByteCap() {
|
|
132
|
+
// "é" (U+00E9) is 1 UTF-16 code unit but 2 UTF-8 bytes. Five of them are
|
|
133
|
+
// 5 code units / 10 bytes; with maxBytes:6 the cap must measure BYTES — a
|
|
134
|
+
// .length compare would see 5 <= 6 and let a 10-byte input past a 6-byte cap.
|
|
135
|
+
var multibyte = "é".repeat(5);
|
|
136
|
+
var rvOver = b.guardYaml.validate(multibyte, { profile: "permissive", maxBytes: 6 });
|
|
137
|
+
var capIssue = rvOver.issues.filter(function (issue) { return issue.kind === "too-large"; })[0];
|
|
138
|
+
check("multibyte over byte cap → too-large fires (byte measure, not char)",
|
|
139
|
+
!!capIssue);
|
|
140
|
+
check("too-large snippet reports the byte length, not the char length",
|
|
141
|
+
!!capIssue && capIssue.snippet === "input 10 bytes exceeds maxBytes 6");
|
|
142
|
+
check("too-large carries ruleId yaml.too-large",
|
|
143
|
+
!!capIssue && capIssue.ruleId === "yaml.too-large");
|
|
144
|
+
|
|
145
|
+
// Same five code units fit under a byte cap that covers their 10 bytes.
|
|
146
|
+
var rvUnder = b.guardYaml.validate(multibyte, { profile: "permissive", maxBytes: 16 });
|
|
147
|
+
check("multibyte under byte cap → too-large does NOT fire",
|
|
148
|
+
!rvUnder.issues.some(function (issue) { return issue.kind === "too-large"; }));
|
|
149
|
+
|
|
150
|
+
// ASCII (1 byte == 1 code unit) is unaffected by the byte measure.
|
|
151
|
+
var rvAscii = b.guardYaml.validate("aaaaaaaa", { profile: "permissive", maxBytes: 4 });
|
|
152
|
+
check("ASCII over cap still fires with byte-count snippet",
|
|
153
|
+
rvAscii.issues.some(function (issue) {
|
|
154
|
+
return issue.kind === "too-large" &&
|
|
155
|
+
issue.snippet === "input 8 bytes exceeds maxBytes 4";
|
|
156
|
+
}));
|
|
157
|
+
|
|
158
|
+
// Non-string input is refused with the yaml.bad-input ruleId.
|
|
159
|
+
var rvBad = b.guardYaml.validate(12345, { profile: "permissive" });
|
|
160
|
+
check("non-string input → bad-input with ruleId yaml.bad-input",
|
|
161
|
+
rvBad.issues.some(function (issue) {
|
|
162
|
+
return issue.kind === "bad-input" && issue.ruleId === "yaml.bad-input";
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
|
|
131
166
|
function testGuardYamlClean() {
|
|
132
167
|
var rv = b.guardYaml.validate("name: alice\nage: 30\ntags:\n - one\n - two\n",
|
|
133
168
|
{ profile: "strict" });
|
|
@@ -193,6 +228,7 @@ async function run() {
|
|
|
193
228
|
testGuardYamlMergeKey();
|
|
194
229
|
testGuardYamlDuplicateKeys();
|
|
195
230
|
testGuardYamlBidiNull();
|
|
231
|
+
testGuardYamlByteCap();
|
|
196
232
|
testGuardYamlClean();
|
|
197
233
|
testGuardYamlParseStrictThrows();
|
|
198
234
|
testGuardYamlCompliancePosture();
|
|
@@ -801,6 +801,26 @@ async function run() {
|
|
|
801
801
|
testLazyLoadValidatesOnLoad();
|
|
802
802
|
testLazyLoadRejectsInlineTranslations();
|
|
803
803
|
testEagerLocalesValidation();
|
|
804
|
+
testLocaleChain();
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function testLocaleChain() {
|
|
808
|
+
function arrEq(a, e) { return JSON.stringify(a) === JSON.stringify(e); }
|
|
809
|
+
check("localeChain: fr-CA → fr → en (fallback en)",
|
|
810
|
+
arrEq(b.i18n.localeChain("fr-CA", { defaultLocale: "en", fallbackLocale: "en" }),
|
|
811
|
+
["fr-CA", "fr", "en"]));
|
|
812
|
+
check("localeChain: strict (fallback null) does not jump to default",
|
|
813
|
+
arrEq(b.i18n.localeChain("zh-Hant-TW", { defaultLocale: "en", fallbackLocale: null }),
|
|
814
|
+
["zh-Hant-TW", "zh-Hant", "zh"]));
|
|
815
|
+
check("localeChain: omitted fallback defaults to defaultLocale",
|
|
816
|
+
b.i18n.localeChain("de-DE", { defaultLocale: "en" }).indexOf("en") !== -1);
|
|
817
|
+
check("localeChain: bad locale throws",
|
|
818
|
+
(function () { try { b.i18n.localeChain("", { defaultLocale: "en" }); return false; }
|
|
819
|
+
catch (_e) { return true; } })());
|
|
820
|
+
check("localeChain: configured-set membership enforced",
|
|
821
|
+
(function () { try {
|
|
822
|
+
b.i18n.localeChain("fr", { defaultLocale: "en", locales: ["fr", "de"] }); return false;
|
|
823
|
+
} catch (_e) { return true; } })());
|
|
804
824
|
}
|
|
805
825
|
|
|
806
826
|
// ---- v0.4.14 ordinal + onMissingKey + lazyLoad ----
|
|
@@ -94,7 +94,22 @@ function _makeFakeExternalDb() {
|
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
async function testByteCapMultibyte() {
|
|
98
|
+
// maxPayloadBytes is a BYTE cap on the serialized metadata. A multibyte
|
|
99
|
+
// value under the char count but over the byte cap must be refused.
|
|
100
|
+
var fake = _makeFakeExternalDb();
|
|
101
|
+
var inbox = b.inbox.create({ externalDb: fake.db, table: "bytecap_inbox", audit: false, maxPayloadBytes: 30 });
|
|
102
|
+
var mb = String.fromCharCode(0x4e2d).repeat(15); // 15 chars / 45 UTF-8 bytes
|
|
103
|
+
var threw = null;
|
|
104
|
+
try {
|
|
105
|
+
await inbox.recordReceive({ messageId: "mb-1", source: "kafka:test", metadata: { note: mb } }, fake.xdb);
|
|
106
|
+
} catch (e) { threw = e; }
|
|
107
|
+
check("inbox byte-cap: multibyte metadata over byte cap refused",
|
|
108
|
+
threw && threw.code === "inbox/bad-receive");
|
|
109
|
+
}
|
|
110
|
+
|
|
97
111
|
async function run() {
|
|
112
|
+
await testByteCapMultibyte();
|
|
98
113
|
check("b.inbox is object", typeof b.inbox === "object");
|
|
99
114
|
check("b.inbox.create is fn", typeof b.inbox.create === "function");
|
|
100
115
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* lib/ip-utils — internal IP-address textual helpers shared across the
|
|
4
|
+
* mail (greylist / rbl / helo), guard-domain, and safe-schema consumers.
|
|
5
|
+
* Covers the strict dotted-quad IPv4 validator, the RFC 5321 bracketed
|
|
6
|
+
* address-literal form, and the bounded loose-IPv6 pre-filter that were
|
|
7
|
+
* consolidated here from five hand-rolled regex spellings.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var helpers = require("../helpers");
|
|
11
|
+
var check = helpers.check;
|
|
12
|
+
var ip = require("../../lib/ip-utils");
|
|
13
|
+
|
|
14
|
+
function run() {
|
|
15
|
+
// ---- isIPv4 / IPV4_RE — strict RFC 791 dotted-quad ----
|
|
16
|
+
["0.0.0.0", "255.255.255.255", "1.2.3.4", "192.168.0.1", "10.0.0.255",
|
|
17
|
+
"203.0.113.42", "9.9.9.9", "199.199.199.199", "250.250.250.250"]
|
|
18
|
+
.forEach(function (s) {
|
|
19
|
+
check("isIPv4 accepts " + s, ip.isIPv4(s) === true);
|
|
20
|
+
check("IPV4_RE matches isIPv4 for " + s, ip.IPV4_RE.test(s) === ip.isIPv4(s));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
["256.0.0.1", "1.2.3", "1.2.3.4.5", "01.2.3.4", "1.2.3.256", "300.1.1.1",
|
|
24
|
+
"", "abc", "1.2.3.4 ", " 1.2.3.4", "1.2.3.x", "999.0.0.0", "1.2.3.04",
|
|
25
|
+
"0xC0.0.0.1"]
|
|
26
|
+
.forEach(function (s) {
|
|
27
|
+
check("isIPv4 rejects " + JSON.stringify(s), ip.isIPv4(s) === false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Non-string inputs never throw, always false.
|
|
31
|
+
[null, undefined, 1234, {}, [], Buffer.from("1.2.3.4")].forEach(function (v) {
|
|
32
|
+
check("isIPv4 false on non-string " + Object.prototype.toString.call(v),
|
|
33
|
+
ip.isIPv4(v) === false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// ---- IPV4_ADDR_LITERAL_RE — RFC 5321 §4.1.3 bracketed form ----
|
|
37
|
+
var lit = "[203.0.113.42]".match(ip.IPV4_ADDR_LITERAL_RE);
|
|
38
|
+
check("IPV4_ADDR_LITERAL_RE matches bracketed literal", lit !== null);
|
|
39
|
+
check("IPV4_ADDR_LITERAL_RE captures inner dotted-quad", lit && lit[1] === "203.0.113.42");
|
|
40
|
+
check("IPV4_ADDR_LITERAL_RE rejects out-of-range octet",
|
|
41
|
+
ip.IPV4_ADDR_LITERAL_RE.test("[256.0.0.1]") === false);
|
|
42
|
+
check("IPV4_ADDR_LITERAL_RE rejects unbracketed", ip.IPV4_ADDR_LITERAL_RE.test("1.2.3.4") === false);
|
|
43
|
+
|
|
44
|
+
// ---- looksLikeIPv6Hex — bounded hex-colon pre-filter ----
|
|
45
|
+
["::1", "2001:db8::1", "fe80::1", "0:0:0:0:0:0:0:0",
|
|
46
|
+
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"] // 39 chars — the upper bound
|
|
47
|
+
.forEach(function (s) {
|
|
48
|
+
check("looksLikeIPv6Hex accepts " + s, ip.looksLikeIPv6Hex(s) === true);
|
|
49
|
+
});
|
|
50
|
+
check("looksLikeIPv6Hex boundary is exactly 39",
|
|
51
|
+
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".length === ip.IPV6_TEXT_MAX_LEN);
|
|
52
|
+
|
|
53
|
+
["::ffff:1.2.3.4", // dotted IPv4-mapped tail — excluded
|
|
54
|
+
"gggg::1", "nothex", "", "1.2.3.4",
|
|
55
|
+
"aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:aaaa:aaaa"] // 44 chars — over the bound
|
|
56
|
+
.forEach(function (s) {
|
|
57
|
+
check("looksLikeIPv6Hex rejects " + JSON.stringify(s), ip.looksLikeIPv6Hex(s) === false);
|
|
58
|
+
});
|
|
59
|
+
[null, undefined, 42, {}].forEach(function (v) {
|
|
60
|
+
check("looksLikeIPv6Hex false on non-string", ip.looksLikeIPv6Hex(v) === false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// A valid IPv6 that passes the pre-filter still expands cleanly.
|
|
64
|
+
check("pre-filter then expandIpv6Hex parses ::1",
|
|
65
|
+
ip.looksLikeIPv6Hex("::1") && ip.expandIpv6Hex("::1") === "00000000000000000000000000000001");
|
|
66
|
+
|
|
67
|
+
// ---- regression: existing helpers unchanged ----
|
|
68
|
+
check("isIPv4Shape loose still true for 999.0.0.0", ip.isIPv4Shape("999.0.0.0") === true);
|
|
69
|
+
check("isIPv4Shape false for non-dotted", ip.isIPv4Shape("notip") === false);
|
|
70
|
+
check("expandIpv6Hex(bad) null", ip.expandIpv6Hex("bad") === null);
|
|
71
|
+
check("expandIpv6Groups ::1", JSON.stringify(ip.expandIpv6Groups("::1")) === JSON.stringify([0, 0, 0, 0, 0, 0, 0, 1]));
|
|
72
|
+
|
|
73
|
+
return Promise.resolve();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { run: run };
|
|
77
|
+
|
|
78
|
+
if (require.main === module) run().then(function () {
|
|
79
|
+
process.stdout.write("OK — ip-utils\n");
|
|
80
|
+
}).catch(function (e) {
|
|
81
|
+
process.stderr.write("FAIL: " + (e && e.stack || e) + "\n");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
});
|
|
@@ -187,7 +187,17 @@ function testParseAuthFailureType() {
|
|
|
187
187
|
event.authFailure === "dmarc");
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
function testByteCapMultibyte() {
|
|
191
|
+
// maxBytes is a BYTE cap (regression for byte-cap-vs-char-length).
|
|
192
|
+
var report = String.fromCharCode(0x4e2d).repeat(20); // 20 chars / 60 UTF-8 bytes; cap 30
|
|
193
|
+
var threw = null;
|
|
194
|
+
try { b.mailArf.parse(report, { maxBytes: 30 }); } catch (e) { threw = e; }
|
|
195
|
+
check("mailArf byte-cap: multibyte report over byte cap refused",
|
|
196
|
+
threw && threw.message.indexOf("exceeds 30 bytes") !== -1);
|
|
197
|
+
}
|
|
198
|
+
|
|
190
199
|
async function run() {
|
|
200
|
+
testByteCapMultibyte();
|
|
191
201
|
testSurface();
|
|
192
202
|
testParseRfc5965Sample();
|
|
193
203
|
testParseMissingRequired();
|