@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.
Files changed (297) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/admin.js +8 -6
  3. package/lib/asset-manifest.json +1 -1
  4. package/lib/security-middleware.js +65 -23
  5. package/lib/storefront.js +10 -7
  6. package/lib/vendor/MANIFEST.json +319 -267
  7. package/lib/vendor/blamejs/CHANGELOG.md +2 -0
  8. package/lib/vendor/blamejs/api-snapshot.json +58 -5
  9. package/lib/vendor/blamejs/examples/wiki/README.md +1 -1
  10. package/lib/vendor/blamejs/examples/wiki/docker-compose.prod.yml +9 -8
  11. package/lib/vendor/blamejs/examples/wiki/docker-compose.yml +10 -9
  12. package/lib/vendor/blamejs/examples/wiki/env-snapshot.json +4 -3
  13. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +33 -17
  14. package/lib/vendor/blamejs/examples/wiki/routes/admin.js +7 -10
  15. package/lib/vendor/blamejs/examples/wiki/server.js +5 -4
  16. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +5 -0
  17. package/lib/vendor/blamejs/lib/a2a-tasks.js +38 -6
  18. package/lib/vendor/blamejs/lib/agent-event-bus.js +13 -0
  19. package/lib/vendor/blamejs/lib/agent-idempotency.js +5 -1
  20. package/lib/vendor/blamejs/lib/agent-snapshot.js +32 -2
  21. package/lib/vendor/blamejs/lib/ai-aedt-bias-audit.js +2 -1
  22. package/lib/vendor/blamejs/lib/ai-content-detect.js +1 -3
  23. package/lib/vendor/blamejs/lib/ai-frontier-protocol.js +1 -1
  24. package/lib/vendor/blamejs/lib/ai-model-manifest.js +1 -1
  25. package/lib/vendor/blamejs/lib/ai-output.js +16 -7
  26. package/lib/vendor/blamejs/lib/api-snapshot.js +4 -1
  27. package/lib/vendor/blamejs/lib/app-shutdown.js +7 -1
  28. package/lib/vendor/blamejs/lib/archive-gz.js +9 -0
  29. package/lib/vendor/blamejs/lib/archive-read.js +9 -7
  30. package/lib/vendor/blamejs/lib/archive-tar-read.js +51 -8
  31. package/lib/vendor/blamejs/lib/archive.js +4 -2
  32. package/lib/vendor/blamejs/lib/asn1-der.js +70 -22
  33. package/lib/vendor/blamejs/lib/atomic-file.js +204 -2
  34. package/lib/vendor/blamejs/lib/audit-chain.js +54 -5
  35. package/lib/vendor/blamejs/lib/audit-daily-review.js +12 -2
  36. package/lib/vendor/blamejs/lib/audit-sign.js +2 -1
  37. package/lib/vendor/blamejs/lib/audit-tools.js +108 -23
  38. package/lib/vendor/blamejs/lib/audit.js +7 -2
  39. package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -2
  40. package/lib/vendor/blamejs/lib/auth/bot-challenge.js +1 -1
  41. package/lib/vendor/blamejs/lib/auth/ciba.js +43 -4
  42. package/lib/vendor/blamejs/lib/auth/dpop.js +6 -1
  43. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +5 -1
  44. package/lib/vendor/blamejs/lib/auth/jwt.js +2 -2
  45. package/lib/vendor/blamejs/lib/auth/lockout.js +18 -2
  46. package/lib/vendor/blamejs/lib/auth/passkey.js +1 -1
  47. package/lib/vendor/blamejs/lib/auth/password.js +1 -1
  48. package/lib/vendor/blamejs/lib/auth/saml.js +33 -13
  49. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +24 -4
  50. package/lib/vendor/blamejs/lib/auth/status-list.js +14 -2
  51. package/lib/vendor/blamejs/lib/auth/step-up.js +9 -1
  52. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +21 -2
  53. package/lib/vendor/blamejs/lib/backup/bundle.js +7 -2
  54. package/lib/vendor/blamejs/lib/backup/crypto.js +23 -8
  55. package/lib/vendor/blamejs/lib/backup/index.js +41 -20
  56. package/lib/vendor/blamejs/lib/backup/manifest.js +7 -1
  57. package/lib/vendor/blamejs/lib/break-glass.js +41 -22
  58. package/lib/vendor/blamejs/lib/cbor.js +34 -11
  59. package/lib/vendor/blamejs/lib/cdn-cache-control.js +7 -3
  60. package/lib/vendor/blamejs/lib/cert.js +5 -3
  61. package/lib/vendor/blamejs/lib/cli.js +5 -1
  62. package/lib/vendor/blamejs/lib/cloud-events.js +3 -2
  63. package/lib/vendor/blamejs/lib/cluster-storage.js +7 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +17 -0
  65. package/lib/vendor/blamejs/lib/compliance-eaa.js +1 -1
  66. package/lib/vendor/blamejs/lib/compliance-sanctions.js +9 -7
  67. package/lib/vendor/blamejs/lib/compliance.js +1 -1
  68. package/lib/vendor/blamejs/lib/config-drift.js +22 -8
  69. package/lib/vendor/blamejs/lib/content-credentials.js +11 -8
  70. package/lib/vendor/blamejs/lib/content-digest.js +11 -4
  71. package/lib/vendor/blamejs/lib/cookies.js +10 -2
  72. package/lib/vendor/blamejs/lib/cose.js +20 -0
  73. package/lib/vendor/blamejs/lib/crdt.js +2 -1
  74. package/lib/vendor/blamejs/lib/crypto-field.js +29 -23
  75. package/lib/vendor/blamejs/lib/crypto.js +18 -4
  76. package/lib/vendor/blamejs/lib/csp.js +4 -0
  77. package/lib/vendor/blamejs/lib/daemon.js +4 -1
  78. package/lib/vendor/blamejs/lib/data-act.js +27 -4
  79. package/lib/vendor/blamejs/lib/db-file-lifecycle.js +14 -6
  80. package/lib/vendor/blamejs/lib/db-query.js +69 -9
  81. package/lib/vendor/blamejs/lib/db.js +32 -15
  82. package/lib/vendor/blamejs/lib/dora.js +43 -13
  83. package/lib/vendor/blamejs/lib/dr-runbook.js +1 -1
  84. package/lib/vendor/blamejs/lib/dsa.js +2 -1
  85. package/lib/vendor/blamejs/lib/dsr.js +22 -8
  86. package/lib/vendor/blamejs/lib/early-hints.js +19 -0
  87. package/lib/vendor/blamejs/lib/eat.js +5 -1
  88. package/lib/vendor/blamejs/lib/external-db.js +60 -4
  89. package/lib/vendor/blamejs/lib/fda-21cfr11.js +30 -5
  90. package/lib/vendor/blamejs/lib/flag-providers.js +6 -2
  91. package/lib/vendor/blamejs/lib/forms.js +1 -1
  92. package/lib/vendor/blamejs/lib/gate-contract.js +46 -5
  93. package/lib/vendor/blamejs/lib/gdpr-ropa.js +18 -9
  94. package/lib/vendor/blamejs/lib/graphql-federation.js +17 -4
  95. package/lib/vendor/blamejs/lib/guard-all.js +2 -2
  96. package/lib/vendor/blamejs/lib/guard-dsn.js +1 -1
  97. package/lib/vendor/blamejs/lib/guard-envelope.js +1 -1
  98. package/lib/vendor/blamejs/lib/guard-html.js +9 -11
  99. package/lib/vendor/blamejs/lib/guard-imap-command.js +1 -1
  100. package/lib/vendor/blamejs/lib/guard-jmap.js +1 -1
  101. package/lib/vendor/blamejs/lib/guard-json.js +14 -6
  102. package/lib/vendor/blamejs/lib/guard-mail-move.js +1 -1
  103. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +1 -1
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +1 -1
  105. package/lib/vendor/blamejs/lib/guard-smtp-command.js +1 -1
  106. package/lib/vendor/blamejs/lib/guard-svg.js +8 -9
  107. package/lib/vendor/blamejs/lib/html-balance.js +7 -3
  108. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +33 -12
  109. package/lib/vendor/blamejs/lib/http-client.js +225 -53
  110. package/lib/vendor/blamejs/lib/iab-tcf.js +3 -2
  111. package/lib/vendor/blamejs/lib/importmap-integrity.js +41 -1
  112. package/lib/vendor/blamejs/lib/incident-report.js +9 -6
  113. package/lib/vendor/blamejs/lib/json-patch.js +1 -1
  114. package/lib/vendor/blamejs/lib/json-path.js +24 -3
  115. package/lib/vendor/blamejs/lib/jtd.js +2 -2
  116. package/lib/vendor/blamejs/lib/legal-hold.js +24 -8
  117. package/lib/vendor/blamejs/lib/log.js +2 -2
  118. package/lib/vendor/blamejs/lib/mail-agent.js +2 -2
  119. package/lib/vendor/blamejs/lib/mail-arf.js +1 -1
  120. package/lib/vendor/blamejs/lib/mail-auth.js +3 -3
  121. package/lib/vendor/blamejs/lib/mail-bimi.js +16 -16
  122. package/lib/vendor/blamejs/lib/mail-bounce.js +3 -3
  123. package/lib/vendor/blamejs/lib/mail-crypto-smime.js +71 -6
  124. package/lib/vendor/blamejs/lib/mail-deploy.js +9 -5
  125. package/lib/vendor/blamejs/lib/mail-greylist.js +2 -4
  126. package/lib/vendor/blamejs/lib/mail-helo.js +2 -4
  127. package/lib/vendor/blamejs/lib/mail-journal.js +11 -8
  128. package/lib/vendor/blamejs/lib/mail-mdn.js +8 -4
  129. package/lib/vendor/blamejs/lib/mail-rbl.js +2 -4
  130. package/lib/vendor/blamejs/lib/mail-scan.js +3 -5
  131. package/lib/vendor/blamejs/lib/mail-server-jmap.js +4 -1
  132. package/lib/vendor/blamejs/lib/mail-server-registry.js +1 -1
  133. package/lib/vendor/blamejs/lib/mail-server-tls.js +9 -2
  134. package/lib/vendor/blamejs/lib/mail-spam-score.js +2 -4
  135. package/lib/vendor/blamejs/lib/mail-store-fts.js +1 -1
  136. package/lib/vendor/blamejs/lib/mail.js +22 -2
  137. package/lib/vendor/blamejs/lib/markup-tokenizer.js +24 -0
  138. package/lib/vendor/blamejs/lib/mcp.js +6 -4
  139. package/lib/vendor/blamejs/lib/mdoc.js +26 -3
  140. package/lib/vendor/blamejs/lib/metrics.js +14 -3
  141. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +2 -2
  142. package/lib/vendor/blamejs/lib/middleware/body-parser.js +10 -4
  143. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +26 -18
  144. package/lib/vendor/blamejs/lib/middleware/clear-site-data.js +5 -1
  145. package/lib/vendor/blamejs/lib/middleware/compression.js +9 -0
  146. package/lib/vendor/blamejs/lib/middleware/cors.js +32 -23
  147. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +60 -21
  148. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +6 -4
  149. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +28 -4
  150. package/lib/vendor/blamejs/lib/middleware/network-allowlist.js +61 -30
  151. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +25 -16
  152. package/lib/vendor/blamejs/lib/middleware/scim-server.js +2 -1
  153. package/lib/vendor/blamejs/lib/middleware/security-headers.js +24 -6
  154. package/lib/vendor/blamejs/lib/middleware/speculation-rules.js +6 -3
  155. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +2 -2
  156. package/lib/vendor/blamejs/lib/money.js +1 -1
  157. package/lib/vendor/blamejs/lib/mtls-ca.js +10 -6
  158. package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
  159. package/lib/vendor/blamejs/lib/network-dns.js +9 -2
  160. package/lib/vendor/blamejs/lib/network-dnssec.js +2 -1
  161. package/lib/vendor/blamejs/lib/network-smtp-policy.js +23 -5
  162. package/lib/vendor/blamejs/lib/network-tls.js +27 -5
  163. package/lib/vendor/blamejs/lib/network-tsig.js +2 -2
  164. package/lib/vendor/blamejs/lib/nis2-report.js +1 -1
  165. package/lib/vendor/blamejs/lib/nist-crosswalk.js +1 -1
  166. package/lib/vendor/blamejs/lib/ntp-check.js +28 -0
  167. package/lib/vendor/blamejs/lib/numeric-bounds.js +9 -0
  168. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -2
  169. package/lib/vendor/blamejs/lib/object-store/gcs-bucket-ops.js +4 -2
  170. package/lib/vendor/blamejs/lib/object-store/gcs.js +6 -4
  171. package/lib/vendor/blamejs/lib/object-store/http-put.js +1 -2
  172. package/lib/vendor/blamejs/lib/object-store/http-request.js +30 -1
  173. package/lib/vendor/blamejs/lib/object-store/local.js +37 -17
  174. package/lib/vendor/blamejs/lib/object-store/sigv4.js +1 -2
  175. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +20 -4
  176. package/lib/vendor/blamejs/lib/outbox.js +11 -4
  177. package/lib/vendor/blamejs/lib/parsers/safe-xml.js +1 -1
  178. package/lib/vendor/blamejs/lib/parsers/safe-yaml.js +21 -3
  179. package/lib/vendor/blamejs/lib/queue-local.js +10 -3
  180. package/lib/vendor/blamejs/lib/redact.js +7 -3
  181. package/lib/vendor/blamejs/lib/request-helpers.js +201 -23
  182. package/lib/vendor/blamejs/lib/resource-access-lock.js +3 -3
  183. package/lib/vendor/blamejs/lib/restore-bundle.js +46 -18
  184. package/lib/vendor/blamejs/lib/restore-rollback.js +10 -4
  185. package/lib/vendor/blamejs/lib/restore.js +19 -0
  186. package/lib/vendor/blamejs/lib/retention.js +20 -4
  187. package/lib/vendor/blamejs/lib/router.js +17 -4
  188. package/lib/vendor/blamejs/lib/safe-ical.js +2 -2
  189. package/lib/vendor/blamejs/lib/safe-icap.js +1 -1
  190. package/lib/vendor/blamejs/lib/safe-json.js +44 -0
  191. package/lib/vendor/blamejs/lib/safe-sieve.js +1 -1
  192. package/lib/vendor/blamejs/lib/safe-vcard.js +1 -1
  193. package/lib/vendor/blamejs/lib/sandbox-worker.js +6 -0
  194. package/lib/vendor/blamejs/lib/sandbox.js +1 -1
  195. package/lib/vendor/blamejs/lib/scheduler.js +17 -1
  196. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +16 -0
  197. package/lib/vendor/blamejs/lib/session.js +27 -3
  198. package/lib/vendor/blamejs/lib/sql.js +3 -3
  199. package/lib/vendor/blamejs/lib/static.js +65 -13
  200. package/lib/vendor/blamejs/lib/template.js +7 -5
  201. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -19
  202. package/lib/vendor/blamejs/lib/tsa.js +5 -2
  203. package/lib/vendor/blamejs/lib/vault/index.js +5 -0
  204. package/lib/vendor/blamejs/lib/vault/passphrase-ops.js +22 -26
  205. package/lib/vendor/blamejs/lib/vault/passphrase-source.js +8 -3
  206. package/lib/vendor/blamejs/lib/vault/rotate.js +13 -18
  207. package/lib/vendor/blamejs/lib/vault/seal-pem-file.js +4 -1
  208. package/lib/vendor/blamejs/lib/vc.js +1 -1
  209. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +10 -10
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +23 -10
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5498 -5494
  212. package/lib/vendor/blamejs/lib/webhook.js +16 -1
  213. package/lib/vendor/blamejs/lib/websocket.js +1 -1
  214. package/lib/vendor/blamejs/lib/worm.js +1 -1
  215. package/lib/vendor/blamejs/lib/ws-client.js +57 -46
  216. package/lib/vendor/blamejs/lib/x509-chain.js +44 -0
  217. package/lib/vendor/blamejs/package.json +1 -1
  218. package/lib/vendor/blamejs/release-notes/v0.15.14.json +122 -0
  219. package/lib/vendor/blamejs/scripts/check-vendor-currency.js +119 -4
  220. package/lib/vendor/blamejs/test/00-primitives.js +5 -1
  221. package/lib/vendor/blamejs/test/integration/mail-crypto-smime.test.js +18 -4
  222. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +42 -0
  223. package/lib/vendor/blamejs/test/layer-0-primitives/agent-event-bus.test.js +36 -0
  224. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  225. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +47 -0
  226. package/lib/vendor/blamejs/test/layer-0-primitives/archive-gz.test.js +24 -0
  227. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-hardening.test.js +160 -0
  228. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +45 -0
  229. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-fd-read.test.js +30 -0
  230. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-open-nofollow.test.js +79 -0
  231. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-excl.test.js +132 -0
  232. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-write-stream.test.js +181 -0
  233. package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-corrupted-anchor.test.js +65 -0
  234. package/lib/vendor/blamejs/test/layer-0-primitives/audit-chain-incremental-verify.test.js +83 -0
  235. package/lib/vendor/blamejs/test/layer-0-primitives/audit-daily-review.test.js +48 -1
  236. package/lib/vendor/blamejs/test/layer-0-primitives/audit-signing-key-rotation.test.js +13 -3
  237. package/lib/vendor/blamejs/test/layer-0-primitives/audit-verifybundle-tamper.test.js +122 -0
  238. package/lib/vendor/blamejs/test/layer-0-primitives/auth-bot-challenge.test.js +37 -0
  239. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +5 -3
  240. package/lib/vendor/blamejs/test/layer-0-primitives/auth-lockout.test.js +21 -0
  241. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +73 -0
  242. package/lib/vendor/blamejs/test/layer-0-primitives/bot-guard.test.js +17 -0
  243. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +62 -3
  244. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +12 -0
  245. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-storage.test.js +40 -0
  246. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +146 -5
  247. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +14 -0
  248. package/lib/vendor/blamejs/test/layer-0-primitives/compression-range.test.js +115 -0
  249. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +17 -5
  250. package/lib/vendor/blamejs/test/layer-0-primitives/cors.test.js +27 -5
  251. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-per-row-key.test.js +83 -0
  252. package/lib/vendor/blamejs/test/layer-0-primitives/csrf-protect.test.js +58 -0
  253. package/lib/vendor/blamejs/test/layer-0-primitives/data-act.test.js +30 -0
  254. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +74 -0
  255. package/lib/vendor/blamejs/test/layer-0-primitives/dora.test.js +20 -6
  256. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-alg-kty.test.js +64 -0
  257. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +32 -0
  258. package/lib/vendor/blamejs/test/layer-0-primitives/fda-21cfr11.test.js +43 -0
  259. package/lib/vendor/blamejs/test/layer-0-primitives/fetch-metadata.test.js +30 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/graphql-federation.test.js +33 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +34 -0
  262. package/lib/vendor/blamejs/test/layer-0-primitives/guard-json.test.js +12 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +72 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-throttle-transform.test.js +88 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/importmap-integrity.test.js +25 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/legal-hold.test.js +28 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +20 -0
  268. package/lib/vendor/blamejs/test/layer-0-primitives/mail-header-injection.test.js +58 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/mail-journal.test.js +63 -9
  270. package/lib/vendor/blamejs/test/layer-0-primitives/mdoc.test.js +41 -14
  271. package/lib/vendor/blamejs/test/layer-0-primitives/network-allowlist.test.js +61 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/object-store-range-header.test.js +51 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/otlp-attr-redaction.test.js +35 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/output-header-hardening.test.js +102 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/parser-verify-hardening.test.js +191 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/proto-shadow-allowlist.test.js +120 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +75 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +128 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/restore-blob-remap.test.js +128 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/retention-sweep-termination.test.js +104 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/router-body-validation.test.js +98 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json-stringify-for-script.test.js +43 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/saml-subjectconfirmation-notonorafter.test.js +48 -5
  284. package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +23 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +54 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/session-extensions.test.js +24 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +42 -1
  288. package/lib/vendor/blamejs/test/layer-0-primitives/step-up.test.js +7 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/template-escape-html.test.js +43 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +15 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/vault-default-store.test.js +48 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/vendor-currency-classify.test.js +77 -0
  293. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +50 -0
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +22 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/x509-chain-ca-enforcement.test.js +149 -0
  296. package/lib/vendor/blamejs/test/layer-5-integration/external-db-residency.test.js +34 -0
  297. 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
- if (v && v.aad && typeof v.aad.seal === "function" && typeof v.aad.unseal === "function") {
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 (typeof v !== "number" || !isFinite(v) || v < 0 || Math.floor(v) !== v) throw new AedtBiasAuditError("aedt/bad-count", "aedtBiasAudit: " + label + " must be a non-negative integer");
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
- function compliancePosture(posture) {
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[opts.type]) throw new FrontierProtocolError("frontier/bad-incident-type", "incidentReport: type must be one of " + Object.keys(CRITICAL_INCIDENT_TYPES).join(", "));
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[d.type]) {
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
- var MD_IMAGE_RE = /!\[[^\]]{0,2048}\]\(\s{0,256}([^)\s]+)/g;
63
- var MD_LINK_RE = /(?<!!)\[[^\]]{0,2048}\]\(\s{0,256}([^)\s]+)/g;
64
- var MD_REF_RE = /^[ \t]{0,3}\[[^\]]+\]:\s*(\S+)/gm;
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
+ // (`![u](u)`), 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]+))/gi;
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 url = m[1] || m[2] || m[3];
147
- if (!url) continue;
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
- var idx = m.index + m[0].indexOf(url);
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
- nodeFs.writeFileSync(filePath, JSON.stringify(canonical, null, 2) + "\n", { mode: 0o644 });
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
- var raw = nodeFs.readFileSync(lockPath, "utf8");
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. Atomic rename via a tmp file so a
912
- // partial write during inflate doesn't leave a half-file at
913
- // the canonical name. Pre-existence check above guarantees
914
- // the rename targets a non-existent path.
915
- var tmpPath = resolvedPath + ".__blamejs-archive-read-tmp__";
916
- nodeFs.writeFileSync(tmpPath, body);
917
- atomicFile.renameWithRetry(tmpPath, resolvedPath);
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
- async function _collectAdapterBytes(adapter) {
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 === 0) return Buffer.alloc(0);
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 = parseInt(globalPax.size, 10);
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 = parseInt(pendingPax.size, 10);
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
- var tmpPath = resolvedPath + ".__blamejs-archive-tar-tmp__";
420
- nodeFs.writeFileSync(tmpPath, body);
421
- atomicFile.renameWithRetry(tmpPath, resolvedPath);
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
- nodeFs.writeFileSync(filepath, buf);
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
- tag = (tag << 7) | (byte & 0x7f); // base-128 tag bits
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
- // First two arcs are encoded as `40*X + Y`.
165
- var first = Math.floor(bytes[0] / 40); // OID encoding constant
166
- var second = bytes[0] % 40; // OID encoding constant
167
- // Per X.690, when first byte >= 80 the first arc is 2 and second is byte-80.
168
- if (first > 2) { first = 2; second = bytes[0] - 80; } // OID encoding constant
169
- var arcs = [String(first), String(second)];
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; // continuation bit
198
+ if ((b & 0x80) === 0) { done = true; break; } // continuation bit
180
199
  }
181
- if (j === i) {
200
+ if (!done) {
182
201
  throw new Asn1Error("asn1/oid-malformed", "OID arc never terminated");
183
202
  }
184
- arcs.push(String(arc));
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 bytes = [parts[0] * 40 + parts[1]]; // OID first-arc encoding
308
- for (var i = 2; i < parts.length; i += 1) {
309
- var arc = parts[i];
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