@blamejs/blamejs-shop 0.0.44
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 +87 -0
- package/LICENSE +17 -0
- package/README.md +117 -0
- package/SECURITY.md +139 -0
- package/lib/admin.js +952 -0
- package/lib/analytics.js +267 -0
- package/lib/cart.js +279 -0
- package/lib/catalog-import.js +344 -0
- package/lib/catalog.js +769 -0
- package/lib/checkout.js +320 -0
- package/lib/config.js +151 -0
- package/lib/customers.js +322 -0
- package/lib/email.js +242 -0
- package/lib/externaldb-d1.js +283 -0
- package/lib/index.js +57 -0
- package/lib/inventory-alerts.js +198 -0
- package/lib/newsletter.js +142 -0
- package/lib/order.js +380 -0
- package/lib/payment.js +318 -0
- package/lib/pricing.js +185 -0
- package/lib/r2-bridge.js +169 -0
- package/lib/shipping.js +185 -0
- package/lib/storefront.js +2160 -0
- package/lib/subscriptions.js +410 -0
- package/lib/tax.js +161 -0
- package/lib/theme.js +194 -0
- package/lib/vendor/MANIFEST.json +19 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +23 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +34 -0
- package/lib/vendor/blamejs/.clusterfuzzlite/project.yaml +16 -0
- package/lib/vendor/blamejs/.dockerignore +45 -0
- package/lib/vendor/blamejs/.gitattributes +42 -0
- package/lib/vendor/blamejs/.github/CODEOWNERS +4 -0
- package/lib/vendor/blamejs/.github/FUNDING.yml +2 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/bug_report.md +58 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/lib/vendor/blamejs/.github/ISSUE_TEMPLATE/feature_request.md +99 -0
- package/lib/vendor/blamejs/.github/PULL_REQUEST_TEMPLATE.md +77 -0
- package/lib/vendor/blamejs/.github/dependabot.yml +37 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +148 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +107 -0
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +122 -0
- package/lib/vendor/blamejs/.github/workflows/ci.yml +511 -0
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +50 -0
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +655 -0
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +406 -0
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +101 -0
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +134 -0
- package/lib/vendor/blamejs/.gitignore +102 -0
- package/lib/vendor/blamejs/.gitleaks.toml +166 -0
- package/lib/vendor/blamejs/.hadolint.yaml +18 -0
- package/lib/vendor/blamejs/.npmrc +5 -0
- package/lib/vendor/blamejs/.pinact.yaml +17 -0
- package/lib/vendor/blamejs/ARCHITECTURE.md +158 -0
- package/lib/vendor/blamejs/CHANGELOG.md +1351 -0
- package/lib/vendor/blamejs/CODE_OF_CONDUCT.md +86 -0
- package/lib/vendor/blamejs/CONTRIBUTING.md +156 -0
- package/lib/vendor/blamejs/GOVERNANCE.md +201 -0
- package/lib/vendor/blamejs/LICENSE +201 -0
- package/lib/vendor/blamejs/LTS-CALENDAR.md +29 -0
- package/lib/vendor/blamejs/MIGRATING.md +29 -0
- package/lib/vendor/blamejs/NOTICE +81 -0
- package/lib/vendor/blamejs/README.md +304 -0
- package/lib/vendor/blamejs/SECURITY.md +432 -0
- package/lib/vendor/blamejs/api-snapshot.json +48709 -0
- package/lib/vendor/blamejs/assets/BlameJS_Logo.png +0 -0
- package/lib/vendor/blamejs/assets/BlameJS_Logo.svg +129 -0
- package/lib/vendor/blamejs/bench/README.md +77 -0
- package/lib/vendor/blamejs/bench/_helpers.js +70 -0
- package/lib/vendor/blamejs/bench/baseline.json +183 -0
- package/lib/vendor/blamejs/bench/crypto-hash.bench.js +19 -0
- package/lib/vendor/blamejs/bench/crypto-symmetric.bench.js +28 -0
- package/lib/vendor/blamejs/bench/run.js +140 -0
- package/lib/vendor/blamejs/bench/safe-json.bench.js +31 -0
- package/lib/vendor/blamejs/bin/blamejs.js +13 -0
- package/lib/vendor/blamejs/docker/caddy/Caddyfile +46 -0
- package/lib/vendor/blamejs/docker/coredns/Corefile +37 -0
- package/lib/vendor/blamejs/docker/haproxy/haproxy.cfg +52 -0
- package/lib/vendor/blamejs/docker/init/generate-certs.sh +118 -0
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +87 -0
- package/lib/vendor/blamejs/docker/mitmproxy/config.yaml +16 -0
- package/lib/vendor/blamejs/docker/mongo/init-tls.sh +17 -0
- package/lib/vendor/blamejs/docker/mysql/my.cnf +12 -0
- package/lib/vendor/blamejs/docker/nats/nats.conf +33 -0
- package/lib/vendor/blamejs/docker/postgres/init-tls.sh +17 -0
- package/lib/vendor/blamejs/docker/postgres/postgresql.conf +18 -0
- package/lib/vendor/blamejs/docker/rabbitmq/rabbitmq.conf +18 -0
- package/lib/vendor/blamejs/docker/redis/redis.conf +15 -0
- package/lib/vendor/blamejs/docker/squid/squid.conf +24 -0
- package/lib/vendor/blamejs/docker/syslog/syslog-ng.conf +34 -0
- package/lib/vendor/blamejs/docker-compose.test.yml +545 -0
- package/lib/vendor/blamejs/docs/cis-postgres-crosswalk.md +102 -0
- package/lib/vendor/blamejs/docs/cis-sqlite-equivalent.md +92 -0
- package/lib/vendor/blamejs/eslint.config.mjs +204 -0
- package/lib/vendor/blamejs/examples/wiki/Caddyfile +40 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +218 -0
- package/lib/vendor/blamejs/examples/wiki/Dockerfile +120 -0
- package/lib/vendor/blamejs/examples/wiki/README.md +157 -0
- package/lib/vendor/blamejs/examples/wiki/cli-snapshot.json +250 -0
- package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +231 -0
- package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +166 -0
- package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +217 -0
- package/lib/vendor/blamejs/examples/wiki/lib/auto-site-entries.js +139 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +555 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-cli.js +507 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-env-vars.js +435 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-errors.js +282 -0
- package/lib/vendor/blamejs/examples/wiki/lib/harvest-vendored-deps.js +321 -0
- package/lib/vendor/blamejs/examples/wiki/lib/nav.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/lib/opts-resolver.js +75 -0
- package/lib/vendor/blamejs/examples/wiki/lib/page-generator.js +508 -0
- package/lib/vendor/blamejs/examples/wiki/lib/section.js +276 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +587 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-doc-parser.js +318 -0
- package/lib/vendor/blamejs/examples/wiki/lib/symbol-index.js +122 -0
- package/lib/vendor/blamejs/examples/wiki/migrations/0001-pages-schema.js +74 -0
- package/lib/vendor/blamejs/examples/wiki/package.json +18 -0
- package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.png +0 -0
- package/lib/vendor/blamejs/examples/wiki/public/img/blamejs-logo.svg +129 -0
- package/lib/vendor/blamejs/examples/wiki/public/robots.txt +5 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/MANIFEST.json +30 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.css +1 -0
- package/lib/vendor/blamejs/examples/wiki/public/vendor/prism.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/public/wiki.css +1250 -0
- package/lib/vendor/blamejs/examples/wiki/routes/admin.js +366 -0
- package/lib/vendor/blamejs/examples/wiki/routes/integration.js +230 -0
- package/lib/vendor/blamejs/examples/wiki/routes/pages.js +266 -0
- package/lib/vendor/blamejs/examples/wiki/scripts/backfill-module-metadata.js +214 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/0001-default-pages.js +35 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/_index.js +34 -0
- package/lib/vendor/blamejs/examples/wiki/seeders/prod/pages/api.js +76 -0
- package/lib/vendor/blamejs/examples/wiki/server.js +129 -0
- package/lib/vendor/blamejs/examples/wiki/site.config.js +197 -0
- package/lib/vendor/blamejs/examples/wiki/snippets/README.md +38 -0
- package/lib/vendor/blamejs/examples/wiki/snippets/auth/password-hash.example.js +15 -0
- package/lib/vendor/blamejs/examples/wiki/src/editor.js +103 -0
- package/lib/vendor/blamejs/examples/wiki/src/wiki.js +349 -0
- package/lib/vendor/blamejs/examples/wiki/test/AUDIT.md +155 -0
- package/lib/vendor/blamejs/examples/wiki/test/codebase-patterns.test.js +594 -0
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +741 -0
- package/lib/vendor/blamejs/examples/wiki/test/find-missing-pages.js +254 -0
- package/lib/vendor/blamejs/examples/wiki/test/integration.js +391 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-cli-snapshot.js +379 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-env-snapshot.js +346 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-nav-coverage.js +212 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-site-coverage.js +252 -0
- package/lib/vendor/blamejs/examples/wiki/test/validate-source-comment-blocks.js +107 -0
- package/lib/vendor/blamejs/examples/wiki/views/_layout.html +115 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/api-keys.html +51 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/dashboard.html +22 -0
- package/lib/vendor/blamejs/examples/wiki/views/admin/edit.html +17 -0
- package/lib/vendor/blamejs/examples/wiki/views/home.html +85 -0
- package/lib/vendor/blamejs/examples/wiki/views/login.html +18 -0
- package/lib/vendor/blamejs/examples/wiki/views/page.html +5 -0
- package/lib/vendor/blamejs/examples/wiki/views/partials/nav.html +13 -0
- package/lib/vendor/blamejs/examples/wiki/views/search.html +19 -0
- package/lib/vendor/blamejs/examples/wiki/wiki.config.js +15 -0
- package/lib/vendor/blamejs/fuzz/README.md +137 -0
- package/lib/vendor/blamejs/fuzz/_expected.js +35 -0
- package/lib/vendor/blamejs/fuzz/guard-agent-registry.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-csv.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/01-basic.csv +3 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/02-formula.csv +1 -0
- package/lib/vendor/blamejs/fuzz/guard-csv_seed_corpus/03-hyperlink.csv +1 -0
- package/lib/vendor/blamejs/fuzz/guard-dsn.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-email.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-email_seed_corpus/01-basic.eml +5 -0
- package/lib/vendor/blamejs/fuzz/guard-envelope.fuzz.js +24 -0
- package/lib/vendor/blamejs/fuzz/guard-event-bus-payload.fuzz.js +24 -0
- package/lib/vendor/blamejs/fuzz/guard-event-bus-topic.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-html.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/01-basic.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/02-script.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/03-event.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-html_seed_corpus/04-jsurl.html +1 -0
- package/lib/vendor/blamejs/fuzz/guard-idempotency-key.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-imap-command.fuzz.js +35 -0
- package/lib/vendor/blamejs/fuzz/guard-jmap.fuzz.js +41 -0
- package/lib/vendor/blamejs/fuzz/guard-json.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/01-basic.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/02-proto.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/03-dupkey.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/04-nan.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-json_seed_corpus/05-bom.json +1 -0
- package/lib/vendor/blamejs/fuzz/guard-list-id.fuzz.js +21 -0
- package/lib/vendor/blamejs/fuzz/guard-list-unsubscribe.fuzz.js +25 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-compose.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-move.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-query.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-reply.fuzz.js +23 -0
- package/lib/vendor/blamejs/fuzz/guard-mail-sieve.fuzz.js +36 -0
- package/lib/vendor/blamejs/fuzz/guard-managesieve-command.fuzz.js +26 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/01-basic.md +2 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/02-jsurl.md +1 -0
- package/lib/vendor/blamejs/fuzz/guard-markdown_seed_corpus/03-jsimg.md +1 -0
- package/lib/vendor/blamejs/fuzz/guard-message-id.fuzz.js +26 -0
- package/lib/vendor/blamejs/fuzz/guard-pop3-command.fuzz.js +23 -0
- package/lib/vendor/blamejs/fuzz/guard-posture-chain.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-saga-config.fuzz.js +32 -0
- package/lib/vendor/blamejs/fuzz/guard-smtp-command.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/guard-snapshot-envelope.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-stream-args.fuzz.js +22 -0
- package/lib/vendor/blamejs/fuzz/guard-svg.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/01-basic.svg +1 -0
- package/lib/vendor/blamejs/fuzz/guard-svg_seed_corpus/02-script.svg +1 -0
- package/lib/vendor/blamejs/fuzz/guard-tenant-id.fuzz.js +20 -0
- package/lib/vendor/blamejs/fuzz/guard-trace-context.fuzz.js +30 -0
- package/lib/vendor/blamejs/fuzz/guard-xml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/01-basic.xml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-xml_seed_corpus/02-xxe.xml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/01-basic.yaml +2 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/02-anchor.yaml +2 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/03-norway.yaml +1 -0
- package/lib/vendor/blamejs/fuzz/guard-yaml_seed_corpus/04-multidoc.yaml +4 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-ini.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-ini_seed_corpus/01-basic.ini +2 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-toml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-toml_seed_corpus/01-basic.toml +4 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-xml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-xml_seed_corpus/01-basic.xml +1 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-yaml.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/parsers__safe-yaml_seed_corpus/01-basic.yaml +4 -0
- package/lib/vendor/blamejs/fuzz/safe-decompress.fuzz.js +49 -0
- package/lib/vendor/blamejs/fuzz/safe-dns.fuzz.js +29 -0
- package/lib/vendor/blamejs/fuzz/safe-ical.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-icap.fuzz.js +42 -0
- package/lib/vendor/blamejs/fuzz/safe-json.fuzz.js +25 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/01-object.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/02-array.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/03-string.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/04-proto.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-json_seed_corpus/05-deep.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/01-basic.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/02-filter.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/03-deepscan.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-jsonpath_seed_corpus/04-slice.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-mime.fuzz.js +27 -0
- package/lib/vendor/blamejs/fuzz/safe-mount-info.fuzz.js +33 -0
- package/lib/vendor/blamejs/fuzz/safe-sieve.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/safe-smtp.fuzz.js +64 -0
- package/lib/vendor/blamejs/fuzz/safe-url.fuzz.js +16 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/01-basic.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/02-userinfo.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/03-dangerous.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/04-data.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/05-ipv6.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-url_seed_corpus/06-idn.txt +1 -0
- package/lib/vendor/blamejs/fuzz/safe-vcard.fuzz.js +16 -0
- package/lib/vendor/blamejs/index.js +678 -0
- package/lib/vendor/blamejs/keys/release-pqc-pub.json +7 -0
- package/lib/vendor/blamejs/lib/_test/crypto-fixtures.js +67 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +598 -0
- package/lib/vendor/blamejs/lib/a2a.js +407 -0
- package/lib/vendor/blamejs/lib/acme.js +1448 -0
- package/lib/vendor/blamejs/lib/agent-audit.js +45 -0
- package/lib/vendor/blamejs/lib/agent-event-bus.js +382 -0
- package/lib/vendor/blamejs/lib/agent-idempotency.js +497 -0
- package/lib/vendor/blamejs/lib/agent-orchestrator.js +717 -0
- package/lib/vendor/blamejs/lib/agent-posture-chain.js +366 -0
- package/lib/vendor/blamejs/lib/agent-saga.js +321 -0
- package/lib/vendor/blamejs/lib/agent-snapshot.js +676 -0
- package/lib/vendor/blamejs/lib/agent-stream.js +269 -0
- package/lib/vendor/blamejs/lib/agent-tenant.js +632 -0
- package/lib/vendor/blamejs/lib/agent-trace.js +281 -0
- package/lib/vendor/blamejs/lib/ai-adverse-decision.js +184 -0
- package/lib/vendor/blamejs/lib/ai-content-detect.js +268 -0
- package/lib/vendor/blamejs/lib/ai-input.js +201 -0
- package/lib/vendor/blamejs/lib/ai-model-manifest.js +363 -0
- package/lib/vendor/blamejs/lib/ai-pref.js +340 -0
- package/lib/vendor/blamejs/lib/api-key.js +721 -0
- package/lib/vendor/blamejs/lib/api-snapshot.js +458 -0
- package/lib/vendor/blamejs/lib/app-shutdown.js +557 -0
- package/lib/vendor/blamejs/lib/app.js +365 -0
- package/lib/vendor/blamejs/lib/archive.js +547 -0
- package/lib/vendor/blamejs/lib/arg-parser.js +697 -0
- package/lib/vendor/blamejs/lib/argon2-builtin.js +173 -0
- package/lib/vendor/blamejs/lib/asn1-der.js +424 -0
- package/lib/vendor/blamejs/lib/asyncapi-bindings.js +160 -0
- package/lib/vendor/blamejs/lib/asyncapi-traits.js +143 -0
- package/lib/vendor/blamejs/lib/asyncapi.js +575 -0
- package/lib/vendor/blamejs/lib/atomic-file.js +1023 -0
- package/lib/vendor/blamejs/lib/audit-chain.js +266 -0
- package/lib/vendor/blamejs/lib/audit-daily-review.js +389 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +751 -0
- package/lib/vendor/blamejs/lib/audit-tools.js +1113 -0
- package/lib/vendor/blamejs/lib/audit.js +1671 -0
- package/lib/vendor/blamejs/lib/auth/aal.js +169 -0
- package/lib/vendor/blamejs/lib/auth/access-lock.js +220 -0
- package/lib/vendor/blamejs/lib/auth/acr-vocabulary.js +265 -0
- package/lib/vendor/blamejs/lib/auth/ato-kill-switch.js +112 -0
- package/lib/vendor/blamejs/lib/auth/auth-time-tracker.js +111 -0
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +573 -0
- package/lib/vendor/blamejs/lib/auth/ciba.js +637 -0
- package/lib/vendor/blamejs/lib/auth/dpop.js +516 -0
- package/lib/vendor/blamejs/lib/auth/elevation-grant.js +306 -0
- package/lib/vendor/blamejs/lib/auth/fal.js +229 -0
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +681 -0
- package/lib/vendor/blamejs/lib/auth/jwt-external.js +519 -0
- package/lib/vendor/blamejs/lib/auth/jwt.js +430 -0
- package/lib/vendor/blamejs/lib/auth/lockout.js +449 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +2141 -0
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +657 -0
- package/lib/vendor/blamejs/lib/auth/oid4vp.js +531 -0
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +600 -0
- package/lib/vendor/blamejs/lib/auth/passkey.js +676 -0
- package/lib/vendor/blamejs/lib/auth/password.js +693 -0
- package/lib/vendor/blamejs/lib/auth/saml.js +2109 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-disclosure.js +95 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-holder.js +225 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc-issuer.js +197 -0
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +728 -0
- package/lib/vendor/blamejs/lib/auth/status-list.js +272 -0
- package/lib/vendor/blamejs/lib/auth/step-up-policy.js +335 -0
- package/lib/vendor/blamejs/lib/auth/step-up.js +454 -0
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +505 -0
- package/lib/vendor/blamejs/lib/auth-header.js +148 -0
- package/lib/vendor/blamejs/lib/backup/bundle.js +265 -0
- package/lib/vendor/blamejs/lib/backup/crypto.js +176 -0
- package/lib/vendor/blamejs/lib/backup/index.js +1001 -0
- package/lib/vendor/blamejs/lib/backup/manifest.js +443 -0
- package/lib/vendor/blamejs/lib/boot-gates.js +174 -0
- package/lib/vendor/blamejs/lib/breach-deadline.js +272 -0
- package/lib/vendor/blamejs/lib/break-glass.js +1753 -0
- package/lib/vendor/blamejs/lib/budr.js +205 -0
- package/lib/vendor/blamejs/lib/bundler.js +461 -0
- package/lib/vendor/blamejs/lib/cache-redis.js +256 -0
- package/lib/vendor/blamejs/lib/cache-status.js +288 -0
- package/lib/vendor/blamejs/lib/cache.js +1331 -0
- package/lib/vendor/blamejs/lib/calendar.js +1240 -0
- package/lib/vendor/blamejs/lib/canonical-json.js +143 -0
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +473 -0
- package/lib/vendor/blamejs/lib/cert.js +763 -0
- package/lib/vendor/blamejs/lib/chain-writer.js +259 -0
- package/lib/vendor/blamejs/lib/circuit-breaker.js +101 -0
- package/lib/vendor/blamejs/lib/cli-helpers.js +237 -0
- package/lib/vendor/blamejs/lib/cli.js +2328 -0
- package/lib/vendor/blamejs/lib/client-hints.js +318 -0
- package/lib/vendor/blamejs/lib/cloud-events.js +277 -0
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +317 -0
- package/lib/vendor/blamejs/lib/cluster-storage.js +351 -0
- package/lib/vendor/blamejs/lib/cluster.js +1017 -0
- package/lib/vendor/blamejs/lib/cms-codec.js +826 -0
- package/lib/vendor/blamejs/lib/codepoint-class.js +262 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-logging.js +190 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +205 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-risk.js +189 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +200 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +821 -0
- package/lib/vendor/blamejs/lib/compliance-eaa.js +204 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-aliases.js +167 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-fetcher.js +206 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions-fuzzy.js +297 -0
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +569 -0
- package/lib/vendor/blamejs/lib/compliance.js +1558 -0
- package/lib/vendor/blamejs/lib/config-drift.js +426 -0
- package/lib/vendor/blamejs/lib/config.js +446 -0
- package/lib/vendor/blamejs/lib/consent.js +369 -0
- package/lib/vendor/blamejs/lib/constants.js +209 -0
- package/lib/vendor/blamejs/lib/content-credentials.js +704 -0
- package/lib/vendor/blamejs/lib/cookies.js +560 -0
- package/lib/vendor/blamejs/lib/cra-report.js +299 -0
- package/lib/vendor/blamejs/lib/credential-hash.js +394 -0
- package/lib/vendor/blamejs/lib/crypto-field.js +1017 -0
- package/lib/vendor/blamejs/lib/crypto-hpke-pq.js +187 -0
- package/lib/vendor/blamejs/lib/crypto-hpke.js +256 -0
- package/lib/vendor/blamejs/lib/crypto.js +1908 -0
- package/lib/vendor/blamejs/lib/csp.js +271 -0
- package/lib/vendor/blamejs/lib/csv.js +418 -0
- package/lib/vendor/blamejs/lib/daemon.js +481 -0
- package/lib/vendor/blamejs/lib/dark-patterns.js +488 -0
- package/lib/vendor/blamejs/lib/data-act.js +328 -0
- package/lib/vendor/blamejs/lib/db-collection.js +587 -0
- package/lib/vendor/blamejs/lib/db-declare-row-policy.js +267 -0
- package/lib/vendor/blamejs/lib/db-declare-view.js +420 -0
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +333 -0
- package/lib/vendor/blamejs/lib/db-query.js +802 -0
- package/lib/vendor/blamejs/lib/db-role-context.js +50 -0
- package/lib/vendor/blamejs/lib/db-schema.js +322 -0
- package/lib/vendor/blamejs/lib/db.js +3111 -0
- package/lib/vendor/blamejs/lib/dbsc.js +299 -0
- package/lib/vendor/blamejs/lib/ddl-change-control.js +523 -0
- package/lib/vendor/blamejs/lib/deprecate.js +377 -0
- package/lib/vendor/blamejs/lib/dev.js +405 -0
- package/lib/vendor/blamejs/lib/dora.js +402 -0
- package/lib/vendor/blamejs/lib/dr-runbook.js +368 -0
- package/lib/vendor/blamejs/lib/dsr.js +1188 -0
- package/lib/vendor/blamejs/lib/dual-control.js +526 -0
- package/lib/vendor/blamejs/lib/early-hints.js +212 -0
- package/lib/vendor/blamejs/lib/error-page.js +420 -0
- package/lib/vendor/blamejs/lib/events.js +214 -0
- package/lib/vendor/blamejs/lib/external-db-migrate.js +659 -0
- package/lib/vendor/blamejs/lib/external-db.js +1877 -0
- package/lib/vendor/blamejs/lib/fapi2.js +394 -0
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +395 -0
- package/lib/vendor/blamejs/lib/fdx.js +370 -0
- package/lib/vendor/blamejs/lib/fedcm.js +264 -0
- package/lib/vendor/blamejs/lib/file-type.js +360 -0
- package/lib/vendor/blamejs/lib/file-upload.js +1256 -0
- package/lib/vendor/blamejs/lib/flag-cache.js +136 -0
- package/lib/vendor/blamejs/lib/flag-evaluation-context.js +135 -0
- package/lib/vendor/blamejs/lib/flag-providers.js +279 -0
- package/lib/vendor/blamejs/lib/flag-targeting.js +210 -0
- package/lib/vendor/blamejs/lib/flag.js +346 -0
- package/lib/vendor/blamejs/lib/forms.js +525 -0
- package/lib/vendor/blamejs/lib/framework-error.js +724 -0
- package/lib/vendor/blamejs/lib/framework-schema.js +845 -0
- package/lib/vendor/blamejs/lib/framework-sha1-hibp.js +34 -0
- package/lib/vendor/blamejs/lib/fsm.js +469 -0
- package/lib/vendor/blamejs/lib/gate-contract.js +1661 -0
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +261 -0
- package/lib/vendor/blamejs/lib/graphql-federation.js +234 -0
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +179 -0
- package/lib/vendor/blamejs/lib/guard-all.js +555 -0
- package/lib/vendor/blamejs/lib/guard-archive.js +901 -0
- package/lib/vendor/blamejs/lib/guard-auth.js +451 -0
- package/lib/vendor/blamejs/lib/guard-cidr.js +676 -0
- package/lib/vendor/blamejs/lib/guard-csv.js +1176 -0
- package/lib/vendor/blamejs/lib/guard-domain.js +814 -0
- package/lib/vendor/blamejs/lib/guard-dsn.js +382 -0
- package/lib/vendor/blamejs/lib/guard-email.js +951 -0
- package/lib/vendor/blamejs/lib/guard-envelope.js +294 -0
- package/lib/vendor/blamejs/lib/guard-event-bus-payload.js +217 -0
- package/lib/vendor/blamejs/lib/guard-event-bus-topic.js +150 -0
- package/lib/vendor/blamejs/lib/guard-filename.js +956 -0
- package/lib/vendor/blamejs/lib/guard-graphql.js +731 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-aria.js +164 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-forms.js +144 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-tables.js +154 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag-tagwalk.js +44 -0
- package/lib/vendor/blamejs/lib/guard-html-wcag.js +470 -0
- package/lib/vendor/blamejs/lib/guard-html.js +1209 -0
- package/lib/vendor/blamejs/lib/guard-idempotency-key.js +151 -0
- package/lib/vendor/blamejs/lib/guard-image.js +584 -0
- package/lib/vendor/blamejs/lib/guard-imap-command.js +337 -0
- package/lib/vendor/blamejs/lib/guard-jmap.js +321 -0
- package/lib/vendor/blamejs/lib/guard-json.js +935 -0
- package/lib/vendor/blamejs/lib/guard-jsonpath.js +512 -0
- package/lib/vendor/blamejs/lib/guard-jwt.js +772 -0
- package/lib/vendor/blamejs/lib/guard-list-id.js +318 -0
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +412 -0
- package/lib/vendor/blamejs/lib/guard-mail-compose.js +282 -0
- package/lib/vendor/blamejs/lib/guard-mail-move.js +202 -0
- package/lib/vendor/blamejs/lib/guard-mail-query.js +310 -0
- package/lib/vendor/blamejs/lib/guard-mail-reply.js +172 -0
- package/lib/vendor/blamejs/lib/guard-mail-sieve.js +207 -0
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +566 -0
- package/lib/vendor/blamejs/lib/guard-markdown.js +768 -0
- package/lib/vendor/blamejs/lib/guard-message-id.js +267 -0
- package/lib/vendor/blamejs/lib/guard-mime.js +609 -0
- package/lib/vendor/blamejs/lib/guard-oauth.js +650 -0
- package/lib/vendor/blamejs/lib/guard-pdf.js +569 -0
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +317 -0
- package/lib/vendor/blamejs/lib/guard-posture-chain.js +201 -0
- package/lib/vendor/blamejs/lib/guard-regex.js +632 -0
- package/lib/vendor/blamejs/lib/guard-saga-config.js +157 -0
- package/lib/vendor/blamejs/lib/guard-shell.js +522 -0
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +594 -0
- package/lib/vendor/blamejs/lib/guard-snapshot-envelope.js +168 -0
- package/lib/vendor/blamejs/lib/guard-stream-args.js +166 -0
- package/lib/vendor/blamejs/lib/guard-svg.js +1163 -0
- package/lib/vendor/blamejs/lib/guard-template.js +490 -0
- package/lib/vendor/blamejs/lib/guard-tenant-id.js +138 -0
- package/lib/vendor/blamejs/lib/guard-time.js +586 -0
- package/lib/vendor/blamejs/lib/guard-trace-context.js +172 -0
- package/lib/vendor/blamejs/lib/guard-uuid.js +548 -0
- package/lib/vendor/blamejs/lib/guard-xml.js +666 -0
- package/lib/vendor/blamejs/lib/guard-yaml.js +726 -0
- package/lib/vendor/blamejs/lib/hal.js +125 -0
- package/lib/vendor/blamejs/lib/handlers.js +350 -0
- package/lib/vendor/blamejs/lib/honeytoken.js +168 -0
- package/lib/vendor/blamejs/lib/html-balance.js +347 -0
- package/lib/vendor/blamejs/lib/http-client-cache.js +923 -0
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +519 -0
- package/lib/vendor/blamejs/lib/http-client.js +2152 -0
- package/lib/vendor/blamejs/lib/http-message-signature.js +589 -0
- package/lib/vendor/blamejs/lib/http2-teardown.js +34 -0
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +398 -0
- package/lib/vendor/blamejs/lib/i18n.js +931 -0
- package/lib/vendor/blamejs/lib/iab-mspa.js +257 -0
- package/lib/vendor/blamejs/lib/iab-tcf.js +461 -0
- package/lib/vendor/blamejs/lib/importmap-integrity.js +90 -0
- package/lib/vendor/blamejs/lib/inbox.js +435 -0
- package/lib/vendor/blamejs/lib/incident-report.js +314 -0
- package/lib/vendor/blamejs/lib/ip-utils.js +102 -0
- package/lib/vendor/blamejs/lib/jobs.js +185 -0
- package/lib/vendor/blamejs/lib/jose-jwe-experimental.js +228 -0
- package/lib/vendor/blamejs/lib/jsonapi.js +230 -0
- package/lib/vendor/blamejs/lib/keychain.js +865 -0
- package/lib/vendor/blamejs/lib/lazy-require.js +48 -0
- package/lib/vendor/blamejs/lib/legal-hold.js +374 -0
- package/lib/vendor/blamejs/lib/local-db-thin.js +321 -0
- package/lib/vendor/blamejs/lib/log-stream-cloudwatch.js +369 -0
- package/lib/vendor/blamejs/lib/log-stream-local.js +146 -0
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +410 -0
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +286 -0
- package/lib/vendor/blamejs/lib/log-stream-syslog.js +310 -0
- package/lib/vendor/blamejs/lib/log-stream-webhook.js +199 -0
- package/lib/vendor/blamejs/lib/log-stream.js +584 -0
- package/lib/vendor/blamejs/lib/log.js +625 -0
- package/lib/vendor/blamejs/lib/lro.js +200 -0
- package/lib/vendor/blamejs/lib/mail-agent.js +786 -0
- package/lib/vendor/blamejs/lib/mail-arc-sign.js +417 -0
- package/lib/vendor/blamejs/lib/mail-arf.js +343 -0
- package/lib/vendor/blamejs/lib/mail-auth.js +2144 -0
- package/lib/vendor/blamejs/lib/mail-bimi.js +1047 -0
- package/lib/vendor/blamejs/lib/mail-bounce.js +955 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +1286 -0
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +789 -0
- package/lib/vendor/blamejs/lib/mail-crypto.js +108 -0
- package/lib/vendor/blamejs/lib/mail-dav.js +1224 -0
- package/lib/vendor/blamejs/lib/mail-deploy.js +1119 -0
- package/lib/vendor/blamejs/lib/mail-dkim.js +1250 -0
- package/lib/vendor/blamejs/lib/mail-greylist.js +448 -0
- package/lib/vendor/blamejs/lib/mail-helo.js +473 -0
- package/lib/vendor/blamejs/lib/mail-journal.js +435 -0
- package/lib/vendor/blamejs/lib/mail-mdn.js +424 -0
- package/lib/vendor/blamejs/lib/mail-rbl.js +392 -0
- package/lib/vendor/blamejs/lib/mail-require-tls.js +198 -0
- package/lib/vendor/blamejs/lib/mail-scan.js +502 -0
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +629 -0
- package/lib/vendor/blamejs/lib/mail-server-imap.js +1858 -0
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +1565 -0
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +908 -0
- package/lib/vendor/blamejs/lib/mail-server-mx.js +969 -0
- package/lib/vendor/blamejs/lib/mail-server-pop3.js +915 -0
- package/lib/vendor/blamejs/lib/mail-server-rate-limit.js +315 -0
- package/lib/vendor/blamejs/lib/mail-server-registry.js +378 -0
- package/lib/vendor/blamejs/lib/mail-server-submission.js +1396 -0
- package/lib/vendor/blamejs/lib/mail-server-tls.js +445 -0
- package/lib/vendor/blamejs/lib/mail-sieve.js +557 -0
- package/lib/vendor/blamejs/lib/mail-spam-score.js +284 -0
- package/lib/vendor/blamejs/lib/mail-srs.js +248 -0
- package/lib/vendor/blamejs/lib/mail-store-fts.js +394 -0
- package/lib/vendor/blamejs/lib/mail-store.js +929 -0
- package/lib/vendor/blamejs/lib/mail-unsubscribe.js +400 -0
- package/lib/vendor/blamejs/lib/mail.js +1971 -0
- package/lib/vendor/blamejs/lib/mcp-tool-registry.js +473 -0
- package/lib/vendor/blamejs/lib/mcp.js +950 -0
- package/lib/vendor/blamejs/lib/metrics.js +1503 -0
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +177 -0
- package/lib/vendor/blamejs/lib/middleware/ai-act-disclosure.js +203 -0
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +981 -0
- package/lib/vendor/blamejs/lib/middleware/assetlinks.js +137 -0
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +171 -0
- package/lib/vendor/blamejs/lib/middleware/attach-user.js +220 -0
- package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +293 -0
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +1519 -0
- package/lib/vendor/blamejs/lib/middleware/bot-disclose.js +183 -0
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +217 -0
- package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +122 -0
- package/lib/vendor/blamejs/lib/middleware/compose-pipeline.js +355 -0
- package/lib/vendor/blamejs/lib/middleware/compression.js +489 -0
- package/lib/vendor/blamejs/lib/middleware/cookies.js +130 -0
- package/lib/vendor/blamejs/lib/middleware/cors.js +386 -0
- package/lib/vendor/blamejs/lib/middleware/csp-nonce.js +388 -0
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +167 -0
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +499 -0
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +243 -0
- package/lib/vendor/blamejs/lib/middleware/db-role-for.js +304 -0
- package/lib/vendor/blamejs/lib/middleware/dpop.js +402 -0
- package/lib/vendor/blamejs/lib/middleware/error-handler.js +69 -0
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +168 -0
- package/lib/vendor/blamejs/lib/middleware/flag-context.js +110 -0
- package/lib/vendor/blamejs/lib/middleware/gpc.js +153 -0
- package/lib/vendor/blamejs/lib/middleware/headers.js +242 -0
- package/lib/vendor/blamejs/lib/middleware/health.js +438 -0
- package/lib/vendor/blamejs/lib/middleware/host-allowlist.js +189 -0
- package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +964 -0
- package/lib/vendor/blamejs/lib/middleware/index.js +183 -0
- package/lib/vendor/blamejs/lib/middleware/nel.js +214 -0
- package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +237 -0
- package/lib/vendor/blamejs/lib/middleware/no-cache.js +106 -0
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +177 -0
- package/lib/vendor/blamejs/lib/middleware/protected-resource-metadata.js +277 -0
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +556 -0
- package/lib/vendor/blamejs/lib/middleware/request-id.js +79 -0
- package/lib/vendor/blamejs/lib/middleware/request-log.js +205 -0
- package/lib/vendor/blamejs/lib/middleware/require-aal.js +138 -0
- package/lib/vendor/blamejs/lib/middleware/require-auth.js +144 -0
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +290 -0
- package/lib/vendor/blamejs/lib/middleware/require-content-type.js +113 -0
- package/lib/vendor/blamejs/lib/middleware/require-methods.js +97 -0
- package/lib/vendor/blamejs/lib/middleware/require-mtls.js +212 -0
- package/lib/vendor/blamejs/lib/middleware/require-step-up.js +226 -0
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +375 -0
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +285 -0
- package/lib/vendor/blamejs/lib/middleware/security-txt.js +170 -0
- package/lib/vendor/blamejs/lib/middleware/span-http-server.js +280 -0
- package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +323 -0
- package/lib/vendor/blamejs/lib/middleware/sse.js +200 -0
- package/lib/vendor/blamejs/lib/middleware/trace-log-correlation.js +167 -0
- package/lib/vendor/blamejs/lib/middleware/trace-propagate.js +148 -0
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +749 -0
- package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +164 -0
- package/lib/vendor/blamejs/lib/migration-files.js +37 -0
- package/lib/vendor/blamejs/lib/migrations.js +385 -0
- package/lib/vendor/blamejs/lib/mime-parse.js +198 -0
- package/lib/vendor/blamejs/lib/money.js +699 -0
- package/lib/vendor/blamejs/lib/mtls-ca.js +572 -0
- package/lib/vendor/blamejs/lib/mtls-engine-default.js +501 -0
- package/lib/vendor/blamejs/lib/network-byte-quota.js +308 -0
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +533 -0
- package/lib/vendor/blamejs/lib/network-dns.js +1930 -0
- package/lib/vendor/blamejs/lib/network-heartbeat.js +425 -0
- package/lib/vendor/blamejs/lib/network-nts.js +574 -0
- package/lib/vendor/blamejs/lib/network-proxy.js +265 -0
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +836 -0
- package/lib/vendor/blamejs/lib/network-tls.js +3126 -0
- package/lib/vendor/blamejs/lib/network.js +346 -0
- package/lib/vendor/blamejs/lib/nis2-report.js +181 -0
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +293 -0
- package/lib/vendor/blamejs/lib/nonce-store.js +177 -0
- package/lib/vendor/blamejs/lib/notify.js +683 -0
- package/lib/vendor/blamejs/lib/ntp-check.js +458 -0
- package/lib/vendor/blamejs/lib/numeric-bounds.js +111 -0
- package/lib/vendor/blamejs/lib/numeric-checks.js +40 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob-bucket-ops.js +349 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +488 -0
- package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +351 -0
- package/lib/vendor/blamejs/lib/object-store/gcs.js +515 -0
- package/lib/vendor/blamejs/lib/object-store/http-put.js +153 -0
- package/lib/vendor/blamejs/lib/object-store/http-request.js +38 -0
- package/lib/vendor/blamejs/lib/object-store/index.js +197 -0
- package/lib/vendor/blamejs/lib/object-store/local.js +163 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +1133 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +957 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +420 -0
- package/lib/vendor/blamejs/lib/observability-tracer.js +395 -0
- package/lib/vendor/blamejs/lib/observability.js +720 -0
- package/lib/vendor/blamejs/lib/openapi-paths-builder.js +248 -0
- package/lib/vendor/blamejs/lib/openapi-schema-walk.js +192 -0
- package/lib/vendor/blamejs/lib/openapi-security.js +169 -0
- package/lib/vendor/blamejs/lib/openapi-yaml.js +154 -0
- package/lib/vendor/blamejs/lib/openapi.js +489 -0
- package/lib/vendor/blamejs/lib/otel-export.js +278 -0
- package/lib/vendor/blamejs/lib/outbox.js +547 -0
- package/lib/vendor/blamejs/lib/pagination.js +542 -0
- package/lib/vendor/blamejs/lib/parsers/index.js +91 -0
- package/lib/vendor/blamejs/lib/parsers/safe-env.js +642 -0
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +293 -0
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +784 -0
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +390 -0
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +1015 -0
- package/lib/vendor/blamejs/lib/permissions.js +793 -0
- package/lib/vendor/blamejs/lib/pick.js +105 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +351 -0
- package/lib/vendor/blamejs/lib/pqc-gate.js +279 -0
- package/lib/vendor/blamejs/lib/pqc-software.js +271 -0
- package/lib/vendor/blamejs/lib/problem-details.js +482 -0
- package/lib/vendor/blamejs/lib/process-spawn.js +196 -0
- package/lib/vendor/blamejs/lib/promise-pool.js +162 -0
- package/lib/vendor/blamejs/lib/protobuf-encoder.js +190 -0
- package/lib/vendor/blamejs/lib/protocol-dispatcher.js +161 -0
- package/lib/vendor/blamejs/lib/public-suffix.js +403 -0
- package/lib/vendor/blamejs/lib/pubsub-cluster.js +154 -0
- package/lib/vendor/blamejs/lib/pubsub-redis.js +167 -0
- package/lib/vendor/blamejs/lib/pubsub.js +463 -0
- package/lib/vendor/blamejs/lib/queue-local.js +476 -0
- package/lib/vendor/blamejs/lib/queue-redis.js +745 -0
- package/lib/vendor/blamejs/lib/queue-sqs.js +319 -0
- package/lib/vendor/blamejs/lib/queue.js +1016 -0
- package/lib/vendor/blamejs/lib/redact.js +1007 -0
- package/lib/vendor/blamejs/lib/redis-client.js +520 -0
- package/lib/vendor/blamejs/lib/render.js +285 -0
- package/lib/vendor/blamejs/lib/request-helpers.js +767 -0
- package/lib/vendor/blamejs/lib/resource-access-lock.js +116 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +340 -0
- package/lib/vendor/blamejs/lib/restore-rollback.js +365 -0
- package/lib/vendor/blamejs/lib/restore.js +409 -0
- package/lib/vendor/blamejs/lib/retention.js +640 -0
- package/lib/vendor/blamejs/lib/retry.js +523 -0
- package/lib/vendor/blamejs/lib/router.js +1289 -0
- package/lib/vendor/blamejs/lib/safe-async.js +1184 -0
- package/lib/vendor/blamejs/lib/safe-buffer.js +562 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +297 -0
- package/lib/vendor/blamejs/lib/safe-dns.js +665 -0
- package/lib/vendor/blamejs/lib/safe-ical.js +634 -0
- package/lib/vendor/blamejs/lib/safe-icap.js +502 -0
- package/lib/vendor/blamejs/lib/safe-json.js +946 -0
- package/lib/vendor/blamejs/lib/safe-jsonpath.js +285 -0
- package/lib/vendor/blamejs/lib/safe-mime.js +831 -0
- package/lib/vendor/blamejs/lib/safe-mount-info.js +306 -0
- package/lib/vendor/blamejs/lib/safe-path.js +254 -0
- package/lib/vendor/blamejs/lib/safe-redirect.js +106 -0
- package/lib/vendor/blamejs/lib/safe-schema.js +1810 -0
- package/lib/vendor/blamejs/lib/safe-sieve.js +684 -0
- package/lib/vendor/blamejs/lib/safe-smtp.js +185 -0
- package/lib/vendor/blamejs/lib/safe-sql.js +363 -0
- package/lib/vendor/blamejs/lib/safe-url.js +428 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +473 -0
- package/lib/vendor/blamejs/lib/sandbox-worker.js +135 -0
- package/lib/vendor/blamejs/lib/sandbox.js +358 -0
- package/lib/vendor/blamejs/lib/scheduler.js +827 -0
- package/lib/vendor/blamejs/lib/sd-notify.js +269 -0
- package/lib/vendor/blamejs/lib/sec-cyber.js +214 -0
- package/lib/vendor/blamejs/lib/security-assert.js +395 -0
- package/lib/vendor/blamejs/lib/seeders.js +620 -0
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +309 -0
- package/lib/vendor/blamejs/lib/self-update.js +804 -0
- package/lib/vendor/blamejs/lib/server-timing.js +174 -0
- package/lib/vendor/blamejs/lib/session-device-binding.js +431 -0
- package/lib/vendor/blamejs/lib/session-stores.js +138 -0
- package/lib/vendor/blamejs/lib/session.js +1162 -0
- package/lib/vendor/blamejs/lib/slug.js +381 -0
- package/lib/vendor/blamejs/lib/sse.js +349 -0
- package/lib/vendor/blamejs/lib/ssrf-guard.js +792 -0
- package/lib/vendor/blamejs/lib/standard-webhooks.js +183 -0
- package/lib/vendor/blamejs/lib/static.js +1249 -0
- package/lib/vendor/blamejs/lib/storage.js +1272 -0
- package/lib/vendor/blamejs/lib/stream-throttle.js +235 -0
- package/lib/vendor/blamejs/lib/structured-fields.js +244 -0
- package/lib/vendor/blamejs/lib/subject.js +667 -0
- package/lib/vendor/blamejs/lib/tcpa-10dlc.js +175 -0
- package/lib/vendor/blamejs/lib/template.js +931 -0
- package/lib/vendor/blamejs/lib/tenant-quota.js +545 -0
- package/lib/vendor/blamejs/lib/test-harness.js +275 -0
- package/lib/vendor/blamejs/lib/testing.js +1185 -0
- package/lib/vendor/blamejs/lib/time.js +578 -0
- package/lib/vendor/blamejs/lib/tls-exporter.js +239 -0
- package/lib/vendor/blamejs/lib/totp.js +318 -0
- package/lib/vendor/blamejs/lib/tracing.js +546 -0
- package/lib/vendor/blamejs/lib/uuid.js +207 -0
- package/lib/vendor/blamejs/lib/validate-opts.js +381 -0
- package/lib/vendor/blamejs/lib/vault/index.js +638 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +311 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-source.js +198 -0
- package/lib/vendor/blamejs/lib/vault/rotate.js +803 -0
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +471 -0
- package/lib/vendor/blamejs/lib/vault/wrap.js +296 -0
- package/lib/vendor/blamejs/lib/vault-aad.js +259 -0
- package/lib/vendor/blamejs/lib/vendor/.vendor-data-pubkey +4 -0
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +161 -0
- package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.data.js +68 -0
- package/lib/vendor/blamejs/lib/vendor/bimi-trust-anchors.pem +33 -0
- package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.data.js +1325 -0
- package/lib/vendor/blamejs/lib/vendor/common-passwords-top-10000.txt +10002 -0
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +9 -0
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +18 -0
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +181 -0
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +16382 -0
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5881 -0
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +328 -0
- package/lib/vendor/blamejs/lib/vendor/vendor-data-pubkey.js +16 -0
- package/lib/vendor/blamejs/lib/vendor-data.js +520 -0
- package/lib/vendor/blamejs/lib/vex.js +630 -0
- package/lib/vendor/blamejs/lib/watcher.js +608 -0
- package/lib/vendor/blamejs/lib/web-push-vapid.js +322 -0
- package/lib/vendor/blamejs/lib/webhook.js +977 -0
- package/lib/vendor/blamejs/lib/websocket-channels.js +327 -0
- package/lib/vendor/blamejs/lib/websocket.js +1561 -0
- package/lib/vendor/blamejs/lib/wiki-concepts.js +338 -0
- package/lib/vendor/blamejs/lib/worker-pool.js +464 -0
- package/lib/vendor/blamejs/lib/ws-client.js +978 -0
- package/lib/vendor/blamejs/lib/xml-c14n.js +506 -0
- package/lib/vendor/blamejs/memory/specs/node-26-map-getorinsert-migration.md +164 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +19 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/README.md +88 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/build.sh +26 -0
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/project.yaml +28 -0
- package/lib/vendor/blamejs/package.json +81 -0
- package/lib/vendor/blamejs/release-notes/v0.0.x.json +310 -0
- package/lib/vendor/blamejs/release-notes/v0.1.x.json +1798 -0
- package/lib/vendor/blamejs/release-notes/v0.10.x.json +1288 -0
- package/lib/vendor/blamejs/release-notes/v0.11.x.json +2551 -0
- package/lib/vendor/blamejs/release-notes/v0.12.0.json +64 -0
- package/lib/vendor/blamejs/release-notes/v0.12.1.json +32 -0
- package/lib/vendor/blamejs/release-notes/v0.12.2.json +45 -0
- package/lib/vendor/blamejs/release-notes/v0.2.x.json +706 -0
- package/lib/vendor/blamejs/release-notes/v0.3.x.json +786 -0
- package/lib/vendor/blamejs/release-notes/v0.4.x.json +588 -0
- package/lib/vendor/blamejs/release-notes/v0.5.x.json +390 -0
- package/lib/vendor/blamejs/release-notes/v0.6.x.json +1947 -0
- package/lib/vendor/blamejs/release-notes/v0.7.x.json +3811 -0
- package/lib/vendor/blamejs/release-notes/v0.8.x.json +3318 -0
- package/lib/vendor/blamejs/release-notes/v0.9.x.json +2257 -0
- package/lib/vendor/blamejs/scripts/build-vendored-sbom.js +325 -0
- package/lib/vendor/blamejs/scripts/check-api-snapshot.js +62 -0
- package/lib/vendor/blamejs/scripts/check-changelog-extract.js +108 -0
- package/lib/vendor/blamejs/scripts/check-pack-against-gitignore.js +83 -0
- package/lib/vendor/blamejs/scripts/check-services.js +483 -0
- package/lib/vendor/blamejs/scripts/check-vendor-currency.js +349 -0
- package/lib/vendor/blamejs/scripts/consolidate-release-notes.js +216 -0
- package/lib/vendor/blamejs/scripts/gen-migrating.js +275 -0
- package/lib/vendor/blamejs/scripts/generate-changelog-entry.js +577 -0
- package/lib/vendor/blamejs/scripts/generate-release-signing-key.js +79 -0
- package/lib/vendor/blamejs/scripts/publish-dep-confusion-placeholder.sh +101 -0
- package/lib/vendor/blamejs/scripts/refresh-api-snapshot.js +31 -0
- package/lib/vendor/blamejs/scripts/refresh-vendor-manifest.js +132 -0
- package/lib/vendor/blamejs/scripts/release.js +652 -0
- package/lib/vendor/blamejs/scripts/sha3-digest.js +62 -0
- package/lib/vendor/blamejs/scripts/sign-release-artifact.js +92 -0
- package/lib/vendor/blamejs/scripts/test-integration.js +181 -0
- package/lib/vendor/blamejs/scripts/test-wiki-integration.js +126 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +77 -0
- package/lib/vendor/blamejs/scripts/vendor-data-gen.js +186 -0
- package/lib/vendor/blamejs/scripts/vendor-data-keygen.js +101 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +278 -0
- package/lib/vendor/blamejs/test/00-primitives.js +19075 -0
- package/lib/vendor/blamejs/test/10-state.js +622 -0
- package/lib/vendor/blamejs/test/20-db.js +561 -0
- package/lib/vendor/blamejs/test/30-chain.js +2110 -0
- package/lib/vendor/blamejs/test/40-consumers.js +2453 -0
- package/lib/vendor/blamejs/test/50-integration.js +486 -0
- package/lib/vendor/blamejs/test/_helpers.js +10 -0
- package/lib/vendor/blamejs/test/_smoke-worker.js +69 -0
- package/lib/vendor/blamejs/test/fixtures/exploit-corpus/corpus.json +368 -0
- package/lib/vendor/blamejs/test/fixtures/http-client-stream-payload.txt +2 -0
- package/lib/vendor/blamejs/test/fixtures/worker-pool/echo.js +52 -0
- package/lib/vendor/blamejs/test/helpers/_codebase-shingle-worker.js +24 -0
- package/lib/vendor/blamejs/test/helpers/_codebase-shingle.js +203 -0
- package/lib/vendor/blamejs/test/helpers/_shape-match.js +513 -0
- package/lib/vendor/blamejs/test/helpers/check.js +36 -0
- package/lib/vendor/blamejs/test/helpers/cluster.js +70 -0
- package/lib/vendor/blamejs/test/helpers/db.js +143 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +207 -0
- package/lib/vendor/blamejs/test/helpers/fs-watch.js +101 -0
- package/lib/vendor/blamejs/test/helpers/http.js +14 -0
- package/lib/vendor/blamejs/test/helpers/index.js +93 -0
- package/lib/vendor/blamejs/test/helpers/json-round-trip.js +120 -0
- package/lib/vendor/blamejs/test/helpers/mocks.js +20 -0
- package/lib/vendor/blamejs/test/helpers/otel.js +13 -0
- package/lib/vendor/blamejs/test/helpers/services.js +380 -0
- package/lib/vendor/blamejs/test/helpers/wait.js +206 -0
- package/lib/vendor/blamejs/test/integration/cache.test.js +235 -0
- package/lib/vendor/blamejs/test/integration/cluster-provider-mysql.test.js +174 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +611 -0
- package/lib/vendor/blamejs/test/integration/http-client.test.js +129 -0
- package/lib/vendor/blamejs/test/integration/log-stream.test.js +219 -0
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +181 -0
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +152 -0
- package/lib/vendor/blamejs/test/integration/mail-smtp.test.js +161 -0
- package/lib/vendor/blamejs/test/integration/mtls-ca.test.js +289 -0
- package/lib/vendor/blamejs/test/integration/network-dns.test.js +123 -0
- package/lib/vendor/blamejs/test/integration/network-heartbeat.test.js +101 -0
- package/lib/vendor/blamejs/test/integration/ntp-check.test.js +89 -0
- package/lib/vendor/blamejs/test/integration/object-store-sigv4.test.js +403 -0
- package/lib/vendor/blamejs/test/integration/pqc-pkcs8-forward-compat.test.js +271 -0
- package/lib/vendor/blamejs/test/integration/pubsub.test.js +137 -0
- package/lib/vendor/blamejs/test/integration/queue-redis.test.js +352 -0
- package/lib/vendor/blamejs/test/integration/redis-client-tls.test.js +96 -0
- package/lib/vendor/blamejs/test/integration/ssrf-guard.test.js +98 -0
- package/lib/vendor/blamejs/test/integration/websocket-permessage-deflate.test.js +261 -0
- package/lib/vendor/blamejs/test/integration/ws-client-roundtrip.test.js +230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +211 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/access-lock.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +219 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-orchestrator.test.js +390 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-posture-chain.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +279 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +322 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-stream.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-tenant.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-trace.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-adverse-decision.test.js +44 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-content-detect.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-input.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-model-manifest.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-pref.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +1080 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +311 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-zip-stream.test.js +291 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +267 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asyncapi.test.js +929 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-conflict-path.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-cve-defensive.test.js +176 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-export-cadf.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-framework-namespaces.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-segregation.test.js +115 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-ml-dsa-65.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-use-store.test.js +246 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge-verifier.test.js +485 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +331 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +572 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password-audit.test.js +61 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-bucket-ops.test.js +258 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-worker.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bearer-auth.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-chunked-malformed.test.js +131 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-smuggling.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/boot-gates.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/breach-deadline.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +861 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/budr.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bundler-engine.test.js +209 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache-status.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +871 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/canonical-json-jcs.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cdn-cache-control.test.js +243 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-api-key.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-audit-verify-chain.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-backup.test.js +135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-config-drift.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-file-type.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-helpers.test.js +145 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-mtls.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-password.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-restore.test.js +160 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-retention.test.js +84 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-security.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-vault.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/client-hints.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +237 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +9600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-cascade.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-eaa.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +712 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/config-drift.test.js +97 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/config.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +357 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cra-report.test.js +31 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/credential-hash.test.js +226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-base64url.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-envelope.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +193 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke-pq.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hpke.test.js +155 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-mlkem768-x25519.test.js +129 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-namespace-hash.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-random-int.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-builder.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-nonce.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +210 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daily-byte-quota.test.js +153 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-collection-extensions.test.js +226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-collection.test.js +136 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-init-extensions.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-cross-schema.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query-extensions.test.js +191 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-role-for.test.js +228 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-vacuum.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-worm.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +184 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/declare-row-policy.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/declare-view.test.js +303 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dns-dnssec-algorithm.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dns-null-mx.test.js +39 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dr-runbook.test.js +59 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr-state-rules.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +786 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/early-hints.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/events.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/exploit-replay.test.js +243 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-hardening.test.js +181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-routing.test.js +531 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fapi2.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +156 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fdx.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +434 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +432 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-type.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +887 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forensic-snapshot.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fsm.test.js +375 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gcs-bucket-ops.test.js +321 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-agent-registry.test.js +87 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-all.test.js +328 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +339 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +694 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-dsn.test.js +296 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-email.test.js +234 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-envelope.test.js +192 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-payload.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-event-bus-topic.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +386 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html-wcag.test.js +859 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +357 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +92 -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-jmap.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +317 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-id.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-list-unsubscribe.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-compose.test.js +111 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-move.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-query.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-reply.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mail-sieve.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +301 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +265 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-message-id.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +161 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-posture-chain.test.js +100 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-saga-config.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-smtp-command.test.js +269 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-snapshot-envelope.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-stream-args.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +288 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-tenant-id.test.js +69 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-trace-context.test.js +102 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-xml.test.js +202 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-yaml.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/hal.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/honeytoken.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +692 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +280 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +225 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +203 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +991 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/iab-mspa.test.js +63 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/iab-tcf.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +612 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +56 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/inbox.test.js +166 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/incident-report.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jose-jwe-experimental.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-api.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-round-trip-helper.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +159 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +118 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/local-db-thin.test.js +150 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-cloudwatch.test.js +489 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp-grpc.test.js +207 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/lro.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +417 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-arf.test.js +208 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +910 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +502 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +680 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-canspam.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +297 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +514 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy-tlsrpt.test.js +369 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +627 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-feedback-id.test.js +56 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-greylist.test.js +217 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +217 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-mdn.test.js +334 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-rbl.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-require-tls.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +336 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +732 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +840 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +285 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +229 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +394 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-tls.test.js +147 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-spam-score.test.js +204 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-srs.test.js +152 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +279 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-unsubscribe.test.js +165 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +439 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-tool-registry.test.js +202 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +155 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-shadow-registry.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +224 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-compose-pipeline.test.js +278 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/money.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-paths.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nel.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-byte-quota.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +372 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +635 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-heartbeat-passive.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-build-options.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls-ct-inclusion.test.js +179 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +447 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +369 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nis2-report.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nist-crosswalk.test.js +42 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/no-cache.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/notify.test.js +707 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/numeric-bounds.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +597 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openapi.test.js +877 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otel-export.test.js +257 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pagination.test.js +522 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +216 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +324 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +546 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +153 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-software.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/problem-details.test.js +195 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/process-spawn.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/promise-pool.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protected-resource-metadata.test.js +68 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protobuf-encoder.test.js +138 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/protocol-dispatcher.test.js +174 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/public-suffix.test.js +197 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +232 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-dlq-extend-lease.test.js +178 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +322 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-priority-rate-progress.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-sqs.test.js +300 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-cluster.test.js +338 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-registry.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact-dlp.test.js +246 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redis-client.test.js +130 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +335 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-log.test.js +170 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-auth-cache-control.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-mtls.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/resource-access-lock.test.js +52 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-floor.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retry.test.js +535 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-cross-origin-redirect.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-loops.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async-parallel.test.js +170 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +248 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +451 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +289 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-icap.test.js +206 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-jsonpath.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +339 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mount-info.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +78 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sieve.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-smtp.test.js +95 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url-idn-homograph.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +257 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-slo.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +228 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler-exactly-once.test.js +238 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +700 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-notify.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sec-cyber.test.js +85 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +107 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-headers.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/seeders.test.js +816 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update-standalone-verifier.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/server-timing.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +247 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/shape-match.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +952 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-multipart-sse.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/slug.test.js +330 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/smtp-policy.test.js +233 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/source-comment-blocks.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/speculation-rules.test.js +319 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sse.test.js +148 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +283 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/standard-webhooks.test.js +67 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +266 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +487 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-chunk-scratch.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +773 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/stream-throttle.test.js +173 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/structured-fields.test.js +180 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tcpa-10dlc.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +571 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/test-harness.test.js +190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/testing-request.test.js +119 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/testing.test.js +522 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-exporter.test.js +168 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-ct.test.js +275 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-ocsp-verify.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-pinset-drift.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-preferred-groups.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tracing.test.js +280 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/uuid.test.js +93 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-aad.test.js +277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-seal-pem-file.test.js +252 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-data.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-manifest.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vex.test.js +661 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +308 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/web-push-vapid.test.js +144 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +674 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket-channels.test.js +360 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool.test.js +302 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +349 -0
- package/lib/vendor/blamejs/test/layer-1-state/api-key.test.js +717 -0
- package/lib/vendor/blamejs/test/layer-5-integration/bundler-output.test.js +444 -0
- package/lib/vendor/blamejs/test/layer-5-integration/guard-host-integration.test.js +597 -0
- package/lib/vendor/blamejs/test/layer-5-integration/security-chaos.test.js +308 -0
- package/lib/vendor/blamejs/test/smoke.js +431 -0
- package/lib/webhooks.js +305 -0
- package/package.json +43 -0
|
@@ -0,0 +1,1519 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* body-parser — request-body buffering + parsing middleware.
|
|
4
|
+
*
|
|
5
|
+
* Populates `req.body` for body-bearing methods (POST, PUT, PATCH,
|
|
6
|
+
* DELETE) based on the request's Content-Type. Five sub-parsers ship,
|
|
7
|
+
* each with its own size-cap, encoding handling, and pollution defense:
|
|
8
|
+
*
|
|
9
|
+
* application/json → req.body = parsed object
|
|
10
|
+
* (via safe-json — POISONED_KEYS
|
|
11
|
+
* stripped, depth + size caps)
|
|
12
|
+
* application/x-www-form-urlencoded → req.body = { field: value }
|
|
13
|
+
* text/plain → req.body = string
|
|
14
|
+
* application/octet-stream → req.body = Buffer (raw)
|
|
15
|
+
* multipart/form-data → req.body = { field: value }
|
|
16
|
+
* req.files = [{ field, filename,
|
|
17
|
+
* mimeType, path, size, hash }]
|
|
18
|
+
* req.filesRejected = [{ field,
|
|
19
|
+
* filename, mimeType, code, message }]
|
|
20
|
+
*
|
|
21
|
+
* Multipart parses incrementally — file parts stream to a tmp dir
|
|
22
|
+
* rather than buffering in memory. Per-file + total-request size caps
|
|
23
|
+
* enforced. Filename sanitization strips path components + traversal.
|
|
24
|
+
* Per-file SHA3-512 hash computed during streaming. Tmp files cleaned
|
|
25
|
+
* on response end (whether the handler returned or threw).
|
|
26
|
+
*
|
|
27
|
+
* var bp = b.middleware.bodyParser({
|
|
28
|
+
* json: {
|
|
29
|
+
* limit: b.constants.BYTES.mib(1),
|
|
30
|
+
* strict: true, // require the body to start with {/[
|
|
31
|
+
* parseHook: function (parsed) { ... return validatedShape; },
|
|
32
|
+
* },
|
|
33
|
+
* urlencoded: {
|
|
34
|
+
* limit: b.constants.BYTES.mib(1),
|
|
35
|
+
* arrayLimit: 100, // for ?tag=a&tag=b → tag: ["a","b"]
|
|
36
|
+
* },
|
|
37
|
+
* text: { limit: b.constants.BYTES.mib(1), charset: "utf-8" },
|
|
38
|
+
* raw: { limit: b.constants.BYTES.mib(10), contentTypes: ["application/octet-stream"] },
|
|
39
|
+
* multipart: {
|
|
40
|
+
* tmpDir: os.tmpdir(),
|
|
41
|
+
* fileSize: b.constants.BYTES.mib(10),
|
|
42
|
+
* totalSize: b.constants.BYTES.mib(50),
|
|
43
|
+
* fileCount: 20,
|
|
44
|
+
* fieldCount: 100,
|
|
45
|
+
* fieldSize: b.constants.BYTES.mib(1),
|
|
46
|
+
* mimeAllowlist: ["image/jpeg", "image/png", "application/pdf"], // null = any
|
|
47
|
+
*
|
|
48
|
+
* // Per-part predicate. Runs after sanitization + MIME checks but
|
|
49
|
+
* // BEFORE the tmp file opens. Rejected parts are SKIPPED — the body
|
|
50
|
+
* // bytes are consumed (we still must scan past them to find the
|
|
51
|
+
* // next boundary) but never written to disk; the part metadata
|
|
52
|
+
* // lands in req.filesRejected. Surviving files appear in req.files
|
|
53
|
+
* // as usual. Sync only — async filtering goes in the route handler.
|
|
54
|
+
* fileFilter: function (part) {
|
|
55
|
+
* // part = { field, filename, mimeType, partHeaders }
|
|
56
|
+
* // return true / undefined → accept
|
|
57
|
+
* // return false → reject silently (entry in req.filesRejected)
|
|
58
|
+
* // return { reject: true, code, message } → reject with custom info
|
|
59
|
+
* return part.field === "avatar" && part.mimeType.startsWith("image/");
|
|
60
|
+
* },
|
|
61
|
+
*
|
|
62
|
+
* // Per-field overrides. maxBytes overrides global fileSize for file
|
|
63
|
+
* // parts and fieldSize for text parts. mimeTypes overrides the
|
|
64
|
+
* // global mimeAllowlist for the named field; other fields still
|
|
65
|
+
* // use the global list.
|
|
66
|
+
* fields: {
|
|
67
|
+
* avatar: { maxBytes: b.constants.BYTES.mib(2), mimeTypes: ["image/jpeg", "image/png"] },
|
|
68
|
+
* document: { maxBytes: b.constants.BYTES.mib(25) },
|
|
69
|
+
* },
|
|
70
|
+
*
|
|
71
|
+
* // When wired, fileFilter rejections emit body-parser.multipart.file_rejected
|
|
72
|
+
* // on the audit chain with the field, filename, mime, and reason.
|
|
73
|
+
* audit: b.audit,
|
|
74
|
+
* },
|
|
75
|
+
* // Stash the raw bytes for webhook-signature paths that need to
|
|
76
|
+
* // verify the wire bytes rather than the parsed shape.
|
|
77
|
+
* keepRawBody: false,
|
|
78
|
+
* });
|
|
79
|
+
* router.use(bp);
|
|
80
|
+
*
|
|
81
|
+
* Set any sub-parser to `false` to disable it entirely (the body is
|
|
82
|
+
* left untouched for those Content-Types — operator handles them).
|
|
83
|
+
*
|
|
84
|
+
* Failure modes — all return responses, do NOT call next(err):
|
|
85
|
+
* 413 Payload Too Large size-cap exceeded (incl. multipart
|
|
86
|
+
* file/total/field caps)
|
|
87
|
+
* 415 Unsupported Media Type Content-Type doesn't match any enabled
|
|
88
|
+
* sub-parser AND the request has a body
|
|
89
|
+
* 400 Bad Request malformed JSON / multipart / urlencoded;
|
|
90
|
+
* filename traversal; MIME not on allowlist
|
|
91
|
+
*
|
|
92
|
+
* Security guarantees:
|
|
93
|
+
* - All parsers enforce size caps BEFORE buffering the full body, so
|
|
94
|
+
* a large body can't OOM the process.
|
|
95
|
+
* - JSON path goes through safe-json — POISONED_KEYS stripped, depth
|
|
96
|
+
* + size caps applied at parse, no prototype pollution downstream.
|
|
97
|
+
* - Urlencoded uses URLSearchParams with a key-count cap, refuses
|
|
98
|
+
* POISONED_KEYS as field names (returns 400).
|
|
99
|
+
* - Multipart filename: path components stripped (basename), traversal
|
|
100
|
+
* dots collapsed, control characters stripped, length capped at 255.
|
|
101
|
+
* Tmp file path is generated by the framework, never derived from
|
|
102
|
+
* the operator-supplied filename — so a malicious filename can't
|
|
103
|
+
* collide with a sensitive path.
|
|
104
|
+
* - Multipart parser refuses fields whose `name` is in POISONED_KEYS
|
|
105
|
+
* (consistent with the JSON path).
|
|
106
|
+
* - Tmp files set with mode 0o600, parent dir created with 0o700.
|
|
107
|
+
* - Cleanup on response end always fires (response close, finish, or
|
|
108
|
+
* error) so a crashing handler doesn't leak files.
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
var nodeFs = require("node:fs");
|
|
112
|
+
var os = require("node:os");
|
|
113
|
+
var nodePath = require("node:path");
|
|
114
|
+
var nodeCrypto = require("node:crypto");
|
|
115
|
+
var atomicFile = require("../atomic-file");
|
|
116
|
+
var bCrypto = require("../crypto");
|
|
117
|
+
var lazyRequire = require("../lazy-require");
|
|
118
|
+
var requestHelpers = require("../request-helpers");
|
|
119
|
+
var safeBuffer = require("../safe-buffer");
|
|
120
|
+
var safeJson = require("../safe-json");
|
|
121
|
+
var structuredFields = require("../structured-fields");
|
|
122
|
+
var validateOpts = require("../validate-opts");
|
|
123
|
+
var C = require("../constants");
|
|
124
|
+
var { defineClass } = require("../framework-error");
|
|
125
|
+
|
|
126
|
+
var audit = lazyRequire(function () { return require("../audit"); });
|
|
127
|
+
|
|
128
|
+
// Node's HTTP parser surfaces malformed chunked-transfer-encoding via a
|
|
129
|
+
// stable family of HPE_* codes. RFC 9112 §7.1 — when a server rejects a
|
|
130
|
+
// chunked decode the connection MUST close so a downstream proxy can't
|
|
131
|
+
// reuse the socket with the next request's body bytes still pending.
|
|
132
|
+
// HPE_INVALID_CHUNK_SIZE / HPE_CHUNK_EXTENSIONS_OVERFLOW (Node 24+) /
|
|
133
|
+
// HPE_INVALID_TRANSFER_ENCODING / HPE_INVALID_EOF_STATE (chunk truncated)
|
|
134
|
+
// all land here. The framework's Connection: close + audit emit closes
|
|
135
|
+
// the smuggling-adjacent socket-reuse path that bare 400-only handling
|
|
136
|
+
// leaves open.
|
|
137
|
+
var CHUNKED_MALFORMED_CODES = new Set([
|
|
138
|
+
"HPE_INVALID_CHUNK_SIZE",
|
|
139
|
+
"HPE_INVALID_TRANSFER_ENCODING",
|
|
140
|
+
"HPE_INVALID_EOF_STATE",
|
|
141
|
+
"HPE_INVALID_CONSTANT",
|
|
142
|
+
"HPE_CHUNK_EXTENSIONS_OVERFLOW",
|
|
143
|
+
"HPE_UNEXPECTED_CONTENT_LENGTH",
|
|
144
|
+
"ERR_HTTP_INVALID_CHUNK",
|
|
145
|
+
]);
|
|
146
|
+
function _isChunkedMalformed(e) {
|
|
147
|
+
if (!e) return false;
|
|
148
|
+
if (typeof e.code === "string" && CHUNKED_MALFORMED_CODES.has(e.code)) return true;
|
|
149
|
+
if (typeof e.code === "string" && e.code.indexOf("HPE_") === 0 &&
|
|
150
|
+
typeof e.message === "string" && /chunk/i.test(e.message)) return true;
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
var HTTP_STATUS = requestHelpers.HTTP_STATUS;
|
|
155
|
+
var BodyParserError = defineClass("BodyParserError", { withStatusCode: true });
|
|
156
|
+
|
|
157
|
+
// Mirrors safe-json.js + safe-schema.js. Field names that match these
|
|
158
|
+
// are refused at the parse boundary regardless of which sub-parser is
|
|
159
|
+
// in play — consistent prototype-pollution defense across the framework.
|
|
160
|
+
var POISONED_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
161
|
+
|
|
162
|
+
// ---- defaults ----
|
|
163
|
+
|
|
164
|
+
var DEFAULTS = Object.freeze({
|
|
165
|
+
json: {
|
|
166
|
+
limit: C.BYTES.mib(1),
|
|
167
|
+
strict: true,
|
|
168
|
+
contentTypes: ["application/json", "application/json; charset=utf-8"],
|
|
169
|
+
charset: "utf-8",
|
|
170
|
+
},
|
|
171
|
+
urlencoded: {
|
|
172
|
+
limit: C.BYTES.mib(1),
|
|
173
|
+
arrayLimit: 100,
|
|
174
|
+
contentTypes: ["application/x-www-form-urlencoded"],
|
|
175
|
+
charset: "utf-8",
|
|
176
|
+
},
|
|
177
|
+
text: {
|
|
178
|
+
limit: C.BYTES.mib(1),
|
|
179
|
+
charset: "utf-8",
|
|
180
|
+
contentTypes: ["text/plain"],
|
|
181
|
+
},
|
|
182
|
+
raw: {
|
|
183
|
+
limit: C.BYTES.mib(10),
|
|
184
|
+
contentTypes: ["application/octet-stream"],
|
|
185
|
+
},
|
|
186
|
+
multipart: {
|
|
187
|
+
tmpDir: null, // resolved per-instance from os.tmpdir()
|
|
188
|
+
fileSize: C.BYTES.mib(10),
|
|
189
|
+
totalSize: C.BYTES.mib(50),
|
|
190
|
+
fileCount: 20,
|
|
191
|
+
fieldCount: 100,
|
|
192
|
+
fieldSize: C.BYTES.mib(1),
|
|
193
|
+
mimeAllowlist: null,
|
|
194
|
+
fileFilter: null, // fn({ field, filename, mimeType, partHeaders }) → bool | { reject, code, message }
|
|
195
|
+
fields: null, // per-field overrides: { name: { maxBytes?, mimeTypes? } }
|
|
196
|
+
audit: null, // when wired, file-rejection emits an audit event
|
|
197
|
+
contentTypes: ["multipart/form-data"],
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
var BODY_BEARING_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
202
|
+
|
|
203
|
+
// Headroom on top of arrayLimit before declaring a key-bomb. Sized so a
|
|
204
|
+
// reasonable form (a few hundred fields with repeated names) fits without
|
|
205
|
+
// tripping the cap.
|
|
206
|
+
var URLENCODED_KEY_HEADROOM = C.BYTES.bytes(1000);
|
|
207
|
+
|
|
208
|
+
// ---- helpers ----
|
|
209
|
+
|
|
210
|
+
function _contentType(req) {
|
|
211
|
+
var ct = req.headers && req.headers["content-type"];
|
|
212
|
+
if (typeof ct !== "string") return { type: "", params: {} };
|
|
213
|
+
var idx = ct.indexOf(";");
|
|
214
|
+
var type = (idx === -1 ? ct : ct.slice(0, idx)).trim().toLowerCase();
|
|
215
|
+
var params = {};
|
|
216
|
+
if (idx !== -1) {
|
|
217
|
+
var rest = ct.slice(idx + 1);
|
|
218
|
+
// RFC 9110 §8.3 + §5.6.6 — parameter values may be quoted-string
|
|
219
|
+
// (e.g. `boundary="foo;bar"`, `charset="x;y"`). Bare `.split(";")`
|
|
220
|
+
// would slice through quoted commas/semicolons and corrupt the
|
|
221
|
+
// multipart boundary. Use the shared quote-aware splitter that
|
|
222
|
+
// tracks RFC 8941 §3.3.3 quoted-string state with backslash-escape.
|
|
223
|
+
var parts = structuredFields.splitTopLevel(rest, ";");
|
|
224
|
+
for (var i = 0; i < parts.length; i++) {
|
|
225
|
+
var p = parts[i].trim();
|
|
226
|
+
var eq = p.indexOf("=");
|
|
227
|
+
if (eq === -1) continue;
|
|
228
|
+
var k = p.slice(0, eq).trim().toLowerCase();
|
|
229
|
+
var v = p.slice(eq + 1).trim();
|
|
230
|
+
var _unq = structuredFields.unquoteSfString(v);
|
|
231
|
+
if (_unq !== null) v = _unq;
|
|
232
|
+
params[k] = v;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { type: type, params: params };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function _typeMatches(actual, allowed) {
|
|
239
|
+
for (var i = 0; i < allowed.length; i++) {
|
|
240
|
+
var a = allowed[i].toLowerCase();
|
|
241
|
+
// Match either exact type or "type/*" prefix
|
|
242
|
+
if (a === actual) return true;
|
|
243
|
+
var slash = a.indexOf("/");
|
|
244
|
+
if (slash !== -1 && a.slice(slash + 1) === "*" &&
|
|
245
|
+
actual.indexOf(a.slice(0, slash + 1)) === 0) return true;
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// RFC 9112 §6.1: Content-Length MUST be a sequence of decimal digits with
|
|
251
|
+
// no whitespace, sign, or trailing garbage. parseInt("123abc") returning
|
|
252
|
+
// 123 is the lenient parse that lets malformed headers slip past the
|
|
253
|
+
// preflight cap; the strict regex catches them at the boundary.
|
|
254
|
+
var STRICT_CONTENT_LENGTH = /^\d+$/;
|
|
255
|
+
|
|
256
|
+
function _parseContentLength(cl) {
|
|
257
|
+
if (typeof cl !== "string" || !STRICT_CONTENT_LENGTH.test(cl)) return null;
|
|
258
|
+
var n = Number(cl);
|
|
259
|
+
return isFinite(n) ? n : null;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function _hasBody(req) {
|
|
263
|
+
if (!BODY_BEARING_METHODS.has(req.method)) return false;
|
|
264
|
+
var cl = req.headers && req.headers["content-length"];
|
|
265
|
+
if (typeof cl === "string") {
|
|
266
|
+
var clNum = _parseContentLength(cl);
|
|
267
|
+
// Spec-shaped zero (the only RFC 9112 §6.1 zero) → no body. Malformed
|
|
268
|
+
// values (non-decimal-digits) flow through as "yes, has body" so the
|
|
269
|
+
// downstream _bufferBody call rejects with 400 — silently treating
|
|
270
|
+
// a malformed header as "no body" would let the request slip past
|
|
271
|
+
// the parser entirely.
|
|
272
|
+
if (clNum === 0) return false;
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
var te = req.headers && req.headers["transfer-encoding"];
|
|
276
|
+
if (typeof te === "string" && te.length > 0) return true;
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// HTTP request-smuggling defense per RFC 9112 §6.1 — covers the
|
|
281
|
+
// CVE-2022-31394 / CVE-2024-27316 / CL.TE / TE.CL / TE.TE class.
|
|
282
|
+
// Returns null on clean; { status, code, message } on smuggling-shaped
|
|
283
|
+
// request that the caller MUST reject with 400 + Connection: close.
|
|
284
|
+
function _detectSmuggling(req) {
|
|
285
|
+
var headers = req.headers || {};
|
|
286
|
+
var cl = headers["content-length"];
|
|
287
|
+
var te = headers["transfer-encoding"];
|
|
288
|
+
|
|
289
|
+
// 1. Both Content-Length AND Transfer-Encoding present — RFC 9112
|
|
290
|
+
// §6.1 says receiver MUST reject; the dual presence is the canonical
|
|
291
|
+
// CL.TE / TE.CL smuggling shape.
|
|
292
|
+
if (typeof cl === "string" && cl.length > 0 &&
|
|
293
|
+
typeof te === "string" && te.length > 0) {
|
|
294
|
+
return {
|
|
295
|
+
status: HTTP_STATUS.BAD_REQUEST, code: "smuggling/te-cl-conflict",
|
|
296
|
+
message: "request has both Content-Length and Transfer-Encoding " +
|
|
297
|
+
"headers (RFC 9112 §6.1 — request-smuggling vector)",
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 2. Multiple Content-Length values. Node's http parser collapses
|
|
302
|
+
// duplicate headers into a comma-separated string — `cl.indexOf(",")`
|
|
303
|
+
// catches it.
|
|
304
|
+
if (typeof cl === "string" && cl.indexOf(",") !== -1) {
|
|
305
|
+
return {
|
|
306
|
+
status: HTTP_STATUS.BAD_REQUEST, code: "smuggling/multiple-content-length",
|
|
307
|
+
message: "request has multiple Content-Length values (RFC 9112 §6.1)",
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 3. Transfer-Encoding present — final coding MUST be `chunked`
|
|
312
|
+
// (RFC 9112 §6.1). Anything else is a smuggling vector or
|
|
313
|
+
// server-side decode error.
|
|
314
|
+
if (typeof te === "string" && te.length > 0) {
|
|
315
|
+
var tokens = te.toLowerCase().split(",").map(function (t) { return t.trim(); }); // allow:bare-split-on-quoted-header — RFC 9112 §6.1 Transfer-Encoding values (chunked / gzip / deflate / identity) are token-only; no quoted-string in the grammar
|
|
316
|
+
var last = tokens[tokens.length - 1];
|
|
317
|
+
if (last !== "chunked") {
|
|
318
|
+
return {
|
|
319
|
+
status: HTTP_STATUS.BAD_REQUEST, code: "smuggling/te-not-chunked",
|
|
320
|
+
message: "request has Transfer-Encoding but final coding is not " +
|
|
321
|
+
"`chunked` (RFC 9112 §6.1 requires chunked be last)",
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
// 4. Duplicate `chunked` token (TE: chunked, chunked) — explicitly
|
|
325
|
+
// forbidden by RFC 9112 §6.1.
|
|
326
|
+
var chunkedCount = 0;
|
|
327
|
+
for (var i = 0; i < tokens.length; i += 1) {
|
|
328
|
+
if (tokens[i] === "chunked") chunkedCount += 1;
|
|
329
|
+
}
|
|
330
|
+
if (chunkedCount > 1) {
|
|
331
|
+
return {
|
|
332
|
+
status: HTTP_STATUS.BAD_REQUEST, code: "smuggling/duplicate-chunked",
|
|
333
|
+
message: "Transfer-Encoding lists `chunked` more than once " +
|
|
334
|
+
"(RFC 9112 §6.1 — TE.TE smuggling vector)",
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function _writeError(res, status, message, code) {
|
|
343
|
+
if (res.headersSent) return;
|
|
344
|
+
var body = JSON.stringify({ error: message, code: code });
|
|
345
|
+
res.writeHead(status, {
|
|
346
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
347
|
+
"Content-Length": Buffer.byteLength(body),
|
|
348
|
+
});
|
|
349
|
+
res.end(body);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Buffer the raw body up to `limit`. If Content-Length is known and
|
|
353
|
+
// exceeds limit, reject IMMEDIATELY without reading any bytes.
|
|
354
|
+
function _bufferBody(req, limit) {
|
|
355
|
+
return new Promise(function (resolve, reject) {
|
|
356
|
+
var cl = req.headers && req.headers["content-length"];
|
|
357
|
+
if (typeof cl === "string") {
|
|
358
|
+
var clNum = _parseContentLength(cl);
|
|
359
|
+
if (clNum === null) {
|
|
360
|
+
// RFC 9112 §6.1 — malformed Content-Length is a 400.
|
|
361
|
+
reject(new BodyParserError(
|
|
362
|
+
"body-parser/bad-content-length",
|
|
363
|
+
"Content-Length is not a sequence of decimal digits: " + JSON.stringify(cl),
|
|
364
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
365
|
+
));
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (clNum > limit) {
|
|
369
|
+
reject(new BodyParserError(
|
|
370
|
+
"body-parser/too-large",
|
|
371
|
+
"request body exceeds limit (" + clNum + " > " + limit + ")",
|
|
372
|
+
true, HTTP_STATUS.PAYLOAD_TOO_LARGE
|
|
373
|
+
));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
var collector = safeBuffer.boundedChunkCollector({
|
|
378
|
+
maxBytes: limit,
|
|
379
|
+
errorClass: BodyParserError,
|
|
380
|
+
sizeCode: "body-parser/too-large",
|
|
381
|
+
sizeMessage: "request body exceeds limit",
|
|
382
|
+
});
|
|
383
|
+
var done = false;
|
|
384
|
+
req.on("data", function (chunk) {
|
|
385
|
+
if (done) return;
|
|
386
|
+
try { collector.push(chunk); }
|
|
387
|
+
catch (e) {
|
|
388
|
+
done = true;
|
|
389
|
+
try { req.destroy(); } catch (_e) { /* socket already closed */ }
|
|
390
|
+
if (e && e.isBodyParserError) e.statusCode = HTTP_STATUS.PAYLOAD_TOO_LARGE;
|
|
391
|
+
reject(e);
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
req.on("end", function () { if (!done) { done = true; resolve(collector.result()); } });
|
|
396
|
+
req.on("error", function (e) { if (!done) { done = true; reject(e); } });
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ---- JSON parser ----
|
|
401
|
+
|
|
402
|
+
async function _parseJson(req, opts) {
|
|
403
|
+
var buf = await _bufferBody(req, opts.limit);
|
|
404
|
+
if (buf.length === 0) return undefined;
|
|
405
|
+
var text = buf.toString(opts.charset);
|
|
406
|
+
if (opts.strict) {
|
|
407
|
+
var head = text.replace(/^[\s\u00A0\uFEFF]+/, "")[0];
|
|
408
|
+
if (head !== "{" && head !== "[") {
|
|
409
|
+
throw new BodyParserError(
|
|
410
|
+
"body-parser/json-strict",
|
|
411
|
+
"JSON body must start with '{' or '[' (strict mode)",
|
|
412
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
var parsed;
|
|
417
|
+
try {
|
|
418
|
+
// safe-json strips POISONED_KEYS and enforces depth + byte caps.
|
|
419
|
+
parsed = safeJson.parse(text, { maxBytes: opts.limit });
|
|
420
|
+
} catch (e) {
|
|
421
|
+
throw new BodyParserError(
|
|
422
|
+
"body-parser/json-malformed",
|
|
423
|
+
"JSON parse failed: " + ((e && e.message) || String(e)),
|
|
424
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
if (typeof opts.parseHook === "function") {
|
|
428
|
+
try { parsed = opts.parseHook(parsed); }
|
|
429
|
+
catch (e) {
|
|
430
|
+
throw new BodyParserError(
|
|
431
|
+
"body-parser/json-hook",
|
|
432
|
+
"JSON parseHook failed: " + ((e && e.message) || String(e)),
|
|
433
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return parsed;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ---- urlencoded parser ----
|
|
441
|
+
|
|
442
|
+
async function _parseUrlencoded(req, opts) {
|
|
443
|
+
var buf = await _bufferBody(req, opts.limit);
|
|
444
|
+
if (buf.length === 0) return {};
|
|
445
|
+
var text = buf.toString(opts.charset);
|
|
446
|
+
var sp;
|
|
447
|
+
try { sp = new URLSearchParams(text); }
|
|
448
|
+
catch (e) {
|
|
449
|
+
throw new BodyParserError(
|
|
450
|
+
"body-parser/urlencoded-malformed",
|
|
451
|
+
"urlencoded parse failed: " + ((e && e.message) || String(e)),
|
|
452
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
var out = {};
|
|
456
|
+
var keyCount = 0;
|
|
457
|
+
// Track repeated keys so [a=1, a=2] becomes a: ["1","2"] rather than overwriting.
|
|
458
|
+
var seen = Object.create(null);
|
|
459
|
+
var keys = [];
|
|
460
|
+
sp.forEach(function (value, key) { keys.push([key, value]); });
|
|
461
|
+
for (var i = 0; i < keys.length; i++) {
|
|
462
|
+
var k = keys[i][0];
|
|
463
|
+
var v = keys[i][1];
|
|
464
|
+
if (POISONED_KEYS.has(k)) {
|
|
465
|
+
throw new BodyParserError(
|
|
466
|
+
"body-parser/urlencoded-poisoned-key",
|
|
467
|
+
"urlencoded body contains forbidden key '" + k + "' (prototype-pollution defense)",
|
|
468
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
keyCount++;
|
|
472
|
+
if (keyCount > opts.arrayLimit + URLENCODED_KEY_HEADROOM) { // soft cap on total keys
|
|
473
|
+
throw new BodyParserError(
|
|
474
|
+
"body-parser/urlencoded-too-many-fields",
|
|
475
|
+
"urlencoded body has too many fields",
|
|
476
|
+
true, 413
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
if (Object.prototype.hasOwnProperty.call(seen, k)) {
|
|
480
|
+
if (Array.isArray(out[k])) {
|
|
481
|
+
if (out[k].length >= opts.arrayLimit) {
|
|
482
|
+
throw new BodyParserError(
|
|
483
|
+
"body-parser/urlencoded-array-too-large",
|
|
484
|
+
"urlencoded array '" + k + "' exceeds arrayLimit (" + opts.arrayLimit + ")",
|
|
485
|
+
true, 413
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
out[k].push(v);
|
|
489
|
+
} else {
|
|
490
|
+
out[k] = [out[k], v];
|
|
491
|
+
}
|
|
492
|
+
} else {
|
|
493
|
+
out[k] = v;
|
|
494
|
+
seen[k] = true;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return out;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// ---- text parser ----
|
|
501
|
+
|
|
502
|
+
async function _parseText(req, opts) {
|
|
503
|
+
var buf = await _bufferBody(req, opts.limit);
|
|
504
|
+
return buf.toString(opts.charset);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// ---- raw parser ----
|
|
508
|
+
|
|
509
|
+
async function _parseRaw(req, opts) {
|
|
510
|
+
return await _bufferBody(req, opts.limit);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// ---- multipart parser ----
|
|
514
|
+
//
|
|
515
|
+
// Streaming RFC 7578 multipart/form-data parser. Walks an incoming
|
|
516
|
+
// request stream byte-by-byte (well, chunk-by-chunk with a sliding
|
|
517
|
+
// look-ahead window) and emits parts as they're encountered. File
|
|
518
|
+
// parts stream straight to disk; field parts buffer in memory up to
|
|
519
|
+
// fieldSize.
|
|
520
|
+
//
|
|
521
|
+
// State machine:
|
|
522
|
+
// INITIAL skip preamble until first boundary
|
|
523
|
+
// AFTER_BD just consumed a boundary; check next two bytes for
|
|
524
|
+
// "--" (end-of-multipart) or "\r\n" (next part)
|
|
525
|
+
// HEADERS reading per-part headers until \r\n\r\n
|
|
526
|
+
// BODY streaming part body; watch for \r\n--<boundary>
|
|
527
|
+
// DONE all parts read
|
|
528
|
+
|
|
529
|
+
var MP_INITIAL = 0;
|
|
530
|
+
var MP_AFTER_BD = 1;
|
|
531
|
+
var MP_HEADERS = 2;
|
|
532
|
+
var MP_BODY = 3;
|
|
533
|
+
var MP_DONE = 4;
|
|
534
|
+
|
|
535
|
+
function _sanitizeFilename(name) {
|
|
536
|
+
if (typeof name !== "string") return null;
|
|
537
|
+
// Strip every path component — keep only basename (last segment).
|
|
538
|
+
// Both POSIX and Windows separators handled, plus URL-encoded.
|
|
539
|
+
var s = name.replace(/\\/g, "/");
|
|
540
|
+
var idx = s.lastIndexOf("/");
|
|
541
|
+
if (idx !== -1) s = s.slice(idx + 1);
|
|
542
|
+
// Drop control characters, NUL, leading/trailing dots.
|
|
543
|
+
s = s.replace(/\p{Cc}/gu, "");
|
|
544
|
+
// Trojan Source CVE-2021-42574 class — strip BiDi formatting +
|
|
545
|
+
// zero-width codepoints from the filename. An attacker uploading
|
|
546
|
+
// `Photo01Bygpj.SCR` displays as `Photo01By.jpg` in audit
|
|
547
|
+
// logs while the OS opens `.SCR`. Universal-refuse on these
|
|
548
|
+
// codepoints; operators with legitimate need pass the raw filename
|
|
549
|
+
// through `b.guardFilename` with explicit BiDi opt-in.
|
|
550
|
+
// BiDi formatting (U+202A..U+202E, U+2066..U+2069), zero-width
|
|
551
|
+
// (U+200B..U+200D, U+2060), BOM (U+FEFF) — Unicode escapes so the
|
|
552
|
+
// regex itself contains no irregular whitespace.
|
|
553
|
+
s = s.replace(/[\u202A-\u202E\u2066-\u2069\u200B-\u200D\u2060\uFEFF]/g, "");
|
|
554
|
+
s = s.replace(/^\.+/, "").replace(/\.+$/, "");
|
|
555
|
+
if (s.length === 0) return null;
|
|
556
|
+
if (s.length > 255) s = s.slice(0, 255);
|
|
557
|
+
// Refuse any remaining traversal artifact.
|
|
558
|
+
if (s === "." || s === "..") return null;
|
|
559
|
+
return s;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function _parseMultipartHeaders(rawHeaders) {
|
|
563
|
+
// Each line is `Header-Name: value`. Common headers: Content-Disposition,
|
|
564
|
+
// Content-Type, Content-Transfer-Encoding. Unknown headers are ignored.
|
|
565
|
+
// RFC 9112 §5.2 — line folding (obs-fold) is OBSOLETE in HTTP messages;
|
|
566
|
+
// a continuation line beginning with SP/HTAB MUST be refused. RFC 9110
|
|
567
|
+
// §5.5 — header field values MUST NOT contain CR, LF, or NUL bytes.
|
|
568
|
+
// We refuse the part outright (caller surfaces the throw as 400 + drop).
|
|
569
|
+
var lines = rawHeaders.split("\r\n");
|
|
570
|
+
var out = {};
|
|
571
|
+
for (var i = 0; i < lines.length; i++) {
|
|
572
|
+
var line = lines[i];
|
|
573
|
+
if (!line) continue;
|
|
574
|
+
var first = line.charCodeAt(0);
|
|
575
|
+
if (first === 32 || first === 9) { // allow:raw-byte-literal — SP/HTAB obs-fold sentinels
|
|
576
|
+
throw new BodyParserError(
|
|
577
|
+
"body-parser/multipart-obs-fold",
|
|
578
|
+
"multipart part header uses obsolete line folding (RFC 9112 §5.2)",
|
|
579
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
var idx = line.indexOf(":");
|
|
583
|
+
if (idx === -1) continue;
|
|
584
|
+
var k = line.slice(0, idx).trim().toLowerCase();
|
|
585
|
+
var v = line.slice(idx + 1).trim();
|
|
586
|
+
for (var j = 0; j < v.length; j++) {
|
|
587
|
+
var c = v.charCodeAt(j);
|
|
588
|
+
if (c === 0 || c === 10 || c === 13) { // allow:raw-byte-literal — NUL/LF/CR forbidden in field-value (RFC 9110 §5.5)
|
|
589
|
+
throw new BodyParserError(
|
|
590
|
+
"body-parser/multipart-bad-header-value",
|
|
591
|
+
"multipart part header `" + k + "` contains CR/LF/NUL (RFC 9110 §5.5)",
|
|
592
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
out[k] = v;
|
|
597
|
+
}
|
|
598
|
+
return out;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// RFC 5987 / 8187 — `filename*=UTF-8''percent%20encoded.txt` extended
|
|
602
|
+
// parameter form for non-ASCII filenames. Charset MUST be `UTF-8`
|
|
603
|
+
// (case-insensitive); we refuse other charsets to keep the decode
|
|
604
|
+
// path single-encoding. Language tag (between the two `'`s) is
|
|
605
|
+
// permitted but ignored.
|
|
606
|
+
function _decodeRfc5987(raw) {
|
|
607
|
+
if (typeof raw !== "string") return null;
|
|
608
|
+
var firstTick = raw.indexOf("'");
|
|
609
|
+
if (firstTick === -1) return null;
|
|
610
|
+
var secondTick = raw.indexOf("'", firstTick + 1);
|
|
611
|
+
if (secondTick === -1) return null;
|
|
612
|
+
var charset = raw.slice(0, firstTick).toLowerCase();
|
|
613
|
+
if (charset !== "utf-8") return null; // RFC 5987 mandated charset; refuse anything else
|
|
614
|
+
var encoded = raw.slice(secondTick + 1);
|
|
615
|
+
try {
|
|
616
|
+
return decodeURIComponent(encoded);
|
|
617
|
+
} catch (_e) {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function _parseHeaderParams(headerValue) {
|
|
623
|
+
// Content-Disposition: form-data; name="field"; filename="x.txt"
|
|
624
|
+
// Returns { _value: "form-data", name: "field", filename: "x.txt" }
|
|
625
|
+
// RFC 5987 / 8187 — when a `filename*=UTF-8''...` extended parameter
|
|
626
|
+
// is present, it takes precedence over the legacy `filename=`
|
|
627
|
+
// companion (RFC 6266 §4.3). We surface the decoded value at
|
|
628
|
+
// `filename` so downstream consumers don't need parser-aware code.
|
|
629
|
+
var out = { _value: "" };
|
|
630
|
+
if (!headerValue) return out;
|
|
631
|
+
// RFC 6266 §4.1 + RFC 9110 §5.6.6 — parameter values may be
|
|
632
|
+
// quoted-string (e.g. `filename="weird;name.txt"`). Bare
|
|
633
|
+
// `.split(";")` would slice through the quoted semicolon and
|
|
634
|
+
// corrupt the filename. Quote-aware shared splitter.
|
|
635
|
+
var parts = structuredFields.splitTopLevel(headerValue, ";");
|
|
636
|
+
out._value = parts[0].trim().toLowerCase();
|
|
637
|
+
var extName = null;
|
|
638
|
+
for (var i = 1; i < parts.length; i++) {
|
|
639
|
+
var p = parts[i].trim();
|
|
640
|
+
var eq = p.indexOf("=");
|
|
641
|
+
if (eq === -1) continue;
|
|
642
|
+
var k = p.slice(0, eq).trim().toLowerCase();
|
|
643
|
+
var v = p.slice(eq + 1).trim();
|
|
644
|
+
var _unq = structuredFields.unquoteSfString(v);
|
|
645
|
+
if (_unq !== null) v = _unq;
|
|
646
|
+
if (k.charAt(k.length - 1) === "*") {
|
|
647
|
+
var decoded = _decodeRfc5987(v);
|
|
648
|
+
if (decoded !== null) {
|
|
649
|
+
var bareKey = k.slice(0, -1);
|
|
650
|
+
if (bareKey === "filename") extName = decoded;
|
|
651
|
+
out[bareKey] = decoded;
|
|
652
|
+
}
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
out[k] = v;
|
|
656
|
+
}
|
|
657
|
+
if (extName !== null) out.filename = extName;
|
|
658
|
+
return out;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
async function _parseMultipart(req, opts, ctParams) {
|
|
662
|
+
var boundary = ctParams.boundary;
|
|
663
|
+
if (typeof boundary !== "string" || boundary.length === 0) {
|
|
664
|
+
throw new BodyParserError(
|
|
665
|
+
"body-parser/multipart-no-boundary",
|
|
666
|
+
"multipart Content-Type missing boundary parameter",
|
|
667
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
// RFC 2046 §5.1.1 — boundary length 1-70 chars, bcharsnospace
|
|
671
|
+
// grammar. Pathological boundaries (zero-length / very long /
|
|
672
|
+
// newlines) drive quadratic match cost in scanners. Refuse at
|
|
673
|
+
// the parse boundary so the rest of the engine doesn't have to
|
|
674
|
+
// defend against them.
|
|
675
|
+
if (boundary.length > 70 || // allow:raw-byte-literal — RFC 2046 §5.1.1 boundary length cap
|
|
676
|
+
!/^[A-Za-z0-9'()+_,\-./:=?]{1,70}$/.test(boundary)) { // allow:raw-byte-literal — RFC 2046 §5.1.1 bchars + cap
|
|
677
|
+
throw new BodyParserError(
|
|
678
|
+
"body-parser/multipart-bad-boundary",
|
|
679
|
+
"multipart boundary violates RFC 2046 §5.1.1 (1-70 chars, bcharsnospace grammar)",
|
|
680
|
+
true, HTTP_STATUS.BAD_REQUEST
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
// Resolve tmpDir per-request so directory-creation failure surfaces as a
|
|
684
|
+
// structured error rather than a deferred fs throw.
|
|
685
|
+
var tmpDir = opts.tmpDir || nodePath.join(os.tmpdir(), "blamejs-uploads");
|
|
686
|
+
try { atomicFile.ensureDir(tmpDir, 0o700); }
|
|
687
|
+
catch (e) {
|
|
688
|
+
throw new BodyParserError(
|
|
689
|
+
"body-parser/multipart-tmpdir",
|
|
690
|
+
"could not create multipart tmp dir '" + tmpDir + "': " + ((e && e.message) || String(e)),
|
|
691
|
+
true, 500
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
var boundaryBuf = Buffer.from("--" + boundary);
|
|
696
|
+
var boundaryDelimBuf = Buffer.from("\r\n--" + boundary);
|
|
697
|
+
|
|
698
|
+
var fields = {};
|
|
699
|
+
var files = [];
|
|
700
|
+
var filesRejected = [];
|
|
701
|
+
var totalRead = 0;
|
|
702
|
+
var fileCount = 0;
|
|
703
|
+
var fieldCount = 0;
|
|
704
|
+
var fileSize = opts.fileSize;
|
|
705
|
+
var totalSize = opts.totalSize;
|
|
706
|
+
var fileLimit = opts.fileCount;
|
|
707
|
+
var fieldLimit = opts.fieldCount;
|
|
708
|
+
var fieldSize = opts.fieldSize;
|
|
709
|
+
var mimeAllowlist = Array.isArray(opts.mimeAllowlist) ? opts.mimeAllowlist : null;
|
|
710
|
+
var fileFilter = typeof opts.fileFilter === "function" ? opts.fileFilter : null;
|
|
711
|
+
var perField = (opts.fields && typeof opts.fields === "object") ? opts.fields : null;
|
|
712
|
+
var auditInst = (opts.audit && typeof opts.audit.safeEmit === "function") ? opts.audit : null;
|
|
713
|
+
|
|
714
|
+
var state = MP_INITIAL;
|
|
715
|
+
var pending = Buffer.alloc(0);
|
|
716
|
+
var currentHeaders = null;
|
|
717
|
+
var currentField = null;
|
|
718
|
+
var currentFilename = null;
|
|
719
|
+
var currentMime = null;
|
|
720
|
+
var currentTmpPath = null;
|
|
721
|
+
var currentFd = null;
|
|
722
|
+
var currentSize = 0;
|
|
723
|
+
var currentHash = null;
|
|
724
|
+
var currentBuf = null; // for fields (in-memory accumulator)
|
|
725
|
+
var currentDiscarded = false; // true when fileFilter rejected the part — body bytes are
|
|
726
|
+
// still consumed (we have to read past them to find the next
|
|
727
|
+
// boundary) but never written to disk.
|
|
728
|
+
var currentEffectiveLimit = 0; // per-field-or-global cap; recomputed at part start.
|
|
729
|
+
|
|
730
|
+
function _resetCurrent() {
|
|
731
|
+
currentHeaders = null;
|
|
732
|
+
currentField = null;
|
|
733
|
+
currentFilename = null;
|
|
734
|
+
currentMime = null;
|
|
735
|
+
currentTmpPath = null;
|
|
736
|
+
if (currentFd !== null) { try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
|
|
737
|
+
currentSize = 0;
|
|
738
|
+
currentHash = null;
|
|
739
|
+
currentBuf = null;
|
|
740
|
+
currentDiscarded = false;
|
|
741
|
+
currentEffectiveLimit = 0;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function _emitRejection(field, filename, mimeType, code, message) {
|
|
745
|
+
filesRejected.push({
|
|
746
|
+
field: field,
|
|
747
|
+
filename: filename,
|
|
748
|
+
mimeType: mimeType,
|
|
749
|
+
code: code,
|
|
750
|
+
message: message || null,
|
|
751
|
+
});
|
|
752
|
+
if (auditInst) {
|
|
753
|
+
try {
|
|
754
|
+
auditInst.safeEmit({
|
|
755
|
+
action: "body-parser.multipart.file_rejected",
|
|
756
|
+
outcome: "denied",
|
|
757
|
+
resource: { kind: "multipart.file", id: field + (filename ? ":" + filename : "") },
|
|
758
|
+
metadata: { field: field, filename: filename, mimeType: mimeType, code: code, message: message || null },
|
|
759
|
+
});
|
|
760
|
+
} catch (_e) { /* audit best-effort */ }
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function _cleanup() {
|
|
765
|
+
if (currentFd !== null) { try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ } currentFd = null; }
|
|
766
|
+
if (currentTmpPath) { try { nodeFs.unlinkSync(currentTmpPath); } catch (_e) { /* tmp file already removed */ } }
|
|
767
|
+
for (var i = 0; i < files.length; i++) {
|
|
768
|
+
try { nodeFs.unlinkSync(files[i].path); } catch (_e) { /* tmp file already removed */ }
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
try {
|
|
773
|
+
return await new Promise(function (resolve, reject) {
|
|
774
|
+
function done(err, value) {
|
|
775
|
+
// De-dup completion — req error + req end can both fire.
|
|
776
|
+
if (resolved) return;
|
|
777
|
+
resolved = true;
|
|
778
|
+
if (err) {
|
|
779
|
+
_cleanup();
|
|
780
|
+
reject(err);
|
|
781
|
+
} else {
|
|
782
|
+
resolve(value);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
var resolved = false;
|
|
786
|
+
|
|
787
|
+
function processBuffer() {
|
|
788
|
+
// Re-enter the state machine until we can't make progress.
|
|
789
|
+
while (true) {
|
|
790
|
+
if (state === MP_INITIAL) {
|
|
791
|
+
// Find the first boundary marker (without the leading \r\n
|
|
792
|
+
// since the preamble may begin with the boundary directly).
|
|
793
|
+
var firstIdx = pending.indexOf(boundaryBuf);
|
|
794
|
+
if (firstIdx === -1) {
|
|
795
|
+
// Need more data.
|
|
796
|
+
if (pending.length > boundary.length + 100) {
|
|
797
|
+
// Drop preamble bytes to bound memory; keep the last
|
|
798
|
+
// boundary.length+4 bytes as look-ahead.
|
|
799
|
+
pending = pending.slice(pending.length - boundary.length - 4);
|
|
800
|
+
}
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
pending = pending.slice(firstIdx + boundaryBuf.length);
|
|
804
|
+
state = MP_AFTER_BD;
|
|
805
|
+
continue;
|
|
806
|
+
}
|
|
807
|
+
if (state === MP_AFTER_BD) {
|
|
808
|
+
if (pending.length < 2) return;
|
|
809
|
+
if (pending[0] === 0x2d && pending[1] === 0x2d) { // "--"
|
|
810
|
+
state = MP_DONE;
|
|
811
|
+
done(null, { fields: fields, files: files, filesRejected: filesRejected });
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (pending[0] === 0x0d && pending[1] === 0x0a) { // "\r\n"
|
|
815
|
+
pending = pending.slice(2);
|
|
816
|
+
state = MP_HEADERS;
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
// Tolerate transport-added \n only.
|
|
820
|
+
if (pending[0] === 0x0a) {
|
|
821
|
+
pending = pending.slice(1);
|
|
822
|
+
state = MP_HEADERS;
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
done(new BodyParserError("body-parser/multipart-malformed",
|
|
826
|
+
"expected --, \\r\\n, or \\n after boundary", true, HTTP_STATUS.BAD_REQUEST));
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (state === MP_HEADERS) {
|
|
830
|
+
// Read until \r\n\r\n.
|
|
831
|
+
var headEnd = pending.indexOf("\r\n\r\n");
|
|
832
|
+
if (headEnd === -1) {
|
|
833
|
+
if (pending.length > C.BYTES.kib(16)) {
|
|
834
|
+
done(new BodyParserError("body-parser/multipart-headers-too-large",
|
|
835
|
+
"multipart part headers exceed 16KB", true, 413));
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
// Count the per-part header bytes toward totalSize so a
|
|
841
|
+
// burst of small parts can't slip past the request-level
|
|
842
|
+
// cap. Without this, fileCount: 20 + fieldCount: 100
|
|
843
|
+
// gives an attacker ~120 × 16 KiB = ~1.9 MiB of pending
|
|
844
|
+
// header state per request, multiplied across concurrent
|
|
845
|
+
// requests.
|
|
846
|
+
totalRead += headEnd + 4;
|
|
847
|
+
if (totalRead > totalSize) {
|
|
848
|
+
done(new BodyParserError("body-parser/multipart-too-large",
|
|
849
|
+
"multipart total request size exceeds totalSize (" + totalSize + ")",
|
|
850
|
+
true, HTTP_STATUS.PAYLOAD_TOO_LARGE));
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
try {
|
|
854
|
+
currentHeaders = _parseMultipartHeaders(pending.slice(0, headEnd).toString("utf8"));
|
|
855
|
+
} catch (parseErr) {
|
|
856
|
+
done(parseErr);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
pending = pending.slice(headEnd + 4);
|
|
860
|
+
// Decode Content-Disposition.
|
|
861
|
+
var cd = _parseHeaderParams(currentHeaders["content-disposition"]);
|
|
862
|
+
if (cd._value !== "form-data" || typeof cd.name !== "string" || cd.name.length === 0) {
|
|
863
|
+
done(new BodyParserError("body-parser/multipart-bad-disposition",
|
|
864
|
+
"multipart part missing form-data Content-Disposition", true, HTTP_STATUS.BAD_REQUEST));
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
if (POISONED_KEYS.has(cd.name)) {
|
|
868
|
+
done(new BodyParserError("body-parser/multipart-poisoned-field",
|
|
869
|
+
"multipart field '" + cd.name + "' is forbidden (prototype-pollution defense)",
|
|
870
|
+
true, HTTP_STATUS.BAD_REQUEST));
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
currentField = cd.name;
|
|
874
|
+
if (typeof cd.filename === "string") {
|
|
875
|
+
currentFilename = _sanitizeFilename(cd.filename);
|
|
876
|
+
if (!currentFilename) {
|
|
877
|
+
done(new BodyParserError("body-parser/multipart-bad-filename",
|
|
878
|
+
"multipart part filename did not survive sanitization (path traversal or empty)",
|
|
879
|
+
true, HTTP_STATUS.BAD_REQUEST));
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
currentMime = currentHeaders["content-type"] || "application/octet-stream";
|
|
883
|
+
// Per-field MIME allowlist takes precedence over the global one
|
|
884
|
+
// for this field; global applies to fields without an entry.
|
|
885
|
+
var fieldRule = perField ? perField[currentField] : null;
|
|
886
|
+
var perFieldMime = (fieldRule && Array.isArray(fieldRule.mimeTypes))
|
|
887
|
+
? fieldRule.mimeTypes : null;
|
|
888
|
+
if (perFieldMime) {
|
|
889
|
+
if (perFieldMime.indexOf(currentMime) === -1) {
|
|
890
|
+
done(new BodyParserError("body-parser/multipart-mime-not-allowed",
|
|
891
|
+
"multipart file '" + currentField + "' MIME '" + currentMime +
|
|
892
|
+
"' is not on the per-field allowlist",
|
|
893
|
+
true, 415));
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
} else if (mimeAllowlist && mimeAllowlist.indexOf(currentMime) === -1) {
|
|
897
|
+
done(new BodyParserError("body-parser/multipart-mime-not-allowed",
|
|
898
|
+
"multipart file MIME '" + currentMime + "' is not on the allowlist",
|
|
899
|
+
true, 415));
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
fileCount++;
|
|
903
|
+
if (fileCount > fileLimit) {
|
|
904
|
+
done(new BodyParserError("body-parser/multipart-too-many-files",
|
|
905
|
+
"multipart fileCount exceeds limit (" + fileLimit + ")",
|
|
906
|
+
true, 413));
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
// Per-field cap overrides global fileSize for this field.
|
|
910
|
+
currentEffectiveLimit = (fieldRule && typeof fieldRule.maxBytes === "number")
|
|
911
|
+
? fieldRule.maxBytes : fileSize;
|
|
912
|
+
|
|
913
|
+
// fileFilter runs AFTER sanitize + MIME checks but BEFORE the
|
|
914
|
+
// tmp file opens. Synchronous so the parser can decide between
|
|
915
|
+
// disk-write and discard-bytes without buffering the part.
|
|
916
|
+
if (fileFilter) {
|
|
917
|
+
var filterVerdict;
|
|
918
|
+
try {
|
|
919
|
+
filterVerdict = fileFilter({
|
|
920
|
+
field: currentField,
|
|
921
|
+
filename: currentFilename,
|
|
922
|
+
mimeType: currentMime,
|
|
923
|
+
partHeaders: currentHeaders,
|
|
924
|
+
});
|
|
925
|
+
} catch (e) {
|
|
926
|
+
done(new BodyParserError("body-parser/multipart-file-filter-throw",
|
|
927
|
+
"fileFilter threw: " + ((e && e.message) || String(e)),
|
|
928
|
+
true, 500));
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
if (filterVerdict === false ||
|
|
932
|
+
(filterVerdict && typeof filterVerdict === "object" && filterVerdict.reject)) {
|
|
933
|
+
var rejCode = (filterVerdict && filterVerdict.code) || "fileFilter";
|
|
934
|
+
var rejMessage = (filterVerdict && filterVerdict.message) || null;
|
|
935
|
+
_emitRejection(currentField, currentFilename, currentMime, rejCode, rejMessage);
|
|
936
|
+
// Read past the body bytes (we still must find the next
|
|
937
|
+
// boundary) but never open a tmp file or push to req.files.
|
|
938
|
+
currentDiscarded = true;
|
|
939
|
+
fileCount--; // doesn't count toward the limit since it didn't land
|
|
940
|
+
currentSize = 0;
|
|
941
|
+
state = MP_BODY;
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// Generate the tmp path — never derived from the
|
|
947
|
+
// operator-supplied filename.
|
|
948
|
+
var unique = bCrypto.generateToken(C.BYTES.bytes(16));
|
|
949
|
+
currentTmpPath = nodePath.join(tmpDir, "blamejs-up-" + unique);
|
|
950
|
+
try {
|
|
951
|
+
currentFd = nodeFs.openSync(currentTmpPath, "wx", 0o600);
|
|
952
|
+
} catch (e) {
|
|
953
|
+
done(new BodyParserError("body-parser/multipart-tmp-open",
|
|
954
|
+
"could not open multipart tmp file: " + ((e && e.message) || String(e)),
|
|
955
|
+
true, 500));
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
currentHash = nodeCrypto.createHash("sha3-512");
|
|
959
|
+
currentSize = 0;
|
|
960
|
+
} else {
|
|
961
|
+
fieldCount++;
|
|
962
|
+
if (fieldCount > fieldLimit) {
|
|
963
|
+
done(new BodyParserError("body-parser/multipart-too-many-fields",
|
|
964
|
+
"multipart fieldCount exceeds limit (" + fieldLimit + ")",
|
|
965
|
+
true, 413));
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
// Per-field cap overrides global fieldSize for text parts too.
|
|
969
|
+
var textFieldRule = perField ? perField[currentField] : null;
|
|
970
|
+
currentEffectiveLimit = (textFieldRule && typeof textFieldRule.maxBytes === "number")
|
|
971
|
+
? textFieldRule.maxBytes : fieldSize;
|
|
972
|
+
currentBuf = [];
|
|
973
|
+
currentSize = 0;
|
|
974
|
+
}
|
|
975
|
+
state = MP_BODY;
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
if (state === MP_BODY) {
|
|
979
|
+
// Look for the next boundary. The marker we want is
|
|
980
|
+
// \r\n--<boundary>
|
|
981
|
+
// Anything before it is part body. We need to keep at least
|
|
982
|
+
// boundary.length + 4 bytes in `pending` so we don't emit a
|
|
983
|
+
// partial match as body bytes.
|
|
984
|
+
var bdIdx = pending.indexOf(boundaryDelimBuf);
|
|
985
|
+
var emitLen;
|
|
986
|
+
if (bdIdx === -1) {
|
|
987
|
+
// No marker yet — emit everything except the trailing
|
|
988
|
+
// boundary-length+4 bytes (might be the start of the marker).
|
|
989
|
+
if (pending.length <= boundaryDelimBuf.length) return;
|
|
990
|
+
emitLen = pending.length - boundaryDelimBuf.length;
|
|
991
|
+
} else {
|
|
992
|
+
emitLen = bdIdx;
|
|
993
|
+
}
|
|
994
|
+
if (emitLen > 0) {
|
|
995
|
+
var bodyChunk = pending.slice(0, emitLen);
|
|
996
|
+
if (currentDiscarded) {
|
|
997
|
+
// fileFilter rejected this part — read past the bytes to find
|
|
998
|
+
// the next boundary but never write to disk. totalSize still
|
|
999
|
+
// applies as a per-request DoS guard.
|
|
1000
|
+
totalRead += bodyChunk.length;
|
|
1001
|
+
if (totalRead > totalSize) {
|
|
1002
|
+
done(new BodyParserError("body-parser/multipart-total-too-large",
|
|
1003
|
+
"multipart total request size exceeds totalSize (" + totalSize + ")",
|
|
1004
|
+
true, 413));
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
} else if (currentFd !== null) {
|
|
1008
|
+
// File part — write to disk.
|
|
1009
|
+
currentSize += bodyChunk.length;
|
|
1010
|
+
if (currentSize > currentEffectiveLimit) {
|
|
1011
|
+
var perFieldFile = (perField && perField[currentField] &&
|
|
1012
|
+
typeof perField[currentField].maxBytes === "number");
|
|
1013
|
+
done(new BodyParserError("body-parser/multipart-file-too-large",
|
|
1014
|
+
"multipart file '" + currentField + "' exceeds " +
|
|
1015
|
+
(perFieldFile ? "per-field maxBytes" : "fileSize") +
|
|
1016
|
+
" (" + currentEffectiveLimit + ")",
|
|
1017
|
+
true, 413));
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
totalRead += bodyChunk.length;
|
|
1021
|
+
if (totalRead > totalSize) {
|
|
1022
|
+
done(new BodyParserError("body-parser/multipart-total-too-large",
|
|
1023
|
+
"multipart total request size exceeds totalSize (" + totalSize + ")",
|
|
1024
|
+
true, 413));
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
try {
|
|
1028
|
+
var written = 0;
|
|
1029
|
+
while (written < bodyChunk.length) {
|
|
1030
|
+
written += nodeFs.writeSync(currentFd, bodyChunk, written, bodyChunk.length - written);
|
|
1031
|
+
}
|
|
1032
|
+
} catch (e) {
|
|
1033
|
+
done(new BodyParserError("body-parser/multipart-tmp-write",
|
|
1034
|
+
"multipart tmp write failed: " + ((e && e.message) || String(e)),
|
|
1035
|
+
true, 500));
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
currentHash.update(bodyChunk);
|
|
1039
|
+
} else {
|
|
1040
|
+
// Field part — buffer in memory up to per-field-or-global cap.
|
|
1041
|
+
currentSize += bodyChunk.length;
|
|
1042
|
+
if (currentSize > currentEffectiveLimit) {
|
|
1043
|
+
var perFieldText = (perField && perField[currentField] &&
|
|
1044
|
+
typeof perField[currentField].maxBytes === "number");
|
|
1045
|
+
done(new BodyParserError("body-parser/multipart-field-too-large",
|
|
1046
|
+
"multipart field '" + currentField + "' exceeds " +
|
|
1047
|
+
(perFieldText ? "per-field maxBytes" : "fieldSize") +
|
|
1048
|
+
" (" + currentEffectiveLimit + ")",
|
|
1049
|
+
true, 413));
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
totalRead += bodyChunk.length;
|
|
1053
|
+
if (totalRead > totalSize) {
|
|
1054
|
+
done(new BodyParserError("body-parser/multipart-total-too-large",
|
|
1055
|
+
"multipart total request size exceeds totalSize (" + totalSize + ")",
|
|
1056
|
+
true, 413));
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
currentBuf.push(bodyChunk);
|
|
1060
|
+
}
|
|
1061
|
+
pending = pending.slice(emitLen);
|
|
1062
|
+
}
|
|
1063
|
+
if (bdIdx === -1) return; // need more data
|
|
1064
|
+
// Consume the boundary delimiter; transition to AFTER_BD.
|
|
1065
|
+
pending = pending.slice(boundaryDelimBuf.length);
|
|
1066
|
+
// Finalize the current part.
|
|
1067
|
+
if (currentDiscarded) {
|
|
1068
|
+
// fileFilter rejected — already recorded in filesRejected; no
|
|
1069
|
+
// tmp file was opened, nothing to clean up here.
|
|
1070
|
+
} else if (currentFd !== null) {
|
|
1071
|
+
try { nodeFs.closeSync(currentFd); } catch (_e) { /* fd already closed */ }
|
|
1072
|
+
currentFd = null;
|
|
1073
|
+
files.push({
|
|
1074
|
+
field: currentField,
|
|
1075
|
+
filename: currentFilename,
|
|
1076
|
+
mimeType: currentMime,
|
|
1077
|
+
path: currentTmpPath,
|
|
1078
|
+
size: currentSize,
|
|
1079
|
+
hash: currentHash.digest("hex"),
|
|
1080
|
+
});
|
|
1081
|
+
} else {
|
|
1082
|
+
// Field part — flatten + decode UTF-8.
|
|
1083
|
+
var fbuf = Buffer.concat(currentBuf);
|
|
1084
|
+
var text = fbuf.toString("utf8");
|
|
1085
|
+
// Repeated field name → array, matching urlencoded parser.
|
|
1086
|
+
if (Object.prototype.hasOwnProperty.call(fields, currentField)) {
|
|
1087
|
+
// lgtm[js/remote-property-injection] — `currentField` is gated
|
|
1088
|
+
// upstream at lib/middleware/body-parser.js:867 by
|
|
1089
|
+
// POISONED_KEYS (__proto__ / constructor / prototype) which
|
|
1090
|
+
// refuses the multipart part with a 400 BodyParserError before
|
|
1091
|
+
// `currentField` is ever assigned. Reachable values cannot
|
|
1092
|
+
// pollute the prototype chain.
|
|
1093
|
+
if (Array.isArray(fields[currentField])) fields[currentField].push(text);
|
|
1094
|
+
else fields[currentField] = [fields[currentField], text];
|
|
1095
|
+
} else {
|
|
1096
|
+
// lgtm[js/remote-property-injection] — see upstream POISONED_KEYS
|
|
1097
|
+
// gate at lib/middleware/body-parser.js:867.
|
|
1098
|
+
fields[currentField] = text;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
currentHeaders = null;
|
|
1102
|
+
currentField = null;
|
|
1103
|
+
currentFilename = null;
|
|
1104
|
+
currentMime = null;
|
|
1105
|
+
currentTmpPath = null;
|
|
1106
|
+
currentSize = 0;
|
|
1107
|
+
currentHash = null;
|
|
1108
|
+
currentBuf = null;
|
|
1109
|
+
currentDiscarded = false;
|
|
1110
|
+
currentEffectiveLimit = 0;
|
|
1111
|
+
state = MP_AFTER_BD;
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
if (state === MP_DONE) return;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
req.on("data", function (chunk) {
|
|
1119
|
+
if (resolved) return;
|
|
1120
|
+
pending = Buffer.concat([pending, chunk]);
|
|
1121
|
+
try { processBuffer(); }
|
|
1122
|
+
catch (e) {
|
|
1123
|
+
done(new BodyParserError("body-parser/multipart-internal",
|
|
1124
|
+
"multipart internal parse error: " + ((e && e.message) || String(e)),
|
|
1125
|
+
true, 500));
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
req.on("end", function () {
|
|
1129
|
+
if (resolved) return;
|
|
1130
|
+
if (state !== MP_DONE) {
|
|
1131
|
+
done(new BodyParserError("body-parser/multipart-truncated",
|
|
1132
|
+
"multipart stream ended before final boundary", true, HTTP_STATUS.BAD_REQUEST));
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
req.on("error", function (e) {
|
|
1137
|
+
if (resolved) return;
|
|
1138
|
+
done(new BodyParserError("body-parser/multipart-stream",
|
|
1139
|
+
"multipart stream error: " + ((e && e.message) || String(e)), true, HTTP_STATUS.BAD_REQUEST));
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1142
|
+
} catch (e) {
|
|
1143
|
+
// Already cleaned up via done(err).
|
|
1144
|
+
throw e;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// ---- main middleware factory ----
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* @primitive b.middleware.bodyParser
|
|
1152
|
+
* @signature b.middleware.bodyParser(req, res, next)
|
|
1153
|
+
* @since 0.1.0
|
|
1154
|
+
* @related b.middleware.bodyParser.raw, b.parsers.json, b.parsers.multipart
|
|
1155
|
+
*
|
|
1156
|
+
* Buffers and parses request bodies based on Content-Type.
|
|
1157
|
+
* Constructed via `b.middleware.bodyParser(opts)`; the resulting
|
|
1158
|
+
* middleware has the `(req, res, next)` shape shown above. Five
|
|
1159
|
+
* sub-parsers ship: JSON (via `safe-json` — POISONED_KEYS stripped,
|
|
1160
|
+
* depth + size caps), urlencoded, text, raw octet-stream, and
|
|
1161
|
+
* multipart/form-data. Multipart streams file parts to a tmp dir
|
|
1162
|
+
* with per-file + total-request size caps, filename sanitization,
|
|
1163
|
+
* SHA3-512 hashing during streaming, and tmp-file cleanup on
|
|
1164
|
+
* response end. Defends against RFC 9112 §6.1 request smuggling
|
|
1165
|
+
* before any body bytes are read. Each sub-parser can be disabled
|
|
1166
|
+
* by passing `false` in its slot.
|
|
1167
|
+
*
|
|
1168
|
+
* @opts
|
|
1169
|
+
* {
|
|
1170
|
+
* json: false | { limit, strict, charset, parseHook, contentTypes },
|
|
1171
|
+
* urlencoded: false | { limit, arrayLimit, contentTypes },
|
|
1172
|
+
* text: false | { limit, charset, contentTypes },
|
|
1173
|
+
* raw: false | { limit, contentTypes },
|
|
1174
|
+
* multipart: false | {
|
|
1175
|
+
* tmpDir, fileSize, totalSize, fileCount, fieldCount, fieldSize,
|
|
1176
|
+
* mimeAllowlist, fileFilter, fields, audit, contentTypes,
|
|
1177
|
+
* },
|
|
1178
|
+
* keepRawBody: boolean, // expose req.bodyRaw for webhook signing
|
|
1179
|
+
* }
|
|
1180
|
+
*
|
|
1181
|
+
* @example
|
|
1182
|
+
* var b = require("@blamejs/core");
|
|
1183
|
+
* var app = b.router.create();
|
|
1184
|
+
* app.use(b.middleware.bodyParser({
|
|
1185
|
+
* json: { limit: b.constants.BYTES.mib(1) },
|
|
1186
|
+
* urlencoded: { limit: b.constants.BYTES.mib(1) },
|
|
1187
|
+
* multipart: false,
|
|
1188
|
+
* }));
|
|
1189
|
+
*/
|
|
1190
|
+
function create(opts) {
|
|
1191
|
+
opts = opts || {};
|
|
1192
|
+
validateOpts(opts, [
|
|
1193
|
+
"json", "urlencoded", "text", "raw", "multipart", "keepRawBody",
|
|
1194
|
+
], "middleware.bodyParser");
|
|
1195
|
+
|
|
1196
|
+
function _resolve(name) {
|
|
1197
|
+
if (opts[name] === false) return null; // disabled
|
|
1198
|
+
return Object.assign({}, DEFAULTS[name], opts[name] || {});
|
|
1199
|
+
}
|
|
1200
|
+
var jsonOpts = _resolve("json");
|
|
1201
|
+
var urlencodedOpts = _resolve("urlencoded");
|
|
1202
|
+
var textOpts = _resolve("text");
|
|
1203
|
+
var rawOpts = _resolve("raw");
|
|
1204
|
+
var multipartOpts = _resolve("multipart");
|
|
1205
|
+
var keepRawBody = !!opts.keepRawBody;
|
|
1206
|
+
|
|
1207
|
+
return async function bodyParser(req, res, next) {
|
|
1208
|
+
// RFC 9112 §6.1 request-smuggling defense — runs BEFORE _hasBody
|
|
1209
|
+
// so the smuggling shape is rejected even if the request would
|
|
1210
|
+
// otherwise short-circuit as no-body. Reject with 400 +
|
|
1211
|
+
// Connection: close so the upstream proxy doesn't reuse the socket.
|
|
1212
|
+
var smug = _detectSmuggling(req);
|
|
1213
|
+
if (smug) {
|
|
1214
|
+
if (!res.headersSent) {
|
|
1215
|
+
var smugBody = JSON.stringify({ error: smug.message, code: smug.code });
|
|
1216
|
+
res.writeHead(smug.status, {
|
|
1217
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
1218
|
+
"Content-Length": Buffer.byteLength(smugBody),
|
|
1219
|
+
"Connection": "close",
|
|
1220
|
+
});
|
|
1221
|
+
res.end(smugBody);
|
|
1222
|
+
}
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
if (!_hasBody(req)) return next();
|
|
1226
|
+
if (req.body !== undefined) return next(); // already parsed by an earlier middleware
|
|
1227
|
+
|
|
1228
|
+
var ct = _contentType(req);
|
|
1229
|
+
|
|
1230
|
+
try {
|
|
1231
|
+
if (jsonOpts && _typeMatches(ct.type, jsonOpts.contentTypes)) {
|
|
1232
|
+
if (keepRawBody) {
|
|
1233
|
+
var rawBuf = await _bufferBody(req, jsonOpts.limit);
|
|
1234
|
+
req.bodyRaw = rawBuf;
|
|
1235
|
+
req.body = rawBuf.length === 0 ? undefined : await _parseJsonFromBuf(rawBuf, jsonOpts);
|
|
1236
|
+
} else {
|
|
1237
|
+
req.body = await _parseJson(req, jsonOpts);
|
|
1238
|
+
}
|
|
1239
|
+
return next();
|
|
1240
|
+
}
|
|
1241
|
+
if (urlencodedOpts && _typeMatches(ct.type, urlencodedOpts.contentTypes)) {
|
|
1242
|
+
req.body = await _parseUrlencoded(req, urlencodedOpts);
|
|
1243
|
+
return next();
|
|
1244
|
+
}
|
|
1245
|
+
if (multipartOpts && _typeMatches(ct.type, multipartOpts.contentTypes)) {
|
|
1246
|
+
var mpResult = await _parseMultipart(req, multipartOpts, ct.params);
|
|
1247
|
+
req.body = mpResult.fields;
|
|
1248
|
+
req.files = mpResult.files;
|
|
1249
|
+
req.filesRejected = mpResult.filesRejected || [];
|
|
1250
|
+
// Cleanup tmp files when the response finishes / closes / errors,
|
|
1251
|
+
// regardless of whether the handler returned cleanly. Operators
|
|
1252
|
+
// who want to KEEP a file move it elsewhere inside the handler.
|
|
1253
|
+
var cleanedUp = false;
|
|
1254
|
+
function cleanup() {
|
|
1255
|
+
if (cleanedUp) return;
|
|
1256
|
+
cleanedUp = true;
|
|
1257
|
+
for (var i = 0; i < mpResult.files.length; i++) {
|
|
1258
|
+
try { nodeFs.unlinkSync(mpResult.files[i].path); } catch (_e) { /* tmp file already removed */ }
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
res.on("finish", cleanup);
|
|
1262
|
+
res.on("close", cleanup);
|
|
1263
|
+
return next();
|
|
1264
|
+
}
|
|
1265
|
+
if (textOpts && _typeMatches(ct.type, textOpts.contentTypes)) {
|
|
1266
|
+
req.body = await _parseText(req, textOpts);
|
|
1267
|
+
return next();
|
|
1268
|
+
}
|
|
1269
|
+
if (rawOpts && _typeMatches(ct.type, rawOpts.contentTypes)) {
|
|
1270
|
+
req.body = await _parseRaw(req, rawOpts);
|
|
1271
|
+
return next();
|
|
1272
|
+
}
|
|
1273
|
+
// Body present but no enabled sub-parser matches the Content-Type.
|
|
1274
|
+
// Don't reject silently — operators with a custom parser opted in
|
|
1275
|
+
// by NOT enabling any sub-parser for this Content-Type would skip
|
|
1276
|
+
// bodyParser entirely. Reaching here means: enabled parsers exist
|
|
1277
|
+
// but none match this body. 415 is honest about the mismatch.
|
|
1278
|
+
_writeError(res, 415,
|
|
1279
|
+
"Unsupported Content-Type '" + ct.type + "'. Enable a matching sub-parser or send a different type.",
|
|
1280
|
+
"body-parser/unsupported-content-type"
|
|
1281
|
+
);
|
|
1282
|
+
} catch (e) {
|
|
1283
|
+
// RFC 9112 §7.1 — a server that rejects a chunked-decoded body
|
|
1284
|
+
// MUST close the connection so the upstream proxy cannot reuse
|
|
1285
|
+
// the socket with the next request's bytes still in flight. The
|
|
1286
|
+
// smuggling-shape pre-flight at top of the request already
|
|
1287
|
+
// catches the static TE/CL conflict cases; this catch handles
|
|
1288
|
+
// mid-stream parser failure (HPE_INVALID_CHUNK_SIZE etc. surfaced
|
|
1289
|
+
// by Node's HTTP parser as the body bytes arrive). Set
|
|
1290
|
+
// Connection: close + audit + 400.
|
|
1291
|
+
if (_isChunkedMalformed(e)) {
|
|
1292
|
+
// CVE-2026-33870 — chunked-encoding extension smuggling. When
|
|
1293
|
+
// Node's parser surfaces HPE_CHUNK_EXTENSIONS_OVERFLOW the
|
|
1294
|
+
// chunk-extension parameters exceeded llhttp's cap; the
|
|
1295
|
+
// framework emits a distinct audit action so operators can
|
|
1296
|
+
// alert on extension-smuggling specifically. RFC 9112 §7.1.1
|
|
1297
|
+
// chunk-ext is `; chunk-ext-name [= chunk-ext-val]` per chunk;
|
|
1298
|
+
// multi-`;` and `;param=value` shapes reach this code path
|
|
1299
|
+
// when the operator sets a tighter
|
|
1300
|
+
// `--max-http-header-size` / per-chunk extension cap.
|
|
1301
|
+
var chunkAction = (e && e.code === "HPE_CHUNK_EXTENSIONS_OVERFLOW")
|
|
1302
|
+
? "http.chunked.extension.refused"
|
|
1303
|
+
: "http.chunked.malformed.refused";
|
|
1304
|
+
try {
|
|
1305
|
+
audit().safeEmit({
|
|
1306
|
+
action: chunkAction,
|
|
1307
|
+
outcome: "denied",
|
|
1308
|
+
metadata: {
|
|
1309
|
+
code: e.code || null,
|
|
1310
|
+
message: (e && e.message) ? String(e.message).slice(0, 256) : "", // allow:raw-byte-literal — diagnostic-message clamp characters, not bytes
|
|
1311
|
+
},
|
|
1312
|
+
});
|
|
1313
|
+
} catch (_e) { /* audit best-effort */ }
|
|
1314
|
+
if (!res.headersSent) {
|
|
1315
|
+
var malformedBody = JSON.stringify({
|
|
1316
|
+
error: "malformed chunked transfer-encoding (RFC 9112 §7.1 — connection closed)",
|
|
1317
|
+
code: "http/chunked-malformed",
|
|
1318
|
+
});
|
|
1319
|
+
res.writeHead(HTTP_STATUS.BAD_REQUEST, {
|
|
1320
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
1321
|
+
"Content-Length": Buffer.byteLength(malformedBody),
|
|
1322
|
+
"Connection": "close",
|
|
1323
|
+
});
|
|
1324
|
+
res.end(malformedBody);
|
|
1325
|
+
}
|
|
1326
|
+
try { req.destroy(); } catch (_e) { /* socket already closed */ }
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
var status = (e && typeof e.statusCode === "number") ? e.statusCode : HTTP_STATUS.BAD_REQUEST;
|
|
1330
|
+
var code = (e && typeof e.code === "string") ? e.code : "body-parser/error";
|
|
1331
|
+
var message = (e && e.message) ? e.message : String(e);
|
|
1332
|
+
_writeError(res, status, message, code);
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// Helper used by keepRawBody path — re-uses the JSON pipeline but
|
|
1338
|
+
// works from an already-buffered Buffer (so we don't read req twice).
|
|
1339
|
+
async function _parseJsonFromBuf(buf, opts) {
|
|
1340
|
+
var text = buf.toString(opts.charset);
|
|
1341
|
+
if (opts.strict) {
|
|
1342
|
+
var head = text.replace(/^[\s\u00A0\uFEFF]+/, "")[0];
|
|
1343
|
+
if (head !== "{" && head !== "[") {
|
|
1344
|
+
throw new BodyParserError("body-parser/json-strict",
|
|
1345
|
+
"JSON body must start with '{' or '[' (strict mode)", true, HTTP_STATUS.BAD_REQUEST);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
var parsed;
|
|
1349
|
+
try { parsed = safeJson.parse(text, { maxBytes: opts.limit }); }
|
|
1350
|
+
catch (e) {
|
|
1351
|
+
throw new BodyParserError("body-parser/json-malformed",
|
|
1352
|
+
"JSON parse failed: " + ((e && e.message) || String(e)), true, HTTP_STATUS.BAD_REQUEST);
|
|
1353
|
+
}
|
|
1354
|
+
if (typeof opts.parseHook === "function") {
|
|
1355
|
+
try { parsed = opts.parseHook(parsed); }
|
|
1356
|
+
catch (e) {
|
|
1357
|
+
throw new BodyParserError("body-parser/json-hook",
|
|
1358
|
+
"JSON parseHook failed: " + ((e && e.message) || String(e)), true, HTTP_STATUS.BAD_REQUEST);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return parsed;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
// raw — convenience wrapper that returns a middleware which buffers
|
|
1365
|
+
// the request body as a Buffer regardless of Content-Type. Webhook
|
|
1366
|
+
// signature-verification routes use this — the HMAC is computed over
|
|
1367
|
+
// the literal body bytes, so JSON-parsing first would change them.
|
|
1368
|
+
//
|
|
1369
|
+
// router.post("/hooks/in", b.middleware.bodyParser.raw(), function (req, res) {
|
|
1370
|
+
// verifier.verify(req.headers["x-signature"], req.body); // req.body is a Buffer
|
|
1371
|
+
// });
|
|
1372
|
+
//
|
|
1373
|
+
// Accepts the same `raw`-section opts as create() (limit, contentTypes).
|
|
1374
|
+
// contentTypes default expands to `["*/*"]` so any Content-Type lands
|
|
1375
|
+
// as raw bytes.
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* @primitive b.middleware.bodyParser.raw
|
|
1379
|
+
* @signature b.middleware.bodyParser.raw(opts)
|
|
1380
|
+
* @since 0.1.0
|
|
1381
|
+
* @related b.middleware.bodyParser
|
|
1382
|
+
*
|
|
1383
|
+
* Convenience factory that mounts only the raw-bytes sub-parser of
|
|
1384
|
+
* `bodyParser`. Sets `req.body` to a Buffer regardless of
|
|
1385
|
+
* `Content-Type`. Use on webhook-signature routes where the HMAC is
|
|
1386
|
+
* computed over the literal body bytes — JSON-parsing first would
|
|
1387
|
+
* change them. The `contentTypes` default expands to `["*\/*"]` so
|
|
1388
|
+
* any inbound type is captured.
|
|
1389
|
+
*
|
|
1390
|
+
* @opts
|
|
1391
|
+
* {
|
|
1392
|
+
* limit: number, // default ~10 MiB
|
|
1393
|
+
* contentTypes: string[], // default ["*\/*"]
|
|
1394
|
+
* }
|
|
1395
|
+
*
|
|
1396
|
+
* @example
|
|
1397
|
+
* var b = require("@blamejs/core");
|
|
1398
|
+
* var app = b.router.create();
|
|
1399
|
+
* app.post("/hooks/in", b.middleware.bodyParser.raw({
|
|
1400
|
+
* limit: b.constants.BYTES.mib(1),
|
|
1401
|
+
* }), function (req, res) {
|
|
1402
|
+
* // req.body is a Buffer of the raw request bytes
|
|
1403
|
+
* res.end(String(req.body.length));
|
|
1404
|
+
* });
|
|
1405
|
+
*/
|
|
1406
|
+
function raw(opts) {
|
|
1407
|
+
opts = opts || {};
|
|
1408
|
+
return create({
|
|
1409
|
+
json: false,
|
|
1410
|
+
urlencoded: false,
|
|
1411
|
+
text: false,
|
|
1412
|
+
multipart: false,
|
|
1413
|
+
raw: {
|
|
1414
|
+
limit: opts.limit != null ? opts.limit : DEFAULTS.raw.limit,
|
|
1415
|
+
contentTypes: opts.contentTypes || ["*/*"],
|
|
1416
|
+
},
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
// Attach raw onto create so b.middleware.bodyParser.raw() works
|
|
1421
|
+
// (middleware/index.js exports the create function as the namespace
|
|
1422
|
+
// itself, so static helpers hang off it).
|
|
1423
|
+
create.raw = raw;
|
|
1424
|
+
|
|
1425
|
+
// ---- Standalone async parsers ----
|
|
1426
|
+
//
|
|
1427
|
+
// `parseJsonStandalone(req, opts)` and `parseMultipartStandalone(req, opts)`
|
|
1428
|
+
// are the same parsing pipelines the middleware uses, exposed for handlers
|
|
1429
|
+
// that lazy-parse — code that decides parser shape from a route flag, or
|
|
1430
|
+
// bypasses the middleware for streaming endpoints. The middleware composes
|
|
1431
|
+
// these so there's no parallel pipeline to drift.
|
|
1432
|
+
//
|
|
1433
|
+
// Throws BodyParserError on caps / malformed shapes — operator handles in
|
|
1434
|
+
// a try/catch around `await b.parsers.json(req, ...)` /
|
|
1435
|
+
// `await b.parsers.multipart(req, ...)`. Validation tier is config-time
|
|
1436
|
+
// (throw at create on bad opts) + observable (throw on bad input — the
|
|
1437
|
+
// handler is awaiting the call, not a request lifecycle hook).
|
|
1438
|
+
|
|
1439
|
+
function _resolveStandaloneJsonOpts(opts) {
|
|
1440
|
+
opts = opts || {};
|
|
1441
|
+
var maxBytes = (opts.maxBytes !== undefined) ? opts.maxBytes : DEFAULTS.json.limit;
|
|
1442
|
+
validateOpts.optionalPositiveFinite(maxBytes, "parsers.json: opts.maxBytes",
|
|
1443
|
+
BodyParserError, "body-parser/bad-max-bytes");
|
|
1444
|
+
var strict = (opts.strict !== undefined) ? !!opts.strict : DEFAULTS.json.strict;
|
|
1445
|
+
var charset = (typeof opts.charset === "string") ? opts.charset : DEFAULTS.json.charset;
|
|
1446
|
+
return {
|
|
1447
|
+
limit: maxBytes,
|
|
1448
|
+
strict: strict,
|
|
1449
|
+
charset: charset,
|
|
1450
|
+
parseHook: (typeof opts.parseHook === "function") ? opts.parseHook : undefined,
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
function _resolveStandaloneMultipartOpts(opts, ct) {
|
|
1455
|
+
opts = opts || {};
|
|
1456
|
+
var resolved = Object.assign({}, DEFAULTS.multipart);
|
|
1457
|
+
validateOpts.optionalPositiveFinite(opts.maxBytes, "parsers.multipart: opts.maxBytes",
|
|
1458
|
+
BodyParserError, "body-parser/bad-max-bytes");
|
|
1459
|
+
if (opts.maxBytes !== undefined) {
|
|
1460
|
+
resolved.totalSize = opts.maxBytes;
|
|
1461
|
+
// Per-file cap clamps to maxBytes so a single field can't exceed the
|
|
1462
|
+
// request total — operator opts in to a smaller fileSize via opts.fileSize.
|
|
1463
|
+
if (resolved.fileSize > opts.maxBytes) resolved.fileSize = opts.maxBytes;
|
|
1464
|
+
}
|
|
1465
|
+
if (opts.maxFiles !== undefined) {
|
|
1466
|
+
var mf = opts.maxFiles;
|
|
1467
|
+
var mfBad = typeof mf !== "number" || !isFinite(mf) || mf <= 0 || Math.floor(mf) !== mf;
|
|
1468
|
+
if (mfBad) {
|
|
1469
|
+
throw new BodyParserError("body-parser/bad-max-files",
|
|
1470
|
+
"parsers.multipart: opts.maxFiles must be a positive integer",
|
|
1471
|
+
true, HTTP_STATUS.BAD_REQUEST);
|
|
1472
|
+
}
|
|
1473
|
+
resolved.fileCount = mf;
|
|
1474
|
+
}
|
|
1475
|
+
// Pass-through overrides for the multipart-specific knobs the middleware
|
|
1476
|
+
// accepts. parsers.multipart is a thin wrapper, not a feature subset.
|
|
1477
|
+
["tmpDir", "fileSize", "fieldCount", "fieldSize", "mimeAllowlist",
|
|
1478
|
+
"fileFilter", "fields", "audit"].forEach(function (k) {
|
|
1479
|
+
if (opts[k] !== undefined) resolved[k] = opts[k];
|
|
1480
|
+
});
|
|
1481
|
+
// ct is the parsed Content-Type; required for the boundary parameter.
|
|
1482
|
+
if (!ct || typeof ct.type !== "string" || ct.type !== "multipart/form-data") {
|
|
1483
|
+
throw new BodyParserError("body-parser/standalone-not-multipart",
|
|
1484
|
+
"parsers.multipart: request Content-Type must be multipart/form-data, got " +
|
|
1485
|
+
JSON.stringify(ct ? ct.type : null),
|
|
1486
|
+
true, HTTP_STATUS.BAD_REQUEST);
|
|
1487
|
+
}
|
|
1488
|
+
return resolved;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
async function parseJsonStandalone(req, opts) {
|
|
1492
|
+
var resolved = _resolveStandaloneJsonOpts(opts);
|
|
1493
|
+
return _parseJson(req, resolved);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
async function parseMultipartStandalone(req, opts) {
|
|
1497
|
+
var ct = _contentType(req);
|
|
1498
|
+
var resolved = _resolveStandaloneMultipartOpts(opts, ct);
|
|
1499
|
+
// Returns { fields, files, filesRejected } — same shape the middleware
|
|
1500
|
+
// attaches to req. Handlers that already-accepted the upload wire
|
|
1501
|
+
// cleanup themselves (move file off tmp / unlink).
|
|
1502
|
+
return _parseMultipart(req, resolved, ct.params);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
module.exports = {
|
|
1506
|
+
create: create,
|
|
1507
|
+
raw: raw,
|
|
1508
|
+
BodyParserError: BodyParserError,
|
|
1509
|
+
// Standalone async helpers — surfaced via b.parsers.{json,multipart}.
|
|
1510
|
+
// The middleware composes these so the request-handling pipeline and
|
|
1511
|
+
// the operator-callable surface share one parsing nodePath.
|
|
1512
|
+
parseJson: parseJsonStandalone,
|
|
1513
|
+
parseMultipart: parseMultipartStandalone,
|
|
1514
|
+
// Internal helpers exposed for tests + the csrf-protect refactor.
|
|
1515
|
+
_contentType: _contentType,
|
|
1516
|
+
_hasBody: _hasBody,
|
|
1517
|
+
_sanitizeFilename: _sanitizeFilename,
|
|
1518
|
+
POISONED_KEYS: POISONED_KEYS,
|
|
1519
|
+
};
|