@blamejs/blamejs-shop 0.4.31 → 0.4.33
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/README.md +1 -1
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +400 -282
- package/lib/vendor/blamejs/.github/workflows/ci.yml +34 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +21 -4
- package/lib/vendor/blamejs/.gitignore +6 -0
- package/lib/vendor/blamejs/CHANGELOG.md +28 -0
- package/lib/vendor/blamejs/MIGRATING.md +55 -0
- package/lib/vendor/blamejs/README.md +8 -6
- package/lib/vendor/blamejs/SECURITY.md +19 -3
- package/lib/vendor/blamejs/api-snapshot.json +2190 -664
- package/lib/vendor/blamejs/docker/caddy/localstack.Caddyfile +19 -0
- package/lib/vendor/blamejs/docker/init/generate-certs.sh +1 -1
- package/lib/vendor/blamejs/docker/otel/config.yaml +42 -0
- package/lib/vendor/blamejs/docker/otel/export/.gitkeep +0 -0
- package/lib/vendor/blamejs/docker/postgres/initdb/10-replication.sh +15 -0
- package/lib/vendor/blamejs/docker/postgres/replica-entrypoint.sh +38 -0
- package/lib/vendor/blamejs/docker/toxiproxy/toxiproxy.json +14 -0
- package/lib/vendor/blamejs/docker-compose.test.yml +209 -0
- package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +132 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +221 -61
- package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +144 -9
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +99 -0
- package/lib/vendor/blamejs/fuzz/guard-sql.fuzz.js +36 -0
- package/lib/vendor/blamejs/index.js +4 -0
- package/lib/vendor/blamejs/lib/agent-envelope-mac.js +104 -0
- package/lib/vendor/blamejs/lib/agent-event-bus.js +105 -4
- package/lib/vendor/blamejs/lib/agent-posture-chain.js +8 -42
- package/lib/vendor/blamejs/lib/ai-content-detect.js +9 -10
- package/lib/vendor/blamejs/lib/api-key.js +158 -77
- package/lib/vendor/blamejs/lib/atomic-file.js +62 -4
- package/lib/vendor/blamejs/lib/audit-chain.js +47 -11
- package/lib/vendor/blamejs/lib/audit-sign.js +77 -2
- package/lib/vendor/blamejs/lib/audit-tools.js +79 -51
- package/lib/vendor/blamejs/lib/audit.js +259 -123
- package/lib/vendor/blamejs/lib/auth/elevation-grant.js +6 -2
- package/lib/vendor/blamejs/lib/auth/oauth.js +66 -9
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +108 -47
- package/lib/vendor/blamejs/lib/auth/saml.js +6 -8
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +36 -7
- package/lib/vendor/blamejs/lib/backup/index.js +45 -10
- package/lib/vendor/blamejs/lib/break-glass.js +355 -147
- package/lib/vendor/blamejs/lib/cache.js +174 -105
- package/lib/vendor/blamejs/lib/chain-writer.js +38 -16
- package/lib/vendor/blamejs/lib/cli.js +19 -14
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +130 -104
- package/lib/vendor/blamejs/lib/cluster-storage.js +119 -22
- package/lib/vendor/blamejs/lib/cluster.js +119 -71
- package/lib/vendor/blamejs/lib/codepoint-class.js +23 -0
- package/lib/vendor/blamejs/lib/compliance.js +210 -4
- package/lib/vendor/blamejs/lib/consent.js +82 -29
- package/lib/vendor/blamejs/lib/constants.js +27 -11
- package/lib/vendor/blamejs/lib/credential-hash.js +9 -0
- package/lib/vendor/blamejs/lib/crypto-field.js +916 -156
- package/lib/vendor/blamejs/lib/db-declare-row-policy.js +35 -22
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +3 -2
- package/lib/vendor/blamejs/lib/db-query.js +882 -260
- package/lib/vendor/blamejs/lib/db-schema.js +228 -44
- package/lib/vendor/blamejs/lib/db.js +249 -99
- package/lib/vendor/blamejs/lib/dsr.js +385 -55
- package/lib/vendor/blamejs/lib/error-page.js +14 -1
- package/lib/vendor/blamejs/lib/external-db-migrate.js +239 -137
- package/lib/vendor/blamejs/lib/external-db.js +549 -34
- package/lib/vendor/blamejs/lib/file-upload.js +52 -7
- package/lib/vendor/blamejs/lib/framework-error.js +20 -1
- package/lib/vendor/blamejs/lib/framework-files.js +73 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +695 -394
- package/lib/vendor/blamejs/lib/gate-contract.js +659 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +26 -44
- package/lib/vendor/blamejs/lib/guard-all.js +1 -0
- package/lib/vendor/blamejs/lib/guard-auth.js +42 -112
- package/lib/vendor/blamejs/lib/guard-cidr.js +33 -154
- package/lib/vendor/blamejs/lib/guard-csv.js +46 -113
- package/lib/vendor/blamejs/lib/guard-domain.js +34 -157
- package/lib/vendor/blamejs/lib/guard-dsn.js +27 -43
- package/lib/vendor/blamejs/lib/guard-email.js +47 -69
- package/lib/vendor/blamejs/lib/guard-envelope.js +19 -32
- package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +24 -42
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +25 -43
- package/lib/vendor/blamejs/lib/guard-filename.js +42 -106
- package/lib/vendor/blamejs/lib/guard-graphql.js +42 -123
- package/lib/vendor/blamejs/lib/guard-html.js +53 -108
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +24 -42
- package/lib/vendor/blamejs/lib/guard-image.js +46 -103
- package/lib/vendor/blamejs/lib/guard-imap-command.js +18 -32
- package/lib/vendor/blamejs/lib/guard-jmap.js +16 -30
- package/lib/vendor/blamejs/lib/guard-json.js +38 -108
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +38 -171
- package/lib/vendor/blamejs/lib/guard-jwt.js +49 -179
- package/lib/vendor/blamejs/lib/guard-list-id.js +25 -41
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +27 -43
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +24 -42
- package/lib/vendor/blamejs/lib/guard-mail-move.js +26 -44
- package/lib/vendor/blamejs/lib/guard-mail-query.js +28 -46
- package/lib/vendor/blamejs/lib/guard-mail-reply.js +24 -42
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +24 -42
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +17 -31
- package/lib/vendor/blamejs/lib/guard-markdown.js +37 -104
- package/lib/vendor/blamejs/lib/guard-message-id.js +26 -45
- package/lib/vendor/blamejs/lib/guard-mime.js +39 -151
- package/lib/vendor/blamejs/lib/guard-oauth.js +54 -135
- package/lib/vendor/blamejs/lib/guard-pdf.js +45 -101
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +21 -31
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +24 -42
- package/lib/vendor/blamejs/lib/guard-regex.js +33 -107
- package/lib/vendor/blamejs/lib/guard-saga-config.js +24 -42
- package/lib/vendor/blamejs/lib/guard-shell.js +42 -172
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +48 -54
- package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +24 -42
- package/lib/vendor/blamejs/lib/guard-sql.js +1491 -0
- package/lib/vendor/blamejs/lib/guard-stream-args.js +24 -43
- package/lib/vendor/blamejs/lib/guard-svg.js +47 -65
- package/lib/vendor/blamejs/lib/guard-template.js +35 -172
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +26 -45
- package/lib/vendor/blamejs/lib/guard-time.js +32 -154
- package/lib/vendor/blamejs/lib/guard-trace-context.js +25 -44
- package/lib/vendor/blamejs/lib/guard-uuid.js +32 -153
- package/lib/vendor/blamejs/lib/guard-xml.js +38 -113
- package/lib/vendor/blamejs/lib/guard-yaml.js +51 -163
- package/lib/vendor/blamejs/lib/http-client.js +37 -9
- package/lib/vendor/blamejs/lib/inbox.js +120 -107
- package/lib/vendor/blamejs/lib/legal-hold.js +121 -50
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +47 -31
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +32 -18
- package/lib/vendor/blamejs/lib/mail-auth.js +236 -0
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +2 -6
- package/lib/vendor/blamejs/lib/mail-dkim.js +1 -0
- package/lib/vendor/blamejs/lib/mail-greylist.js +2 -6
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -6
- package/lib/vendor/blamejs/lib/mail-journal.js +85 -64
- package/lib/vendor/blamejs/lib/mail-rbl.js +2 -6
- package/lib/vendor/blamejs/lib/mail-scan.js +2 -6
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +117 -12
- package/lib/vendor/blamejs/lib/mail-server-mx.js +276 -7
- package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -6
- package/lib/vendor/blamejs/lib/mail-store.js +293 -154
- package/lib/vendor/blamejs/lib/mail.js +8 -4
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +71 -25
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +19 -8
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -1
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +17 -7
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +75 -51
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +102 -32
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +21 -5
- package/lib/vendor/blamejs/lib/migrations.js +108 -66
- package/lib/vendor/blamejs/lib/network-heartbeat.js +7 -0
- package/lib/vendor/blamejs/lib/network-proxy.js +24 -1
- package/lib/vendor/blamejs/lib/nonce-store.js +31 -9
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +9 -4
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +57 -3
- package/lib/vendor/blamejs/lib/object-store/gcs.js +4 -1
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -2
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +38 -6
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +9 -1
- package/lib/vendor/blamejs/lib/observability.js +124 -0
- package/lib/vendor/blamejs/lib/otel-export.js +12 -3
- package/lib/vendor/blamejs/lib/outbox.js +184 -83
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +47 -7
- package/lib/vendor/blamejs/lib/pqc-agent.js +44 -0
- package/lib/vendor/blamejs/lib/pubsub-cluster.js +42 -20
- package/lib/vendor/blamejs/lib/queue-local.js +225 -140
- package/lib/vendor/blamejs/lib/queue-redis.js +9 -1
- package/lib/vendor/blamejs/lib/queue-sqs.js +6 -0
- package/lib/vendor/blamejs/lib/queue.js +7 -0
- package/lib/vendor/blamejs/lib/redact.js +68 -11
- package/lib/vendor/blamejs/lib/redis-client.js +160 -31
- package/lib/vendor/blamejs/lib/request-helpers.js +7 -0
- package/lib/vendor/blamejs/lib/retention.js +117 -42
- package/lib/vendor/blamejs/lib/router.js +212 -5
- package/lib/vendor/blamejs/lib/safe-dns.js +29 -45
- package/lib/vendor/blamejs/lib/safe-ical.js +18 -33
- package/lib/vendor/blamejs/lib/safe-icap.js +27 -43
- package/lib/vendor/blamejs/lib/safe-sieve.js +21 -40
- package/lib/vendor/blamejs/lib/safe-sql.js +212 -3
- package/lib/vendor/blamejs/lib/safe-url.js +170 -3
- package/lib/vendor/blamejs/lib/safe-vcard.js +18 -33
- package/lib/vendor/blamejs/lib/scheduler.js +47 -12
- package/lib/vendor/blamejs/lib/seeders.js +122 -74
- package/lib/vendor/blamejs/lib/session-stores.js +42 -14
- package/lib/vendor/blamejs/lib/session.js +175 -77
- package/lib/vendor/blamejs/lib/sql.js +3842 -0
- package/lib/vendor/blamejs/lib/sse.js +26 -0
- package/lib/vendor/blamejs/lib/ssrf-guard.js +169 -4
- package/lib/vendor/blamejs/lib/static.js +177 -34
- package/lib/vendor/blamejs/lib/subject.js +96 -49
- package/lib/vendor/blamejs/lib/vault/index.js +3 -2
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +3 -2
- package/lib/vendor/blamejs/lib/vault/rotate.js +168 -108
- package/lib/vendor/blamejs/lib/vault-aad.js +6 -0
- package/lib/vendor/blamejs/lib/vendor-data.js +2 -0
- package/lib/vendor/blamejs/lib/websocket.js +35 -5
- package/lib/vendor/blamejs/lib/worker-pool.js +11 -0
- package/lib/vendor/blamejs/package.json +2 -2
- package/lib/vendor/blamejs/release-notes/v0.14.x.json +1503 -0
- package/lib/vendor/blamejs/release-notes/v0.15.0.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.15.1.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.2.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.3.json +39 -0
- package/lib/vendor/blamejs/release-notes/v0.15.4.json +39 -0
- package/lib/vendor/blamejs/release-notes/v0.15.5.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.15.6.json +59 -0
- package/lib/vendor/blamejs/release-notes/v0.15.7.json +43 -0
- package/lib/vendor/blamejs/scripts/check-services.js +21 -0
- package/lib/vendor/blamejs/scripts/gen-migrating.js +67 -0
- package/lib/vendor/blamejs/scripts/release.js +398 -38
- package/lib/vendor/blamejs/test/00-primitives.js +168 -0
- package/lib/vendor/blamejs/test/10-state.js +140 -14
- package/lib/vendor/blamejs/test/20-db.js +65 -2
- package/lib/vendor/blamejs/test/helpers/db.js +9 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +27 -15
- package/lib/vendor/blamejs/test/helpers/services.js +21 -0
- package/lib/vendor/blamejs/test/integration/audit-actor-binding-pg.test.js +246 -0
- package/lib/vendor/blamejs/test/integration/audit-chain-external-db.test.js +517 -0
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +639 -0
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +832 -0
- package/lib/vendor/blamejs/test/integration/backup-restore-objectstore.test.js +453 -0
- package/lib/vendor/blamejs/test/integration/data-layer-cluster-mysql.test.js +649 -0
- package/lib/vendor/blamejs/test/integration/data-layer-cluster-pg.test.js +770 -0
- package/lib/vendor/blamejs/test/integration/data-layer-mysql-privacy.test.js +630 -0
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +610 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +577 -0
- package/lib/vendor/blamejs/test/integration/data-layer-postgres.test.js +771 -0
- package/lib/vendor/blamejs/test/integration/db-layer-mysql.test.js +549 -0
- package/lib/vendor/blamejs/test/integration/db-layer-postgres.test.js +598 -0
- package/lib/vendor/blamejs/test/integration/distributed-scheduler-fencing-pg.test.js +602 -0
- package/lib/vendor/blamejs/test/integration/external-db-postgres.test.js +576 -0
- package/lib/vendor/blamejs/test/integration/framework-schema-mysql.test.js +353 -0
- package/lib/vendor/blamejs/test/integration/log-stream-cloudwatch.test.js +224 -0
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +142 -17
- package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +25 -10
- package/lib/vendor/blamejs/test/integration/object-store-azure.test.js +101 -0
- package/lib/vendor/blamejs/test/integration/object-store-gcs.test.js +239 -0
- package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +35 -16
- package/lib/vendor/blamejs/test/integration/object-store-worm-lock.test.js +291 -0
- package/lib/vendor/blamejs/test/integration/pubsub.test.js +14 -0
- package/lib/vendor/blamejs/test/integration/queue-sqs.test.js +322 -0
- package/lib/vendor/blamejs/test/integration/redis-reconnect-toxiproxy.test.js +300 -0
- package/lib/vendor/blamejs/test/integration/sql-fts5-catalog-sqlite.test.js +154 -0
- package/lib/vendor/blamejs/test/integration/tls-classical-downgrade-audit.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +175 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-exclusive-temp.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-checkpoint-false-rollback.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-query-self-log.test.js +126 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-safeemit-redacts-secrets.test.js +196 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +197 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +209 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-residency-posture.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-scheduletest-drill.test.js +318 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +233 -7
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +1196 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +229 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +24 -7
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-dual-read-migrate.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +350 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-unseal-rate-cap.test.js +27 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-upgrade-dialect.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-interop-oracles.test.js +392 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +159 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-column-gate.test.js +180 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-sealed-field-in.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-drift.test.js +38 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/db-schema-reconcile-emittable.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-stream-and-payload-shape.test.js +267 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/defineguard-default-gate-posture-caps.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-replaystore-required.test.js +46 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +218 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/erase-posture-vacuum.test.js +210 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +4 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +48 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +237 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +20 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +193 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +90 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +10 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +15 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +189 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +3 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +123 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +207 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +101 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox-inflight-reaper.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey-real-vectors.test.js +429 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +21 -11
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-byo-db.test.js +40 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-dryrun-no-vacuum.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-use-path-scope.test.js +255 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-canonicalize.test.js +362 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-xml.test.js +143 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +287 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-watchdog-stale-settle.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc-ecdsa-p1363.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +31 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +49 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +595 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sse-backpressure.test.js +91 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +194 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket-extension-header.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +638 -0
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +21 -0
- package/lib/vendor/blamejs/test/smoke.js +79 -21
- package/package.json +2 -2
- package/lib/vendor/blamejs/release-notes/v0.14.0.json +0 -43
- package/lib/vendor/blamejs/release-notes/v0.14.1.json +0 -60
- package/lib/vendor/blamejs/release-notes/v0.14.10.json +0 -54
- package/lib/vendor/blamejs/release-notes/v0.14.11.json +0 -72
- package/lib/vendor/blamejs/release-notes/v0.14.12.json +0 -95
- package/lib/vendor/blamejs/release-notes/v0.14.13.json +0 -52
- package/lib/vendor/blamejs/release-notes/v0.14.14.json +0 -31
- package/lib/vendor/blamejs/release-notes/v0.14.16.json +0 -45
- package/lib/vendor/blamejs/release-notes/v0.14.17.json +0 -57
- package/lib/vendor/blamejs/release-notes/v0.14.18.json +0 -127
- package/lib/vendor/blamejs/release-notes/v0.14.19.json +0 -61
- package/lib/vendor/blamejs/release-notes/v0.14.2.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.20.json +0 -73
- package/lib/vendor/blamejs/release-notes/v0.14.21.json +0 -98
- package/lib/vendor/blamejs/release-notes/v0.14.22.json +0 -91
- package/lib/vendor/blamejs/release-notes/v0.14.3.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.4.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.5.json +0 -18
- package/lib/vendor/blamejs/release-notes/v0.14.6.json +0 -60
- package/lib/vendor/blamejs/release-notes/v0.14.7.json +0 -77
- package/lib/vendor/blamejs/release-notes/v0.14.8.json +0 -27
- package/lib/vendor/blamejs/release-notes/v0.14.9.json +0 -40
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
|
|
82
82
|
var C = require("./constants");
|
|
83
83
|
var { defineClass } = require("./framework-error");
|
|
84
|
+
var gateContract = require("./gate-contract");
|
|
84
85
|
|
|
85
86
|
var SafeIcalError = defineClass("SafeIcalError", { alwaysPermanent: true });
|
|
86
87
|
|
|
@@ -116,12 +117,7 @@ var PROFILES = Object.freeze({
|
|
|
116
117
|
}),
|
|
117
118
|
});
|
|
118
119
|
|
|
119
|
-
var COMPLIANCE_POSTURES =
|
|
120
|
-
hipaa: "strict",
|
|
121
|
-
"pci-dss": "strict",
|
|
122
|
-
gdpr: "strict",
|
|
123
|
-
soc2: "strict",
|
|
124
|
-
});
|
|
120
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
125
121
|
|
|
126
122
|
// Property-name allowlist per RFC 5545 §8.7 (Property Registry) +
|
|
127
123
|
// RFC 5546 §4.3 (iTIP additions) + RFC 7986 §5 (new calendar
|
|
@@ -273,24 +269,6 @@ function parse(text, opts) {
|
|
|
273
269
|
: { vcalendar: vcalendars[0], vcalendars: vcalendars };
|
|
274
270
|
}
|
|
275
271
|
|
|
276
|
-
/**
|
|
277
|
-
* @primitive b.safeIcal.compliancePosture
|
|
278
|
-
* @signature b.safeIcal.compliancePosture(name)
|
|
279
|
-
* @since 0.9.81
|
|
280
|
-
* @status stable
|
|
281
|
-
* @related b.safeIcal.parse
|
|
282
|
-
*
|
|
283
|
-
* Map a compliance-posture name to its profile. Returns the profile
|
|
284
|
-
* string for a known posture, `null` for unknown names.
|
|
285
|
-
*
|
|
286
|
-
* @example
|
|
287
|
-
* b.safeIcal.compliancePosture("hipaa"); // → "strict"
|
|
288
|
-
* b.safeIcal.compliancePosture("loose"); // → null
|
|
289
|
-
*/
|
|
290
|
-
function compliancePosture(name) {
|
|
291
|
-
return COMPLIANCE_POSTURES[name] || null;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
272
|
// ---- Profile / opt resolution ----
|
|
295
273
|
|
|
296
274
|
function _resolveCaps(opts) {
|
|
@@ -623,12 +601,19 @@ function _preview(s) {
|
|
|
623
601
|
return s.length > 64 ? s.slice(0, 64) + "..." : s; // log-preview length cap
|
|
624
602
|
}
|
|
625
603
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
604
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
605
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
606
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
607
|
+
// generator.
|
|
608
|
+
module.exports = gateContract.defineParser({
|
|
609
|
+
name: "ical",
|
|
610
|
+
entry: parse,
|
|
611
|
+
entryName: "parse",
|
|
612
|
+
errorClass: SafeIcalError,
|
|
613
|
+
profiles: PROFILES,
|
|
614
|
+
postures: COMPLIANCE_POSTURES,
|
|
615
|
+
extra: {
|
|
616
|
+
KNOWN_PROPERTIES: KNOWN_PROPERTIES,
|
|
617
|
+
KNOWN_COMPONENTS: KNOWN_COMPONENTS,
|
|
618
|
+
},
|
|
619
|
+
});
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
|
|
78
78
|
var C = require("./constants");
|
|
79
79
|
var { defineClass } = require("./framework-error");
|
|
80
|
+
var gateContract = require("./gate-contract");
|
|
80
81
|
|
|
81
82
|
var SafeIcapError = defineClass("SafeIcapError", { alwaysPermanent: true });
|
|
82
83
|
|
|
@@ -131,11 +132,15 @@ var PROFILES = Object.freeze({
|
|
|
131
132
|
},
|
|
132
133
|
});
|
|
133
134
|
|
|
134
|
-
var COMPLIANCE_POSTURES =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
136
|
+
|
|
137
|
+
var _resolveProfile = gateContract.makeProfileResolver({
|
|
138
|
+
profiles: PROFILES,
|
|
139
|
+
postures: COMPLIANCE_POSTURES,
|
|
140
|
+
defaults: DEFAULT_PROFILE,
|
|
141
|
+
errorClass: SafeIcapError,
|
|
142
|
+
codePrefix: "safe-icap",
|
|
143
|
+
byObject: true,
|
|
139
144
|
});
|
|
140
145
|
|
|
141
146
|
/**
|
|
@@ -257,22 +262,6 @@ function parse(buf, opts) {
|
|
|
257
262
|
};
|
|
258
263
|
}
|
|
259
264
|
|
|
260
|
-
/**
|
|
261
|
-
* @primitive b.safeIcap.compliancePosture
|
|
262
|
-
* @signature b.safeIcap.compliancePosture(posture)
|
|
263
|
-
* @since 0.9.81
|
|
264
|
-
* @status stable
|
|
265
|
-
*
|
|
266
|
-
* Return the effective profile name for a compliance posture, or
|
|
267
|
-
* `null` for unknown posture names.
|
|
268
|
-
*
|
|
269
|
-
* @example
|
|
270
|
-
* b.safeIcap.compliancePosture("hipaa"); // → "strict"
|
|
271
|
-
*/
|
|
272
|
-
function compliancePosture(posture) {
|
|
273
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
265
|
// ---- internals ----
|
|
277
266
|
|
|
278
267
|
function _findHeaderEnd(buf, maxHeaderBytes) {
|
|
@@ -479,25 +468,20 @@ function _detectThreat(statusCode, headers) {
|
|
|
479
468
|
return { found: found, name: name };
|
|
480
469
|
}
|
|
481
470
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
ALLOWED_STATUS: ALLOWED_STATUS,
|
|
500
|
-
SafeIcapError: SafeIcapError,
|
|
501
|
-
NAME: "icap",
|
|
502
|
-
KIND: "icap-response",
|
|
503
|
-
};
|
|
471
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
472
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
473
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
474
|
+
// generator.
|
|
475
|
+
module.exports = gateContract.defineParser({
|
|
476
|
+
name: "icap",
|
|
477
|
+
entry: parse,
|
|
478
|
+
entryName: "parse",
|
|
479
|
+
errorClass: SafeIcapError,
|
|
480
|
+
profiles: PROFILES,
|
|
481
|
+
postures: COMPLIANCE_POSTURES,
|
|
482
|
+
extra: {
|
|
483
|
+
ALLOWED_STATUS: ALLOWED_STATUS,
|
|
484
|
+
NAME: "icap",
|
|
485
|
+
KIND: "icap-response",
|
|
486
|
+
},
|
|
487
|
+
});
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
51
|
var { defineClass } = require("./framework-error");
|
|
52
|
+
var gateContract = require("./gate-contract");
|
|
52
53
|
|
|
53
54
|
var SafeSieveError = defineClass("SafeSieveError", { alwaysPermanent: true });
|
|
54
55
|
|
|
@@ -82,12 +83,7 @@ var PROFILES = Object.freeze({
|
|
|
82
83
|
}),
|
|
83
84
|
});
|
|
84
85
|
|
|
85
|
-
var COMPLIANCE_POSTURES =
|
|
86
|
-
hipaa: "strict",
|
|
87
|
-
"pci-dss": "strict",
|
|
88
|
-
gdpr: "strict",
|
|
89
|
-
soc2: "strict",
|
|
90
|
-
});
|
|
86
|
+
var COMPLIANCE_POSTURES = gateContract.ALL_STRICT_POSTURES;
|
|
91
87
|
|
|
92
88
|
// RFC 5228 §1.2 capability identifiers. Each entry lists whether the
|
|
93
89
|
// framework's v0.9.55 interpreter implements the capability. Unknown
|
|
@@ -648,37 +644,22 @@ function validate(script, opts) {
|
|
|
648
644
|
}
|
|
649
645
|
}
|
|
650
646
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
return COMPLIANCE_POSTURES[name] || null;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
module.exports = {
|
|
674
|
-
parse: parse,
|
|
675
|
-
validate: validate,
|
|
676
|
-
compliancePosture: compliancePosture,
|
|
677
|
-
KNOWN_CAPABILITIES: KNOWN_CAPABILITIES,
|
|
678
|
-
PROFILES: PROFILES,
|
|
679
|
-
COMPLIANCE_POSTURES: COMPLIANCE_POSTURES,
|
|
680
|
-
SafeSieveError: SafeSieveError,
|
|
681
|
-
// Internal exports for the interpreter at lib/mail-sieve.js.
|
|
682
|
-
_tokenize: _tokenize,
|
|
683
|
-
_resolveCaps: _resolveCaps,
|
|
684
|
-
};
|
|
647
|
+
// compliancePosture is assembled by gateContract.defineParser below; its
|
|
648
|
+
// wiki section renders from the single-sourced @abiTemplate (defineParser)
|
|
649
|
+
// block in gate-contract.js, instantiated for this guard by the page
|
|
650
|
+
// generator.
|
|
651
|
+
module.exports = gateContract.defineParser({
|
|
652
|
+
name: "sieve",
|
|
653
|
+
entry: parse,
|
|
654
|
+
entryName: "parse",
|
|
655
|
+
errorClass: SafeSieveError,
|
|
656
|
+
profiles: PROFILES,
|
|
657
|
+
postures: COMPLIANCE_POSTURES,
|
|
658
|
+
extra: {
|
|
659
|
+
validate: validate,
|
|
660
|
+
KNOWN_CAPABILITIES: KNOWN_CAPABILITIES,
|
|
661
|
+
// Internal exports for the interpreter at lib/mail-sieve.js.
|
|
662
|
+
_tokenize: _tokenize,
|
|
663
|
+
_resolveCaps: _resolveCaps,
|
|
664
|
+
},
|
|
665
|
+
});
|
|
@@ -175,7 +175,7 @@ function validateIdentifier(name, opts) {
|
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* @primitive b.safeSql.quoteIdentifier
|
|
178
|
-
* @signature b.safeSql.quoteIdentifier(name, dialect?)
|
|
178
|
+
* @signature b.safeSql.quoteIdentifier(name, dialect?, opts?)
|
|
179
179
|
* @since 0.1.0
|
|
180
180
|
* @status stable
|
|
181
181
|
* @related b.safeSql.validateIdentifier, b.safeSql.quoteQualified
|
|
@@ -185,6 +185,17 @@ function validateIdentifier(name, opts) {
|
|
|
185
185
|
* MySQL. Default dialect is `"sqlite"`. Throws `SafeSqlError` if the
|
|
186
186
|
* identifier fails `validateIdentifier`.
|
|
187
187
|
*
|
|
188
|
+
* `opts` is forwarded to `validateIdentifier` — pass
|
|
189
|
+
* `{ allowReserved: true }` to quote a name that collides with a SQL
|
|
190
|
+
* keyword (a column literally named `from` / `select`). Quoting is
|
|
191
|
+
* exactly what makes a reserved word safe in identifier position, so the
|
|
192
|
+
* query builder (`b.sql`) routes every identifier through here with
|
|
193
|
+
* `allowReserved` on; the default still rejects reserved words so a bare
|
|
194
|
+
* caller catches the likely typo.
|
|
195
|
+
*
|
|
196
|
+
* @opts
|
|
197
|
+
* allowReserved: boolean, // default: false — permit SQL-keyword names (safe once quoted)
|
|
198
|
+
*
|
|
188
199
|
* @example
|
|
189
200
|
* var b = require("blamejs");
|
|
190
201
|
* b.safeSql.quoteIdentifier("users");
|
|
@@ -193,11 +204,14 @@ function validateIdentifier(name, opts) {
|
|
|
193
204
|
* b.safeSql.quoteIdentifier("Order", "postgres");
|
|
194
205
|
* // → '"Order"'
|
|
195
206
|
*
|
|
207
|
+
* b.safeSql.quoteIdentifier("from", "postgres", { allowReserved: true });
|
|
208
|
+
* // → '"from"'
|
|
209
|
+
*
|
|
196
210
|
* b.safeSql.quoteIdentifier("users", "mysql");
|
|
197
211
|
* // → "`users`"
|
|
198
212
|
*/
|
|
199
|
-
function quoteIdentifier(name, dialect) {
|
|
200
|
-
validateIdentifier(name);
|
|
213
|
+
function quoteIdentifier(name, dialect, opts) {
|
|
214
|
+
validateIdentifier(name, opts);
|
|
201
215
|
dialect = (dialect || "sqlite").toLowerCase();
|
|
202
216
|
if (dialect === "mysql") return "`" + name + "`";
|
|
203
217
|
// sqlite + postgres both use double-quote per SQL standard
|
|
@@ -258,6 +272,53 @@ function quoteQualified(parts, dialect) {
|
|
|
258
272
|
return quoted.join(".");
|
|
259
273
|
}
|
|
260
274
|
|
|
275
|
+
/**
|
|
276
|
+
* @primitive b.safeSql.quoteList
|
|
277
|
+
* @signature b.safeSql.quoteList(names, dialect?, opts?)
|
|
278
|
+
* @since 0.15.0
|
|
279
|
+
* @status stable
|
|
280
|
+
* @related b.safeSql.quoteIdentifier, b.safeSql.quoteQualified, b.sql
|
|
281
|
+
*
|
|
282
|
+
* Quote a list of identifiers into a comma-joined fragment — each name
|
|
283
|
+
* validated + quoted via `quoteIdentifier`. The "many" companion to
|
|
284
|
+
* `quoteIdentifier` (one) and `quoteQualified` (a dotted name): use it for
|
|
285
|
+
* SELECT projections and INSERT column lists so the recurring
|
|
286
|
+
* `cols.map(quoteIdentifier).join(", ")` shape is composed, not hand-rolled.
|
|
287
|
+
*
|
|
288
|
+
* There is deliberately NO value/string-literal quoter in this module:
|
|
289
|
+
* values flow as bound placeholders (`?` / `$N`), never interpolated, which
|
|
290
|
+
* is what makes the injection class structurally impossible. Quoting a
|
|
291
|
+
* literal would reopen it — use the query builder's parameter binding.
|
|
292
|
+
*
|
|
293
|
+
* `opts` is forwarded to each `quoteIdentifier` (e.g.
|
|
294
|
+
* `{ allowReserved: true }` for column lists that may contain SQL-keyword
|
|
295
|
+
* names, as `b.sql` does).
|
|
296
|
+
*
|
|
297
|
+
* Throws `SafeSqlError` (`sql/empty`) on an empty array and (per
|
|
298
|
+
* `quoteIdentifier`) on any invalid identifier.
|
|
299
|
+
*
|
|
300
|
+
* @opts
|
|
301
|
+
* allowReserved: boolean, // default: false — forwarded to quoteIdentifier
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* var b = require("blamejs");
|
|
305
|
+
* b.safeSql.quoteList(["id", "createdAt"], "postgres");
|
|
306
|
+
* // → '"id", "createdAt"'
|
|
307
|
+
*
|
|
308
|
+
* b.safeSql.quoteList(["queueName", "status"], "mysql");
|
|
309
|
+
* // → "`queueName`, `status`"
|
|
310
|
+
*/
|
|
311
|
+
function quoteList(names, dialect, opts) {
|
|
312
|
+
if (!Array.isArray(names) || names.length === 0) {
|
|
313
|
+
throw new SafeSqlError("quoteList requires a non-empty array of identifiers", "sql/empty");
|
|
314
|
+
}
|
|
315
|
+
var out = [];
|
|
316
|
+
for (var i = 0; i < names.length; i++) {
|
|
317
|
+
out.push(quoteIdentifier(names[i], dialect, opts));
|
|
318
|
+
}
|
|
319
|
+
return out.join(", ");
|
|
320
|
+
}
|
|
321
|
+
|
|
261
322
|
/**
|
|
262
323
|
* @primitive b.safeSql.assertOneOf
|
|
263
324
|
* @signature b.safeSql.assertOneOf(name, allowlist)
|
|
@@ -310,6 +371,64 @@ function assertOneOf(name, allowlist) {
|
|
|
310
371
|
return name;
|
|
311
372
|
}
|
|
312
373
|
|
|
374
|
+
/**
|
|
375
|
+
* @primitive b.safeSql.countPlaceholders
|
|
376
|
+
* @signature b.safeSql.countPlaceholders(sql)
|
|
377
|
+
* @since 0.14.29
|
|
378
|
+
* @status stable
|
|
379
|
+
* @related b.safeSql.quoteIdentifier, b.safeSql.validateIdentifier
|
|
380
|
+
*
|
|
381
|
+
* Count the bound `?` placeholders in a SQL string, skipping any `?`
|
|
382
|
+
* that appears inside a string literal (`'...'` / `"..."`, doubled-quote
|
|
383
|
+
* escape aware) or inside a line or block comment. The canonical quote-
|
|
384
|
+
* and comment-aware scanner the query builder uses to check placeholder /
|
|
385
|
+
* param parity and the residency write-gate uses to align bound values;
|
|
386
|
+
* both compose this so the skip rules live in one place.
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* var b = require("blamejs");
|
|
390
|
+
* b.safeSql.countPlaceholders("a = ? AND b = ?");
|
|
391
|
+
* // → 2
|
|
392
|
+
*
|
|
393
|
+
* b.safeSql.countPlaceholders("note = 'is ? literal' AND id = ?");
|
|
394
|
+
* // → 1
|
|
395
|
+
*/
|
|
396
|
+
function countPlaceholders(sql) {
|
|
397
|
+
var count = 0;
|
|
398
|
+
var i = 0;
|
|
399
|
+
var len = sql.length;
|
|
400
|
+
while (i < len) {
|
|
401
|
+
var ch = sql.charAt(i);
|
|
402
|
+
var next = i + 1 < len ? sql.charAt(i + 1) : "";
|
|
403
|
+
if (ch === "'" || ch === '"') {
|
|
404
|
+
var quote = ch;
|
|
405
|
+
i += 1;
|
|
406
|
+
while (i < len) {
|
|
407
|
+
if (sql.charAt(i) === quote) {
|
|
408
|
+
// SQL doubles the quote char to escape it within a literal.
|
|
409
|
+
if (sql.charAt(i + 1) === quote) { i += 2; continue; }
|
|
410
|
+
i += 1; break;
|
|
411
|
+
}
|
|
412
|
+
i += 1;
|
|
413
|
+
}
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (ch === "-" && next === "-") {
|
|
417
|
+
while (i < len && sql.charAt(i) !== "\n") i += 1;
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (ch === "/" && next === "*") {
|
|
421
|
+
i += 2;
|
|
422
|
+
while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) i += 1;
|
|
423
|
+
i += 2;
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (ch === "?") count += 1;
|
|
427
|
+
i += 1;
|
|
428
|
+
}
|
|
429
|
+
return count;
|
|
430
|
+
}
|
|
431
|
+
|
|
313
432
|
/**
|
|
314
433
|
* @primitive b.safeSql.DEFAULT_IDENTIFIER_RE
|
|
315
434
|
* @signature b.safeSql.DEFAULT_IDENTIFIER_RE
|
|
@@ -351,11 +470,101 @@ function assertOneOf(name, allowlist) {
|
|
|
351
470
|
* // → 63
|
|
352
471
|
*/
|
|
353
472
|
|
|
473
|
+
/**
|
|
474
|
+
* @primitive b.safeSql.assertSingleStatement
|
|
475
|
+
* @signature b.safeSql.assertSingleStatement(sql, opts?)
|
|
476
|
+
* @since 0.15.4
|
|
477
|
+
* @status stable
|
|
478
|
+
* @related b.safeSql.quoteIdentifier, b.safeSql.countPlaceholders, b.sql
|
|
479
|
+
*
|
|
480
|
+
* The one quote/comment-aware single-statement gate for any FINISHED SQL
|
|
481
|
+
* string that reaches a driver. Refuses a NUL, a lone surrogate, a
|
|
482
|
+
* top-level ';' (stacked statement), an unterminated quote, and unbalanced
|
|
483
|
+
* parentheses - while CORRECTLY allowing those characters inside a balanced
|
|
484
|
+
* quoted label (e.g. a MySQL ENUM('a;b')). Hand-rolled DDL (schema
|
|
485
|
+
* reconcile, the DSR store, migrations) and the b.sql builder's own output
|
|
486
|
+
* gates route through this single scan so the injection backstop cannot
|
|
487
|
+
* drift between the structured builder and the raw-DDL paths. Returns the
|
|
488
|
+
* input string so a caller can wrap inline:
|
|
489
|
+
* runSql(db, safeSql.assertSingleStatement(ddl, { label: "schema" }));
|
|
490
|
+
*
|
|
491
|
+
* @opts
|
|
492
|
+
* label: string, // message prefix (default: "sql")
|
|
493
|
+
* makeError: function, // (message, codeSuffix) => Error (default: SafeSqlError "sql/<suffix>")
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* var ddl = b.safeSql.assertSingleStatement("CREATE TABLE t (id INTEGER)", { label: "schema" });
|
|
497
|
+
* // returns the input string; throws sql/stacked-statement on a stacked DDL
|
|
498
|
+
*/
|
|
499
|
+
function assertSingleStatement(sql, opts) {
|
|
500
|
+
opts = opts || {};
|
|
501
|
+
var label = typeof opts.label === "string" ? opts.label : "sql";
|
|
502
|
+
var mkErr = typeof opts.makeError === "function"
|
|
503
|
+
? opts.makeError
|
|
504
|
+
: function (msg, suffix) { return new SafeSqlError(msg, "sql/" + suffix); };
|
|
505
|
+
// Backtick written via its code point so no NUL byte can reach this source.
|
|
506
|
+
var BACKTICK = String.fromCharCode(96);
|
|
507
|
+
if (typeof sql !== "string" || sql.length === 0) {
|
|
508
|
+
throw mkErr(label + ": SQL must be a non-empty string", "empty-sql");
|
|
509
|
+
}
|
|
510
|
+
if (sql.indexOf(String.fromCharCode(0)) !== -1) {
|
|
511
|
+
throw mkErr(label + ": SQL contains a NUL byte - rejected", "null-byte-sql");
|
|
512
|
+
}
|
|
513
|
+
if (typeof sql.isWellFormed === "function" && !sql.isWellFormed()) {
|
|
514
|
+
throw mkErr(label + ": SQL contains invalid Unicode (lone surrogates) - rejected",
|
|
515
|
+
"invalid-encoding-sql");
|
|
516
|
+
}
|
|
517
|
+
var i = 0;
|
|
518
|
+
var len = sql.length;
|
|
519
|
+
var depth = 0;
|
|
520
|
+
while (i < len) {
|
|
521
|
+
var ch = sql.charAt(i);
|
|
522
|
+
var next = i + 1 < len ? sql.charAt(i + 1) : "";
|
|
523
|
+
if (ch === "'" || ch === '"' || ch === BACKTICK) {
|
|
524
|
+
var qch = ch;
|
|
525
|
+
var closed = false;
|
|
526
|
+
i += 1;
|
|
527
|
+
while (i < len) {
|
|
528
|
+
if (sql.charAt(i) === qch) {
|
|
529
|
+
if (sql.charAt(i + 1) === qch) { i += 2; continue; } // doubled quote = escaped literal
|
|
530
|
+
i += 1; closed = true; break;
|
|
531
|
+
}
|
|
532
|
+
i += 1;
|
|
533
|
+
}
|
|
534
|
+
if (!closed) {
|
|
535
|
+
throw mkErr(label + ": unterminated quote in SQL (quote-jump / breakout risk)",
|
|
536
|
+
"unterminated-quote");
|
|
537
|
+
}
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
if (ch === "-" && next === "-") { while (i < len && sql.charAt(i) !== "\n") i += 1; continue; }
|
|
541
|
+
if (ch === "/" && next === "*") {
|
|
542
|
+
i += 2;
|
|
543
|
+
while (i < len && !(sql.charAt(i) === "*" && sql.charAt(i + 1) === "/")) i += 1;
|
|
544
|
+
i += 2;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (ch === "(") { depth += 1; }
|
|
548
|
+
else if (ch === ")") { depth -= 1; }
|
|
549
|
+
else if (ch === ";") {
|
|
550
|
+
throw mkErr(label + ": emitted a top-level ';' - exactly one statement", "stacked-statement");
|
|
551
|
+
}
|
|
552
|
+
i += 1;
|
|
553
|
+
}
|
|
554
|
+
if (depth !== 0) {
|
|
555
|
+
throw mkErr(label + ": unbalanced parentheses in SQL", "unbalanced");
|
|
556
|
+
}
|
|
557
|
+
return sql;
|
|
558
|
+
}
|
|
559
|
+
|
|
354
560
|
module.exports = {
|
|
355
561
|
validateIdentifier: validateIdentifier,
|
|
562
|
+
assertSingleStatement: assertSingleStatement,
|
|
356
563
|
quoteIdentifier: quoteIdentifier,
|
|
357
564
|
quoteQualified: quoteQualified,
|
|
565
|
+
quoteList: quoteList,
|
|
358
566
|
assertOneOf: assertOneOf,
|
|
567
|
+
countPlaceholders: countPlaceholders,
|
|
359
568
|
SafeSqlError: SafeSqlError,
|
|
360
569
|
// Exposed so consumers can compose their own validators
|
|
361
570
|
DEFAULT_IDENTIFIER_RE: DEFAULT_IDENTIFIER_RE,
|