@blamejs/blamejs-shop 0.4.89 → 0.4.90

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/core",
3
- "version": "0.15.19",
3
+ "version": "0.15.20",
4
4
  "description": "The Node framework that owns its stack.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "blamejs contributors",
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../scripts/release-notes-schema.json",
3
+ "version": "0.15.20",
4
+ "date": "2026-06-24",
5
+ "headline": "Vendored SBOM version fields are derived from the bundle so they cannot drift, and the Public Suffix List + @simplewebauthn/server bundles are refreshed",
6
+ "summary": "The vendor manifest recorded each bundled package's version in two scanner-facing places that were hand-maintained and could drift from the code actually shipped — the structured components[].version (the CycloneDX component versions) and the cpe string. Two had drifted: peculiar-pki's @peculiar/x509 component read 1.13.0 while the bundle shipped 2.0.0, and @noble/curves' cpe read 0.0.0 while the bundle shipped 2.2.0. A CVE scanner (Trivy / Grype / a CycloneDX export, or a consumer mirroring the manifest into its own SBOM) keys on those structured fields, so an advisory was matched against the wrong version — a false negative on a real fix or a false positive on a patched one. Both fields are corrected, the vendor-bundle script now derives them from the actually-installed package versions at bundle time so they cannot drift again, and a manifest gate fails the build if they ever disagree. Separately, the vendored Mozilla Public Suffix List is refreshed to the current upstream revision and @simplewebauthn/server is refreshed to 13.3.2.",
7
+ "sections": [
8
+ {
9
+ "heading": "Fixed",
10
+ "items": [
11
+ {
12
+ "title": "Vendored SBOM version metadata is bundle-derived, not hand-maintained",
13
+ "body": "lib/vendor/MANIFEST.json recorded each package's version in two places a CVE/SBOM scanner reads — the structured components[].version sub-object and the cpe string — both hand-maintained alongside the human version string, so they could (and did) drift from the bundled code. @peculiar/x509's component version read 1.13.0 while the bundle shipped 2.0.0; @noble/curves' cpe read 0.0.0 while the bundle shipped 2.2.0. Either drift makes a scanner match advisories against the wrong version. Both are corrected to the shipped versions, and the durable fix is structural: scripts/vendor-update.sh now writes both the structured component versions and the cpe version from the ACTUALLY-INSTALLED package versions captured at bundle time, so a maintainer can no longer update one field and forget the other. A smoke-time manifest gate additionally fails the build if any component or cpe version disagrees with the package version, catching a manual drift before it ships."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "heading": "Changed",
19
+ "items": [
20
+ {
21
+ "title": "Vendored Public Suffix List and @simplewebauthn/server refreshed",
22
+ "body": "The vendored Mozilla Public Suffix List is refreshed to the current upstream revision (used by b.publicSuffix for DMARC / BIMI / cookie-scope / same-site domain classification). @simplewebauthn/server is refreshed from 13.3.1 to 13.3.2, which improves WebAuthn attestation certificate-path validation; the published-tarball diff was reviewed (no install scripts, no network/eval, a self-contained code change) before re-vendoring."
23
+ }
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -203,6 +203,12 @@ ENTRY
203
203
  rm _pki-entry.mjs
204
204
  sed -i "1s|^|// Peculiar PKI — vendored @peculiar/x509 v${X509_VER} + pkijs v${PKIJS_VER}\n// License: MIT. Bundled with esbuild.\n// Exports: { pkijs, x509, crypto (node:webcrypto bound) }\n// Includes: reflect-metadata, pvutils, pvtsutils, asn1js, @peculiar/asn1-*\n// Used by lib/mtls-engine-default.js for pure-JS CA + PKCS#12 operations.\n|" lib/vendor/pki.cjs
205
205
  INSTALLED_VER="${X509_VER}+pkijs-${PKIJS_VER}"
206
+ # Structured SBOM component versions, derived from the ACTUALLY-INSTALLED
207
+ # package versions captured above — written into MANIFEST components[] below
208
+ # so the sub-object the CVE scanners key on can never drift from the bundle
209
+ # (issue #366). A scanner-facing fact must come from the install, not a hand
210
+ # edit.
211
+ COMPONENT_VERSIONS_JSON="{\"@peculiar/x509\":\"${X509_VER}\",\"pkijs\":\"${PKIJS_VER}\"}"
206
212
  ;;
207
213
 
208
214
  *)
@@ -213,14 +219,35 @@ ENTRY
213
219
  ;;
214
220
  esac
215
221
 
216
- # Update MANIFEST.json
217
- node -e "
222
+ # Update MANIFEST.json. COMPONENT_VERSIONS_JSON (set only for meta-bundles that
223
+ # carry a structured components[] sub-object, e.g. peculiar-pki) is passed via
224
+ # the environment so its JSON braces/quotes don't fight the bash interpolation
225
+ # into the inline node script.
226
+ COMPONENT_VERSIONS_JSON="${COMPONENT_VERSIONS_JSON:-}" node -e "
218
227
  var fs = require('fs');
219
228
  var m = JSON.parse(fs.readFileSync('$MANIFEST', 'utf8'));
220
229
  var pkg = '$PKG';
221
230
  if (m.packages[pkg]) {
222
231
  m.packages[pkg].version = '$INSTALLED_VER';
223
232
  m.packages[pkg].bundledAt = '$DATE';
233
+ // Derive structured SBOM component versions from the ACTUALLY-INSTALLED
234
+ // packages (issue #366) so components[].version — the field CycloneDX / Trivy
235
+ // / Grype key on — can never drift from the bundled version string.
236
+ var compJson = process.env.COMPONENT_VERSIONS_JSON || '';
237
+ if (compJson && m.packages[pkg].components) {
238
+ var comps = JSON.parse(compJson);
239
+ Object.keys(comps).forEach(function (c) {
240
+ if (m.packages[pkg].components[c]) { m.packages[pkg].components[c].version = comps[c]; }
241
+ });
242
+ }
243
+ // Keep the cpe version in sync with the install too — same SBOM-drift class
244
+ // as components[] (#366): the cpe string encodes the version in field 5
245
+ // (cpe:2.3:a:vendor:product:VERSION:...) and CVE scanners match against it.
246
+ if (typeof m.packages[pkg].cpe === 'string') {
247
+ var sv = (String('$INSTALLED_VER').match(/\d+\.\d+\.\d+/) || [null])[0];
248
+ var parts = m.packages[pkg].cpe.split(':');
249
+ if (sv && parts.length > 5) { parts[5] = sv; m.packages[pkg].cpe = parts.join(':'); }
250
+ }
224
251
  fs.writeFileSync('$MANIFEST', JSON.stringify(m, null, 2) + '\n');
225
252
  console.log('Updated MANIFEST.json: ' + pkg + ' -> ' + '$INSTALLED_VER');
226
253
  } else {
@@ -79,6 +79,52 @@ function run() {
79
79
  check("vendor manifest: " + name + " :: " + fk + " hash matches",
80
80
  declared[fk] === actual[fk]);
81
81
  }
82
+
83
+ // SBOM / CVE scanners (Trivy / Grype / a CycloneDX export) key on the
84
+ // STRUCTURED components[<pkg>].version, not the human version string. A
85
+ // hand-maintained components sub-object can drift from the version string
86
+ // (#366: the bundle moved @peculiar/x509 1.13.0 -> 2.0.0, the version
87
+ // string was updated to 2.0.0 but components still read 1.13.0, so any
88
+ // advisory in the (1.13.0, 2.0.0] range matched the wrong version). Nothing
89
+ // auto-derives components (refresh-vendor-manifest only refreshes hashes),
90
+ // so gate the consistency here: every structured component version MUST
91
+ // appear in the package's version string, making the drift un-shippable.
92
+ if (pkg.components && typeof pkg.version === "string") {
93
+ // Bind the structured component versions to the version string as a
94
+ // MULTISET, not a loose substring: the sorted list of component versions
95
+ // must equal the sorted list of semver tokens in the version string. A
96
+ // bare "does the component version appear in the string" check would let
97
+ // a component drift to a value that merely appears elsewhere in the string
98
+ // — e.g. setting @peculiar/x509 to pkijs's 3.4.0 passes indexOf against
99
+ // "2.0.0+pkijs-3.4.0" but the SBOM then reports the wrong x509 version.
100
+ // The multiset {3.4.0,3.4.0} != {2.0.0,3.4.0} catches it.
101
+ var compVers = Object.keys(pkg.components)
102
+ .map(function (cn) { return pkg.components[cn] && pkg.components[cn].version; })
103
+ .filter(function (v) { return typeof v === "string"; })
104
+ .sort();
105
+ var strVers = (pkg.version.match(/\d+\.\d+\.\d+/g) || []).slice().sort();
106
+ check("vendor manifest: " + name + " :: components[] versions [" + compVers.join(",") +
107
+ "] are exactly the semver tokens in the version string [" + strVers.join(",") + "]",
108
+ compVers.length === strVers.length &&
109
+ compVers.every(function (v, i) { return v === strVers[i]; }));
110
+ }
111
+
112
+ // The cpe (Common Platform Enumeration) string encodes the version in
113
+ // field 5 (cpe:2.3:a:vendor:product:VERSION:...) and CVE scanners match
114
+ // against it — the same SBOM-drift class as components[] (#366 sibling:
115
+ // @noble/curves shipped 2.2.0 but its cpe still read 0.0.0). Gate it: the
116
+ // cpe version must equal the package's (leading) semver, so a wrong-version
117
+ // CVE match can't ship.
118
+ if (typeof pkg.cpe === "string") {
119
+ var cpeM = /^cpe:2\.3:a:[^:]+:[^:]+:([^:]+):/.exec(pkg.cpe);
120
+ var cpeVer = cpeM ? cpeM[1] : null;
121
+ var pkgSemver = (String(pkg.version).match(/\d+\.\d+\.\d+/) || [null])[0];
122
+ if (cpeVer !== null && cpeVer !== "*" && pkgSemver !== null) {
123
+ check("vendor manifest: " + name + " :: cpe version (" + cpeVer +
124
+ ") matches the package version (" + pkgSemver + ")",
125
+ cpeVer === pkgSemver);
126
+ }
127
+ }
82
128
  }
83
129
  check("vendor manifest: scanned at least one hash",
84
130
  totalHashes > 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/blamejs-shop",
3
- "version": "0.4.89",
3
+ "version": "0.4.90",
4
4
  "description": "Open-source framework built on blamejs. Vendored stack, zero npm runtime deps, PQC-first crypto, security-on by default.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {