@blamejs/blamejs-shop 0.4.69 → 0.4.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/lib/admin.js +8 -6
- package/lib/asset-manifest.json +1 -1
- package/lib/security-middleware.js +65 -23
- package/lib/storefront.js +10 -7
- package/lib/vendor/MANIFEST.json +319 -267
- package/lib/vendor/blamejs/CHANGELOG.md +2 -0
- package/lib/vendor/blamejs/api-snapshot.json +58 -5
- package/lib/vendor/blamejs/examples/wiki/README.md +1 -1
- package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +9 -8
- package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +10 -9
- package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +4 -3
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +33 -17
- package/lib/vendor/blamejs/examples/wiki/routes/admin.js +7 -10
- package/lib/vendor/blamejs/examples/wiki/server.js +5 -4
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +5 -0
- package/lib/vendor/blamejs/lib/a2a-tasks.js +38 -6
- package/lib/vendor/blamejs/lib/agent-event-bus.js +13 -0
- package/lib/vendor/blamejs/lib/agent-idempotency.js +5 -1
- package/lib/vendor/blamejs/lib/agent-snapshot.js +32 -2
- package/lib/vendor/blamejs/lib/ai-aedt-bias-audit.js +2 -1
- package/lib/vendor/blamejs/lib/ai-content-detect.js +1 -3
- package/lib/vendor/blamejs/lib/ai-frontier-protocol.js +1 -1
- package/lib/vendor/blamejs/lib/ai-model-manifest.js +1 -1
- package/lib/vendor/blamejs/lib/ai-output.js +16 -7
- package/lib/vendor/blamejs/lib/api-snapshot.js +4 -1
- package/lib/vendor/blamejs/lib/app-shutdown.js +7 -1
- package/lib/vendor/blamejs/lib/archive-gz.js +9 -0
- package/lib/vendor/blamejs/lib/archive-read.js +9 -7
- package/lib/vendor/blamejs/lib/archive-tar-read.js +51 -8
- package/lib/vendor/blamejs/lib/archive.js +4 -2
- package/lib/vendor/blamejs/lib/asn1-der.js +70 -22
- package/lib/vendor/blamejs/lib/atomic-file.js +204 -2
- package/lib/vendor/blamejs/lib/audit-chain.js +54 -5
- package/lib/vendor/blamejs/lib/audit-daily-review.js +12 -2
- package/lib/vendor/blamejs/lib/audit-sign.js +2 -1
- package/lib/vendor/blamejs/lib/audit-tools.js +108 -23
- package/lib/vendor/blamejs/lib/audit.js +7 -2
- package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -2
- package/lib/vendor/blamejs/lib/auth/bot-challenge.js +1 -1
- package/lib/vendor/blamejs/lib/auth/ciba.js +43 -4
- package/lib/vendor/blamejs/lib/auth/dpop.js +6 -1
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +5 -1
- package/lib/vendor/blamejs/lib/auth/jwt.js +2 -2
- package/lib/vendor/blamejs/lib/auth/lockout.js +18 -2
- package/lib/vendor/blamejs/lib/auth/passkey.js +1 -1
- package/lib/vendor/blamejs/lib/auth/password.js +1 -1
- package/lib/vendor/blamejs/lib/auth/saml.js +33 -13
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +24 -4
- package/lib/vendor/blamejs/lib/auth/status-list.js +14 -2
- package/lib/vendor/blamejs/lib/auth/step-up.js +9 -1
- package/lib/vendor/blamejs/lib/auth-bot-challenge.js +21 -2
- package/lib/vendor/blamejs/lib/backup/bundle.js +7 -2
- package/lib/vendor/blamejs/lib/backup/crypto.js +23 -8
- package/lib/vendor/blamejs/lib/backup/index.js +41 -20
- package/lib/vendor/blamejs/lib/backup/manifest.js +7 -1
- package/lib/vendor/blamejs/lib/break-glass.js +41 -22
- package/lib/vendor/blamejs/lib/cbor.js +34 -11
- package/lib/vendor/blamejs/lib/cdn-cache-control.js +7 -3
- package/lib/vendor/blamejs/lib/cert.js +5 -3
- package/lib/vendor/blamejs/lib/cli.js +5 -1
- package/lib/vendor/blamejs/lib/cloud-events.js +3 -2
- package/lib/vendor/blamejs/lib/cluster-storage.js +7 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +17 -0
- package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -1
- package/lib/vendor/blamejs/lib/compliance-sanctions.js +9 -7
- package/lib/vendor/blamejs/lib/compliance.js +1 -1
- package/lib/vendor/blamejs/lib/config-drift.js +22 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +11 -8
- package/lib/vendor/blamejs/lib/content-digest.js +11 -4
- package/lib/vendor/blamejs/lib/cookies.js +10 -2
- package/lib/vendor/blamejs/lib/cose.js +20 -0
- package/lib/vendor/blamejs/lib/crdt.js +2 -1
- package/lib/vendor/blamejs/lib/crypto-field.js +29 -23
- package/lib/vendor/blamejs/lib/crypto.js +18 -4
- package/lib/vendor/blamejs/lib/csp.js +4 -0
- package/lib/vendor/blamejs/lib/daemon.js +4 -1
- package/lib/vendor/blamejs/lib/data-act.js +27 -4
- package/lib/vendor/blamejs/lib/db-file-lifecycle.js +14 -6
- package/lib/vendor/blamejs/lib/db-query.js +69 -9
- package/lib/vendor/blamejs/lib/db.js +32 -15
- package/lib/vendor/blamejs/lib/dora.js +43 -13
- package/lib/vendor/blamejs/lib/dr-runbook.js +1 -1
- package/lib/vendor/blamejs/lib/dsa.js +2 -1
- package/lib/vendor/blamejs/lib/dsr.js +22 -8
- package/lib/vendor/blamejs/lib/early-hints.js +19 -0
- package/lib/vendor/blamejs/lib/eat.js +5 -1
- package/lib/vendor/blamejs/lib/external-db.js +60 -4
- package/lib/vendor/blamejs/lib/fda-21cfr11.js +30 -5
- package/lib/vendor/blamejs/lib/flag-providers.js +6 -2
- package/lib/vendor/blamejs/lib/forms.js +1 -1
- package/lib/vendor/blamejs/lib/gate-contract.js +46 -5
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +18 -9
- package/lib/vendor/blamejs/lib/graphql-federation.js +17 -4
- package/lib/vendor/blamejs/lib/guard-all.js +2 -2
- package/lib/vendor/blamejs/lib/guard-dsn.js +1 -1
- package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
- package/lib/vendor/blamejs/lib/guard-html.js +9 -11
- package/lib/vendor/blamejs/lib/guard-imap-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-jmap.js +1 -1
- package/lib/vendor/blamejs/lib/guard-json.js +14 -6
- package/lib/vendor/blamejs/lib/guard-mail-move.js +1 -1
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-smtp-command.js +1 -1
- package/lib/vendor/blamejs/lib/guard-svg.js +8 -9
- package/lib/vendor/blamejs/lib/html-balance.js +7 -3
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +33 -12
- package/lib/vendor/blamejs/lib/http-client.js +225 -53
- package/lib/vendor/blamejs/lib/iab-tcf.js +3 -2
- package/lib/vendor/blamejs/lib/importmap-integrity.js +41 -1
- package/lib/vendor/blamejs/lib/incident-report.js +9 -6
- package/lib/vendor/blamejs/lib/json-patch.js +1 -1
- package/lib/vendor/blamejs/lib/json-path.js +24 -3
- package/lib/vendor/blamejs/lib/jtd.js +2 -2
- package/lib/vendor/blamejs/lib/legal-hold.js +24 -8
- package/lib/vendor/blamejs/lib/log.js +2 -2
- package/lib/vendor/blamejs/lib/mail-agent.js +2 -2
- package/lib/vendor/blamejs/lib/mail-arf.js +1 -1
- package/lib/vendor/blamejs/lib/mail-auth.js +3 -3
- package/lib/vendor/blamejs/lib/mail-bimi.js +16 -16
- package/lib/vendor/blamejs/lib/mail-bounce.js +3 -3
- package/lib/vendor/blamejs/lib/mail-crypto-smime.js +71 -6
- package/lib/vendor/blamejs/lib/mail-deploy.js +9 -5
- package/lib/vendor/blamejs/lib/mail-greylist.js +2 -4
- package/lib/vendor/blamejs/lib/mail-helo.js +2 -4
- package/lib/vendor/blamejs/lib/mail-journal.js +11 -8
- package/lib/vendor/blamejs/lib/mail-mdn.js +8 -4
- package/lib/vendor/blamejs/lib/mail-rbl.js +2 -4
- package/lib/vendor/blamejs/lib/mail-scan.js +3 -5
- package/lib/vendor/blamejs/lib/mail-server-jmap.js +4 -1
- package/lib/vendor/blamejs/lib/mail-server-registry.js +1 -1
- package/lib/vendor/blamejs/lib/mail-server-tls.js +9 -2
- package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -4
- package/lib/vendor/blamejs/lib/mail-store-fts.js +1 -1
- package/lib/vendor/blamejs/lib/mail.js +22 -2
- package/lib/vendor/blamejs/lib/markup-tokenizer.js +24 -0
- package/lib/vendor/blamejs/lib/mcp.js +6 -4
- package/lib/vendor/blamejs/lib/mdoc.js +26 -3
- package/lib/vendor/blamejs/lib/metrics.js +14 -3
- package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +2 -2
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +10 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +26 -18
- package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +5 -1
- package/lib/vendor/blamejs/lib/middleware/compression.js +9 -0
- package/lib/vendor/blamejs/lib/middleware/cors.js +32 -23
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +60 -21
- package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -4
- package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +28 -4
- package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +61 -30
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +25 -16
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +2 -1
- package/lib/vendor/blamejs/lib/middleware/security-headers.js +24 -6
- package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +6 -3
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +2 -2
- package/lib/vendor/blamejs/lib/money.js +1 -1
- package/lib/vendor/blamejs/lib/mtls-ca.js +10 -6
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
- package/lib/vendor/blamejs/lib/network-dns.js +9 -2
- package/lib/vendor/blamejs/lib/network-dnssec.js +2 -1
- package/lib/vendor/blamejs/lib/network-smtp-policy.js +23 -5
- package/lib/vendor/blamejs/lib/network-tls.js +27 -5
- package/lib/vendor/blamejs/lib/network-tsig.js +2 -2
- package/lib/vendor/blamejs/lib/nis2-report.js +1 -1
- package/lib/vendor/blamejs/lib/nist-crosswalk.js +1 -1
- package/lib/vendor/blamejs/lib/ntp-check.js +28 -0
- package/lib/vendor/blamejs/lib/numeric-bounds.js +9 -0
- package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -2
- package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +4 -2
- package/lib/vendor/blamejs/lib/object-store/gcs.js +6 -4
- package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -2
- package/lib/vendor/blamejs/lib/object-store/http-request.js +30 -1
- package/lib/vendor/blamejs/lib/object-store/local.js +37 -17
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +1 -2
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +20 -4
- package/lib/vendor/blamejs/lib/outbox.js +11 -4
- package/lib/vendor/blamejs/lib/parsers/safe-xml.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +21 -3
- package/lib/vendor/blamejs/lib/queue-local.js +10 -3
- package/lib/vendor/blamejs/lib/redact.js +7 -3
- package/lib/vendor/blamejs/lib/request-helpers.js +201 -23
- package/lib/vendor/blamejs/lib/resource-access-lock.js +3 -3
- package/lib/vendor/blamejs/lib/restore-bundle.js +46 -18
- package/lib/vendor/blamejs/lib/restore-rollback.js +10 -4
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +20 -4
- package/lib/vendor/blamejs/lib/router.js +17 -4
- package/lib/vendor/blamejs/lib/safe-ical.js +2 -2
- package/lib/vendor/blamejs/lib/safe-icap.js +1 -1
- package/lib/vendor/blamejs/lib/safe-json.js +44 -0
- package/lib/vendor/blamejs/lib/safe-sieve.js +1 -1
- package/lib/vendor/blamejs/lib/safe-vcard.js +1 -1
- package/lib/vendor/blamejs/lib/sandbox-worker.js +6 -0
- package/lib/vendor/blamejs/lib/sandbox.js +1 -1
- package/lib/vendor/blamejs/lib/scheduler.js +17 -1
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +16 -0
- package/lib/vendor/blamejs/lib/session.js +27 -3
- package/lib/vendor/blamejs/lib/sql.js +3 -3
- package/lib/vendor/blamejs/lib/static.js +65 -13
- package/lib/vendor/blamejs/lib/template.js +7 -5
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -19
- package/lib/vendor/blamejs/lib/tsa.js +5 -2
- package/lib/vendor/blamejs/lib/vault/index.js +5 -0
- package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +22 -26
- package/lib/vendor/blamejs/lib/vault/passphrase-source.js +8 -3
- package/lib/vendor/blamejs/lib/vault/rotate.js +13 -18
- package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +4 -1
- package/lib/vendor/blamejs/lib/vc.js +1 -1
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +10 -10
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +23 -10
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5498 -5494
- package/lib/vendor/blamejs/lib/webhook.js +16 -1
- package/lib/vendor/blamejs/lib/websocket.js +1 -1
- package/lib/vendor/blamejs/lib/worm.js +1 -1
- package/lib/vendor/blamejs/lib/ws-client.js +57 -46
- package/lib/vendor/blamejs/lib/x509-chain.js +44 -0
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.14.json +122 -0
- package/lib/vendor/blamejs/scripts/check-vendor-currency.js +119 -4
- package/lib/vendor/blamejs/test/00-primitives.js +5 -1
- package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +18 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +42 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-gz.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-hardening.test.js +160 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-open-nofollow.test.js +79 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-excl.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-stream.test.js +181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-corrupted-anchor.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-incremental-verify.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +48 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +13 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +37 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +5 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +62 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-storage.test.js +40 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +146 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compression-range.test.js +115 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +17 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +27 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +20 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-alg-kty.test.js +64 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +12 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +72 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-throttle-transform.test.js +88 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-header-injection.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +63 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/mdoc.test.js +41 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +61 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/object-store-range-header.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/output-header-hardening.test.js +102 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parser-verify-hardening.test.js +191 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/proto-shadow-allowlist.test.js +120 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +75 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-blob-remap.test.js +128 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention-sweep-termination.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-body-validation.test.js +98 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json-stringify-for-script.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +48 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +23 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +54 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +42 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +7 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template-escape-html.test.js +43 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-default-store.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vendor-currency-classify.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/x509-chain-ca-enforcement.test.js +149 -0
- package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +34 -0
- package/package.json +1 -1
|
@@ -58,6 +58,7 @@ var validateOpts = require("./validate-opts");
|
|
|
58
58
|
|
|
59
59
|
var audit = lazyRequire(function () { return require("./audit"); });
|
|
60
60
|
var auditSign = lazyRequire(function () { return require("./audit-sign"); });
|
|
61
|
+
var compliance = lazyRequire(function () { return require("./compliance"); });
|
|
61
62
|
var vault = lazyRequire(function () { return require("./vault"); });
|
|
62
63
|
|
|
63
64
|
var AgentSnapshotError = defineClass("AgentSnapshotError", { alwaysPermanent: true });
|
|
@@ -310,14 +311,40 @@ function _resolveSigner(ctx) {
|
|
|
310
311
|
"OR pass opts.signer to b.agent.snapshot.create({ signer: { sign, verify } })");
|
|
311
312
|
}
|
|
312
313
|
|
|
314
|
+
// allowPlaintext is a dev / single-tenant escape hatch (no at-rest sealing,
|
|
315
|
+
// and no signature required on load). It is REFUSED under a regulated
|
|
316
|
+
// compliance posture so a regulated deployment cannot silently persist OR
|
|
317
|
+
// restore unsealed, unsigned snapshot state. Posture is read from the
|
|
318
|
+
// framework's globally-pinned source (compliance().current()) — the same
|
|
319
|
+
// source the residency + cryptoField seal floors use.
|
|
320
|
+
var REGULATED_NO_PLAINTEXT = ["hipaa", "pci-dss", "gdpr", "soc2"];
|
|
321
|
+
function _activePosture() {
|
|
322
|
+
try { var c = compliance(); return (c && typeof c.current === "function") ? c.current() : null; }
|
|
323
|
+
catch (_e) { return null; }
|
|
324
|
+
}
|
|
325
|
+
function _refusePlaintextUnderPosture(action) {
|
|
326
|
+
var active = _activePosture();
|
|
327
|
+
if (active && REGULATED_NO_PLAINTEXT.indexOf(active) !== -1) {
|
|
328
|
+
throw new AgentSnapshotError("agent-snapshot/plaintext-refused-under-posture",
|
|
329
|
+
action + ": allowPlaintext is refused under the '" + active + "' compliance posture — " +
|
|
330
|
+
"wire a sealer (b.vault.init() at boot OR opts.sealer { seal, unseal }) so snapshot " +
|
|
331
|
+
"state is sealed + signature-verified at rest");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
313
335
|
function _resolveSealer(ctx) {
|
|
314
336
|
if (ctx.sealer) return ctx.sealer;
|
|
315
337
|
var v;
|
|
316
338
|
try { v = vault(); } catch (_e) { v = null; }
|
|
317
|
-
|
|
339
|
+
// Only use the framework vault when it is actually INITIALIZED. A loaded-but-
|
|
340
|
+
// uninitialized vault still exposes aad.seal/unseal (they throw on call), which
|
|
341
|
+
// previously masked the allowPlaintext escape hatch and leaked a raw
|
|
342
|
+
// vault/not-initialized error instead of a clean sealer-not-wired refusal.
|
|
343
|
+
if (v && typeof v.isInitialized === "function" && v.isInitialized() &&
|
|
344
|
+
v.aad && typeof v.aad.seal === "function" && typeof v.aad.unseal === "function") {
|
|
318
345
|
return v.aad;
|
|
319
346
|
}
|
|
320
|
-
if (ctx.allowPlaintext) return null;
|
|
347
|
+
if (ctx.allowPlaintext) { _refusePlaintextUnderPosture("persist"); return null; }
|
|
321
348
|
throw new AgentSnapshotError("agent-snapshot/sealer-not-wired",
|
|
322
349
|
"persist: no sealer wired — operator must run b.vault.init() at boot " +
|
|
323
350
|
"OR pass opts.sealer to b.agent.snapshot.create({ sealer: { seal, unseal } }) " +
|
|
@@ -526,6 +553,9 @@ async function _unwrapAndVerify(ctx, raw, expectedId) {
|
|
|
526
553
|
// remains visible to compliance audit.
|
|
527
554
|
if (typeof snap.sig !== "string" || snap.sig.length === 0) {
|
|
528
555
|
if (ctx.allowPlaintext) {
|
|
556
|
+
// Even the dev escape hatch cannot waive signature verification under a
|
|
557
|
+
// regulated posture — refuse the unsigned restore rather than trust it.
|
|
558
|
+
_refusePlaintextUnderPosture("load");
|
|
529
559
|
agentAudit.safeAudit(ctx.audit, "agent.snapshot.unsigned_load", null, {
|
|
530
560
|
snapshotId: snap.snapshotId,
|
|
531
561
|
});
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
var validateOpts = require("./validate-opts");
|
|
39
|
+
var numericBounds = require("./numeric-bounds");
|
|
39
40
|
var { defineClass } = require("./framework-error");
|
|
40
41
|
|
|
41
42
|
var AedtBiasAuditError = defineClass("AedtBiasAuditError", { alwaysPermanent: true });
|
|
@@ -49,7 +50,7 @@ function _str(v, label) {
|
|
|
49
50
|
return v;
|
|
50
51
|
}
|
|
51
52
|
function _count(v, label) {
|
|
52
|
-
if (
|
|
53
|
+
if (!numericBounds.isNonNegativeFiniteInt(v)) throw new AedtBiasAuditError("aedt/bad-count", "aedtBiasAudit: " + label + " must be a non-negative integer");
|
|
53
54
|
return v;
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -255,9 +255,7 @@ function report(opts) {
|
|
|
255
255
|
* @example
|
|
256
256
|
* b.ai.aiContentDetect.compliancePosture("ca-ab-853"); // → "strict"
|
|
257
257
|
*/
|
|
258
|
-
|
|
259
|
-
return COMPLIANCE_POSTURES[posture] || null;
|
|
260
|
-
}
|
|
258
|
+
var compliancePosture = gateContract.makePostureAccessor(COMPLIANCE_POSTURES);
|
|
261
259
|
|
|
262
260
|
module.exports = {
|
|
263
261
|
report: report,
|
|
@@ -161,7 +161,7 @@ function frontierModelProtocol(opts) {
|
|
|
161
161
|
function incidentReport(opts) {
|
|
162
162
|
opts = opts || {};
|
|
163
163
|
if (typeof opts !== "object") throw new FrontierProtocolError("frontier/bad-opts", "incidentReport: opts must be an object");
|
|
164
|
-
if (!CRITICAL_INCIDENT_TYPES
|
|
164
|
+
if (!Object.prototype.hasOwnProperty.call(CRITICAL_INCIDENT_TYPES, opts.type)) throw new FrontierProtocolError("frontier/bad-incident-type", "incidentReport: type must be one of " + Object.keys(CRITICAL_INCIDENT_TYPES).join(", "));
|
|
165
165
|
|
|
166
166
|
var discoveredMs;
|
|
167
167
|
if (opts.discoveredAt == null) discoveredMs = Date.now();
|
|
@@ -95,7 +95,7 @@ function _validateDataComponent(d, idx) {
|
|
|
95
95
|
"build.datasets[" + idx + "]: must be an object");
|
|
96
96
|
}
|
|
97
97
|
_requireString(d, "name", "build.datasets[" + idx + "]");
|
|
98
|
-
if (d.type !== undefined && !VALID_DATA_TYPES
|
|
98
|
+
if (d.type !== undefined && !Object.prototype.hasOwnProperty.call(VALID_DATA_TYPES, d.type)) {
|
|
99
99
|
throw new AiModelManifestError("aibom/bad-dataset-type",
|
|
100
100
|
"build.datasets[" + idx + "].type '" + d.type + "' not in CycloneDX 1.6 data-type vocabulary");
|
|
101
101
|
}
|
|
@@ -59,14 +59,18 @@ var NEUTRALIZED_URL = "about:blank#blocked";
|
|
|
59
59
|
// matched (we only need the URL to gate it). Reference-style definitions
|
|
60
60
|
// ([id]: url) are caught by the third pattern so EchoLeak reference-link
|
|
61
61
|
// payloads don't slip past.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
// The `d` (hasIndices) flag is required so _rewriteUrls can splice at the
|
|
63
|
+
// captured URL's EXACT offset — when a markdown alt text equals its target URL
|
|
64
|
+
// (``), locating the URL by m[0].indexOf would hit the alt-text copy and
|
|
65
|
+
// leave the real exfiltration target intact (EchoLeak bypass).
|
|
66
|
+
var MD_IMAGE_RE = /!\[[^\]]{0,2048}\]\(\s{0,256}([^)\s]+)/dg;
|
|
67
|
+
var MD_LINK_RE = /(?<!!)\[[^\]]{0,2048}\]\(\s{0,256}([^)\s]+)/dg;
|
|
68
|
+
var MD_REF_RE = /^[ \t]{0,3}\[[^\]]+\]:\s*(\S+)/dgm;
|
|
65
69
|
// HTML src= / href= attribute URL extractor — the guardHtml pass already
|
|
66
70
|
// strips dangerous markup, but a surviving same-origin-looking src that
|
|
67
71
|
// points at an internal / metadata host must still be neutralized for
|
|
68
72
|
// the auto-fetch exfiltration class.
|
|
69
|
-
var HTML_URL_ATTR_RE = /\b(?:src|href)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^"'>\s]+))/
|
|
73
|
+
var HTML_URL_ATTR_RE = /\b(?:src|href)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^"'>\s]+))/dgi;
|
|
70
74
|
|
|
71
75
|
// SQL-shaped fragment signal. Composes safe-sql's reserved-word stance:
|
|
72
76
|
// a leading SQL keyword followed by a clause keyword is the executable
|
|
@@ -143,11 +147,16 @@ function _rewriteUrls(text, re, onUrl) {
|
|
|
143
147
|
var last = 0;
|
|
144
148
|
var m;
|
|
145
149
|
while ((m = re.exec(text)) !== null) {
|
|
146
|
-
var
|
|
147
|
-
|
|
150
|
+
var g = m[1] !== undefined ? 1 : (m[2] !== undefined ? 2 : (m[3] !== undefined ? 3 : 0));
|
|
151
|
+
var url = g ? m[g] : null;
|
|
152
|
+
if (!url) { if (re.lastIndex === m.index) re.lastIndex += 1; continue; }
|
|
148
153
|
var replacement = onUrl(url);
|
|
149
154
|
if (replacement !== null && replacement !== url) {
|
|
150
|
-
|
|
155
|
+
// Splice at the captured group's EXACT offset (hasIndices), never
|
|
156
|
+
// m[0].indexOf(url) — when a markdown alt text equals its target URL the
|
|
157
|
+
// indexOf would hit the alt copy and leave the real URL intact (EchoLeak).
|
|
158
|
+
var span = m.indices && m.indices[g];
|
|
159
|
+
var idx = span ? span[0] : (m.index + m[0].lastIndexOf(url));
|
|
151
160
|
out += text.slice(last, idx) + replacement;
|
|
152
161
|
last = idx + url.length;
|
|
153
162
|
}
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
*/
|
|
52
52
|
|
|
53
53
|
var nodeFs = require("node:fs");
|
|
54
|
+
var atomicFile = require("./atomic-file");
|
|
54
55
|
var numericBounds = require("./numeric-bounds");
|
|
55
56
|
var safeJson = require("./safe-json");
|
|
56
57
|
var { FrameworkError } = require("./framework-error");
|
|
@@ -199,7 +200,9 @@ function write(snapshot, filePath) {
|
|
|
199
200
|
createdAt: snapshot.createdAt,
|
|
200
201
|
exports: snapshot.exports,
|
|
201
202
|
};
|
|
202
|
-
|
|
203
|
+
// Atomic, symlink-refusing write (0o644 — the snapshot is a public,
|
|
204
|
+
// committed artifact). writeSync stages into a no-follow exclusive temp.
|
|
205
|
+
atomicFile.writeSync(filePath, JSON.stringify(canonical, null, 2) + "\n", { fileMode: 0o644 });
|
|
203
206
|
return filePath;
|
|
204
207
|
}
|
|
205
208
|
|
|
@@ -511,6 +511,7 @@ function standardPhases(components) {
|
|
|
511
511
|
// IS the lock.
|
|
512
512
|
var nodeFs = require("node:fs");
|
|
513
513
|
var nodePath = require("node:path");
|
|
514
|
+
var atomicFile = require("./atomic-file");
|
|
514
515
|
|
|
515
516
|
/**
|
|
516
517
|
* @primitive b.appShutdown.pidLock
|
|
@@ -552,7 +553,12 @@ function pidLock(lockPath) {
|
|
|
552
553
|
|
|
553
554
|
function _readExisting() {
|
|
554
555
|
try {
|
|
555
|
-
|
|
556
|
+
// fd-safe + capped + symlink-refusing read: a PID lockfile is never a
|
|
557
|
+
// legitimate symlink (unlike a k8s/certbot secret mount), so refuseSymlink
|
|
558
|
+
// is safe here and stops a planted symlink/oversized file from redirecting
|
|
559
|
+
// or OOM-ing the read. Any throw (symlink/too-large/enoent) → null, the
|
|
560
|
+
// existing "no live lock" semantic.
|
|
561
|
+
var raw = atomicFile.fdSafeReadSync(lockPath, { maxBytes: C.BYTES.kib(1), refuseSymlink: true, encoding: "utf8" });
|
|
556
562
|
var pid = parseInt(String(raw).trim(), 10);
|
|
557
563
|
return isFinite(pid) && pid > 0 ? pid : null;
|
|
558
564
|
} catch (_e) { return null; }
|
|
@@ -149,6 +149,15 @@ function readGz(adapter, opts) {
|
|
|
149
149
|
throw new ArchiveGzError("archive-gz/empty-input",
|
|
150
150
|
"read.gz: adapter reports empty payload");
|
|
151
151
|
}
|
|
152
|
+
// Cap the raw COMPRESSED read before allocating — `adapter.range(0, size)`
|
|
153
|
+
// does Buffer.allocUnsafe(size) of an fstat/HEAD-reported length, which a
|
|
154
|
+
// hostile .gz (or an objectStore/HTTP source advertising a huge size) can
|
|
155
|
+
// drive to OOM. maxOutputBytes bounds the DECOMPRESSED output only; this
|
|
156
|
+
// bounds the compressed read too, matching archive-tar-read's _collectAdapterBytes.
|
|
157
|
+
if (typeof maxOutputBytes === "number" && size > maxOutputBytes) {
|
|
158
|
+
throw new ArchiveGzError("archive-gz/source-too-large",
|
|
159
|
+
"read.gz: random-access source size=" + size + " exceeds the read cap " + maxOutputBytes);
|
|
160
|
+
}
|
|
152
161
|
return adapter.range(0, size);
|
|
153
162
|
}
|
|
154
163
|
if (adapter.kind === "trusted-sequential") {
|
|
@@ -908,13 +908,15 @@ function zip(adapter, opts) {
|
|
|
908
908
|
"cumulative uncompressed=" + totalDecompressed +
|
|
909
909
|
" exceeds maxTotalDecompressedBytes during extract");
|
|
910
910
|
}
|
|
911
|
-
// Write entry to disk.
|
|
912
|
-
//
|
|
913
|
-
//
|
|
914
|
-
//
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
911
|
+
// Write entry to disk atomically. The previous hand-rolled form
|
|
912
|
+
// staged into a PREDICTABLE temp name (resolvedPath +
|
|
913
|
+
// ".__blamejs-archive-read-tmp__") via a plain writeFileSync, so a
|
|
914
|
+
// symlink pre-planted at that exact path would be followed (CWE-59
|
|
915
|
+
// arbitrary write outside the extract dir). writeSync stages into a
|
|
916
|
+
// CSPRNG temp opened O_EXCL | O_NOFOLLOW, then renames — a partial
|
|
917
|
+
// write during inflate also never leaves a half-file at the canonical
|
|
918
|
+
// name. The pre-existence check above keeps the rename non-clobbering.
|
|
919
|
+
atomicFile.writeSync(resolvedPath, body);
|
|
918
920
|
written.push({ name: entry.name, bytesWritten: body.length, path: resolvedPath });
|
|
919
921
|
bytesExtracted += body.length;
|
|
920
922
|
}
|
|
@@ -99,13 +99,43 @@ function _parsePaxRecords(buf) {
|
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
// A PAX `size` attribute is an attacker-controlled ASCII string. `parseInt` of
|
|
103
|
+
// a malformed value ("", "abc", "1e9") yields NaN, which then SILENTLY bypasses
|
|
104
|
+
// the entry-size bomb check (`NaN > maxEntryDecompressedBytes` is false) AND
|
|
105
|
+
// desyncs the block walker (`Math.ceil(NaN / BLOCK_SIZE)` is NaN, so `pos`
|
|
106
|
+
// advances by NaN). Reject anything that is not a plain non-negative integer.
|
|
107
|
+
function _paxSize(raw) {
|
|
108
|
+
var s = String(raw).trim();
|
|
109
|
+
var n = parseInt(s, 10);
|
|
110
|
+
// Round-trip: a clean non-negative integer survives parseInt → String
|
|
111
|
+
// unchanged. This rejects "", "abc" (NaN), "1e9", "100abc" (parseInt stops
|
|
112
|
+
// early), negatives, leading zeros, and astronomically long strings that
|
|
113
|
+
// overflow to Infinity (String(Infinity) !== s) — every shape that would
|
|
114
|
+
// otherwise yield NaN/garbage and bypass the bomb check + desync the walker.
|
|
115
|
+
if (!Number.isFinite(n) || n < 0 || String(n) !== s) {
|
|
116
|
+
throw new TarError("archive-tar/bad-pax-size",
|
|
117
|
+
"PAX size attribute " + JSON.stringify(raw) + " is not a non-negative integer");
|
|
118
|
+
}
|
|
119
|
+
return n;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function _collectAdapterBytes(adapter, maxBytes) {
|
|
103
123
|
if (adapter.kind === "random-access") {
|
|
104
124
|
var size = adapter.size;
|
|
105
125
|
if (size == null && typeof adapter.resolveSize === "function") {
|
|
106
126
|
size = await adapter.resolveSize();
|
|
107
127
|
}
|
|
108
|
-
if (typeof size !== "number" || size
|
|
128
|
+
if (typeof size !== "number" || !Number.isFinite(size) || size <= 0) return Buffer.alloc(0);
|
|
129
|
+
// Cap the random-access read the same way the trusted-sequential branch
|
|
130
|
+
// caps its collector — a multi-GiB adapter.range(0, size) is an OOM lever
|
|
131
|
+
// (the size comes from the adapter, e.g. an on-disk file's stat or an
|
|
132
|
+
// operator-supplied length). The default ceiling is the bomb policy's
|
|
133
|
+
// total-decompressed cap.
|
|
134
|
+
if (typeof maxBytes === "number" && size > maxBytes) {
|
|
135
|
+
throw new TarError("archive-tar/source-too-large",
|
|
136
|
+
"read.tar: random-access source size=" + size +
|
|
137
|
+
" exceeds the read cap " + maxBytes);
|
|
138
|
+
}
|
|
109
139
|
return adapter.range(0, size);
|
|
110
140
|
}
|
|
111
141
|
if (adapter.kind === "trusted-sequential") {
|
|
@@ -172,7 +202,7 @@ function tar(adapter, opts) {
|
|
|
172
202
|
var entryTypePolicy = _normalizeEntryTypePolicy(opts.entryTypePolicy);
|
|
173
203
|
|
|
174
204
|
async function _walk() {
|
|
175
|
-
var bytes = await _collectAdapterBytes(adapter);
|
|
205
|
+
var bytes = await _collectAdapterBytes(adapter, bombPolicy.maxTotalDecompressedBytes);
|
|
176
206
|
if (bytes.length === 0) return { entries: [], bytes: bytes };
|
|
177
207
|
var pos = 0;
|
|
178
208
|
var entries = [];
|
|
@@ -190,6 +220,16 @@ function tar(adapter, opts) {
|
|
|
190
220
|
zeroBlockCount = 0;
|
|
191
221
|
var hdr = _parseHeader(block);
|
|
192
222
|
if (hdr.typeflag === TF_PAX_EXTENDED || hdr.typeflag === TF_PAX_GLOBAL) {
|
|
223
|
+
// The per-entry bomb cap below (line ~252) is AFTER the PAX `continue`,
|
|
224
|
+
// so a PAX header body (its size is the attacker-controlled ustar octal
|
|
225
|
+
// field, up to ~8 GiB) escaped it — a multi-hundred-MiB UTF-8 string +
|
|
226
|
+
// record Object materialization above the cap operators set. Legitimate
|
|
227
|
+
// PAX/global bodies are tiny, so bound them by the same per-entry cap.
|
|
228
|
+
if (hdr.size > bombPolicy.maxEntryDecompressedBytes) {
|
|
229
|
+
throw new TarError("archive-tar/entry-too-large",
|
|
230
|
+
"pax header body size=" + hdr.size + " exceeds maxEntryDecompressedBytes=" +
|
|
231
|
+
bombPolicy.maxEntryDecompressedBytes);
|
|
232
|
+
}
|
|
193
233
|
var bodyEnd = pos + Math.ceil(hdr.size / BLOCK_SIZE) * BLOCK_SIZE;
|
|
194
234
|
if (bodyEnd > bytes.length) {
|
|
195
235
|
throw new TarError("archive-tar/truncated-entry",
|
|
@@ -206,12 +246,12 @@ function tar(adapter, opts) {
|
|
|
206
246
|
}
|
|
207
247
|
if (globalPax) {
|
|
208
248
|
if (globalPax.path) hdr.name = globalPax.path;
|
|
209
|
-
if (globalPax.size) hdr.size =
|
|
249
|
+
if (globalPax.size) hdr.size = _paxSize(globalPax.size);
|
|
210
250
|
if (globalPax.linkpath) hdr.linkname = globalPax.linkpath;
|
|
211
251
|
}
|
|
212
252
|
if (pendingPax) {
|
|
213
253
|
if (pendingPax.path) hdr.name = pendingPax.path;
|
|
214
|
-
if (pendingPax.size) hdr.size =
|
|
254
|
+
if (pendingPax.size) hdr.size = _paxSize(pendingPax.size);
|
|
215
255
|
if (pendingPax.linkpath) hdr.linkname = pendingPax.linkpath;
|
|
216
256
|
pendingPax = null;
|
|
217
257
|
}
|
|
@@ -416,9 +456,12 @@ function tar(adapter, opts) {
|
|
|
416
456
|
"cumulative uncompressed=" + totalDecompressed +
|
|
417
457
|
" exceeds maxTotalDecompressedBytes during extract");
|
|
418
458
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
459
|
+
// Atomic, symlink-refusing write. The previous hand-rolled form staged
|
|
460
|
+
// into a PREDICTABLE temp name (resolvedPath +
|
|
461
|
+
// ".__blamejs-archive-tar-tmp__") via a plain writeFileSync, so a
|
|
462
|
+
// symlink pre-planted at that exact path would be followed (CWE-59).
|
|
463
|
+
// writeSync uses a CSPRNG temp opened O_EXCL | O_NOFOLLOW + rename.
|
|
464
|
+
atomicFile.writeSync(resolvedPath, body);
|
|
422
465
|
written.push({ name: entry.name, bytesWritten: body.length, path: resolvedPath });
|
|
423
466
|
bytesExtracted += body.length;
|
|
424
467
|
}
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
* ZIP archive creation primitive.
|
|
53
53
|
*/
|
|
54
54
|
var zlib = require("node:zlib");
|
|
55
|
-
var nodeFs = require("node:fs");
|
|
56
55
|
var nodeCrypto = require("node:crypto");
|
|
57
56
|
var nodeStream = require("node:stream");
|
|
58
57
|
var streamPromises = require("node:stream/promises");
|
|
59
58
|
var C = require("./constants");
|
|
60
59
|
var { defineClass } = require("./framework-error");
|
|
61
60
|
var auditEmit = require("./audit-emit");
|
|
61
|
+
var atomicFile = require("./atomic-file");
|
|
62
62
|
|
|
63
63
|
var ArchiveError = defineClass("ArchiveError", { alwaysPermanent: true });
|
|
64
64
|
|
|
@@ -478,7 +478,9 @@ function zip() {
|
|
|
478
478
|
|
|
479
479
|
function writeTo(filepath) {
|
|
480
480
|
var buf = toBuffer();
|
|
481
|
-
|
|
481
|
+
// Atomic, symlink-refusing write (a bare writeFileSync follows a symlink
|
|
482
|
+
// planted at filepath and can leave a torn archive on a crash).
|
|
483
|
+
atomicFile.writeSync(filepath, buf, { fileMode: 0o600 });
|
|
482
484
|
return buf.length;
|
|
483
485
|
}
|
|
484
486
|
|
|
@@ -79,13 +79,25 @@ function readNode(buf, offset) {
|
|
|
79
79
|
// High-tag-number form (multi-byte tag). Walk continuation octets
|
|
80
80
|
// (each top bit set means another follows).
|
|
81
81
|
tag = 0;
|
|
82
|
+
var tagOctets = 0;
|
|
82
83
|
while (true) {
|
|
83
84
|
if (offset + headerLen >= buf.length) {
|
|
84
85
|
throw new Asn1Error("asn1/short", "tag continuation truncated");
|
|
85
86
|
}
|
|
86
87
|
var byte = buf[offset + headerLen];
|
|
88
|
+
if (tagOctets === 0 && byte === 0x80) { // leading 0x80 = non-minimal
|
|
89
|
+
throw new Asn1Error("asn1/tag-non-minimal",
|
|
90
|
+
"high-tag-number form has a non-minimal leading 0x80 octet");
|
|
91
|
+
}
|
|
87
92
|
headerLen += 1;
|
|
88
|
-
|
|
93
|
+
tagOctets += 1;
|
|
94
|
+
// Base-128 multiplication (NOT `tag << 7`, which coerces to 32-bit
|
|
95
|
+
// signed int and overflows to a negative/wrong tag past 2^28).
|
|
96
|
+
tag = (tag * 128) + (byte & 0x7f);
|
|
97
|
+
if (tag > Number.MAX_SAFE_INTEGER) {
|
|
98
|
+
throw new Asn1Error("asn1/tag-too-large",
|
|
99
|
+
"high-tag-number exceeds the safe-integer range");
|
|
100
|
+
}
|
|
89
101
|
if ((byte & 0x80) === 0) break; // continuation bit
|
|
90
102
|
}
|
|
91
103
|
}
|
|
@@ -161,29 +173,45 @@ function readOid(node) {
|
|
|
161
173
|
if (bytes.length === 0) {
|
|
162
174
|
throw new Asn1Error("asn1/oid-empty", "OID value is empty");
|
|
163
175
|
}
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
var
|
|
170
|
-
|
|
171
|
-
var i = 1;
|
|
176
|
+
// Decode every subidentifier as a full base-128 quantity (X.690 §8.19),
|
|
177
|
+
// rejecting non-minimal leading-0x80 padding and unterminated/oversized
|
|
178
|
+
// arcs. The FIRST subidentifier may itself span continuation octets
|
|
179
|
+
// (§8.19.4); only after decoding it do we split into the first two arcs.
|
|
180
|
+
var subids = [];
|
|
181
|
+
var i = 0;
|
|
172
182
|
while (i < bytes.length) {
|
|
173
183
|
var arc = 0;
|
|
174
184
|
var j = i;
|
|
185
|
+
var done = false;
|
|
175
186
|
while (j < bytes.length) {
|
|
176
187
|
var b = bytes[j];
|
|
188
|
+
if (j === i && b === 0x80) { // leading 0x80 = non-minimal
|
|
189
|
+
throw new Asn1Error("asn1/oid-non-minimal",
|
|
190
|
+
"OID subidentifier has a non-minimal leading 0x80 octet");
|
|
191
|
+
}
|
|
177
192
|
arc = (arc * 128) + (b & 0x7f); // base-128 OID arc
|
|
193
|
+
if (arc > Number.MAX_SAFE_INTEGER) {
|
|
194
|
+
throw new Asn1Error("asn1/oid-overflow",
|
|
195
|
+
"OID subidentifier exceeds the safe-integer range");
|
|
196
|
+
}
|
|
178
197
|
j += 1;
|
|
179
|
-
if ((b & 0x80) === 0) break;
|
|
198
|
+
if ((b & 0x80) === 0) { done = true; break; } // continuation bit
|
|
180
199
|
}
|
|
181
|
-
if (
|
|
200
|
+
if (!done) {
|
|
182
201
|
throw new Asn1Error("asn1/oid-malformed", "OID arc never terminated");
|
|
183
202
|
}
|
|
184
|
-
|
|
203
|
+
subids.push(arc);
|
|
185
204
|
i = j;
|
|
186
205
|
}
|
|
206
|
+
|
|
207
|
+
// Split the first subidentifier into the first two arcs (40*X + Y).
|
|
208
|
+
var firstSubid = subids[0];
|
|
209
|
+
var first, second;
|
|
210
|
+
if (firstSubid < 40) { first = 0; second = firstSubid; }
|
|
211
|
+
else if (firstSubid < 80) { first = 1; second = firstSubid - 40; }
|
|
212
|
+
else { first = 2; second = firstSubid - 80; }
|
|
213
|
+
var arcs = [String(first), String(second)];
|
|
214
|
+
for (var k = 1; k < subids.length; k += 1) arcs.push(String(subids[k]));
|
|
187
215
|
return arcs.join(".");
|
|
188
216
|
}
|
|
189
217
|
|
|
@@ -298,24 +326,44 @@ function writeInteger(buf) {
|
|
|
298
326
|
return writeNode(TAG.INTEGER, buf);
|
|
299
327
|
}
|
|
300
328
|
|
|
329
|
+
// Append `arc` to `bytes` as a base-128 subidentifier (X.690 §8.19), most-
|
|
330
|
+
// significant octet first, every octet but the last carrying the
|
|
331
|
+
// continuation bit. Uses integer division (not 32-bit `>>> 7`) so arcs
|
|
332
|
+
// beyond 2^31 encode correctly.
|
|
333
|
+
function _writeBase128Subid(arc, bytes) {
|
|
334
|
+
if (arc === 0) { bytes.push(0); return; }
|
|
335
|
+
var stack = [];
|
|
336
|
+
while (arc > 0) {
|
|
337
|
+
stack.unshift(arc % 128); // base-128 digit
|
|
338
|
+
arc = Math.floor(arc / 128);
|
|
339
|
+
}
|
|
340
|
+
for (var j = 0; j < stack.length - 1; j += 1) stack[j] |= 0x80; // continuation bit
|
|
341
|
+
for (var k = 0; k < stack.length; k += 1) bytes.push(stack[k]);
|
|
342
|
+
}
|
|
343
|
+
|
|
301
344
|
function writeOid(dotted) {
|
|
302
345
|
// Encode dotted-decimal OID per X.690 §8.19.
|
|
303
346
|
var parts = String(dotted).split(".").map(function (s) { return parseInt(s, 10); });
|
|
304
347
|
if (parts.length < 2) {
|
|
305
348
|
throw new Asn1Error("asn1/oid-too-short", "OID needs at least 2 arcs");
|
|
306
349
|
}
|
|
307
|
-
var
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (arc === 0) { bytes.push(0); continue; }
|
|
311
|
-
var stack = [];
|
|
312
|
-
while (arc > 0) {
|
|
313
|
-
stack.unshift(arc & 0x7f); // base-128 mask
|
|
314
|
-
arc = arc >>> 7; // base-128 shift
|
|
350
|
+
for (var p = 0; p < parts.length; p += 1) {
|
|
351
|
+
if (!Number.isInteger(parts[p]) || parts[p] < 0 || parts[p] > Number.MAX_SAFE_INTEGER) {
|
|
352
|
+
throw new Asn1Error("asn1/oid-bad-arc", "OID arc " + p + " is not a non-negative integer");
|
|
315
353
|
}
|
|
316
|
-
for (var j = 0; j < stack.length - 1; j += 1) stack[j] |= 0x80; // continuation bit
|
|
317
|
-
for (var k = 0; k < stack.length; k += 1) bytes.push(stack[k]);
|
|
318
354
|
}
|
|
355
|
+
if (parts[0] > 2) {
|
|
356
|
+
throw new Asn1Error("asn1/oid-bad-arc", "OID first arc must be 0, 1, or 2");
|
|
357
|
+
}
|
|
358
|
+
if (parts[0] < 2 && parts[1] >= 40) {
|
|
359
|
+
throw new Asn1Error("asn1/oid-bad-arc",
|
|
360
|
+
"OID second arc must be < 40 when the first arc is 0 or 1");
|
|
361
|
+
}
|
|
362
|
+
var bytes = [];
|
|
363
|
+
// The first two arcs share one subidentifier (40*X + Y), which may itself
|
|
364
|
+
// need multiple base-128 octets (e.g. 2.999 -> 1079).
|
|
365
|
+
_writeBase128Subid(parts[0] * 40 + parts[1], bytes);
|
|
366
|
+
for (var i = 2; i < parts.length; i += 1) _writeBase128Subid(parts[i], bytes);
|
|
319
367
|
return writeNode(TAG.OID, Buffer.from(bytes));
|
|
320
368
|
}
|
|
321
369
|
|