@blamejs/exceptd-skills 0.12.15 → 0.12.18
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 +136 -0
- package/bin/exceptd.js +395 -20
- package/data/_indexes/_meta.json +3 -3
- package/data/cve-catalog.json +1 -1
- package/data/playbooks/ai-api.json +27 -5
- package/data/playbooks/containers.json +34 -7
- package/data/playbooks/cred-stores.json +21 -4
- package/data/playbooks/crypto-codebase.json +29 -14
- package/data/playbooks/crypto.json +13 -3
- package/data/playbooks/framework.json +15 -3
- package/data/playbooks/hardening.json +24 -5
- package/data/playbooks/kernel.json +13 -3
- package/data/playbooks/library-author.json +21 -10
- package/data/playbooks/mcp.json +16 -4
- package/data/playbooks/runtime.json +20 -4
- package/data/playbooks/sbom.json +18 -5
- package/data/playbooks/secrets.json +33 -6
- package/lib/auto-discovery.js +70 -32
- package/lib/cve-curation.js +15 -9
- package/lib/prefetch.js +30 -8
- package/lib/refresh-network.js +40 -0
- package/lib/schemas/playbook.schema.json +7 -1
- package/lib/scoring.js +171 -11
- package/lib/sign.js +163 -2
- package/lib/validate-playbooks.js +46 -0
- package/lib/verify.js +149 -2
- package/manifest-snapshot.json +1 -1
- package/manifest-snapshot.sha256 +1 -1
- package/manifest.json +45 -40
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
- package/scripts/verify-shipped-tarball.js +35 -6
|
@@ -45,6 +45,19 @@ const path = require("path");
|
|
|
45
45
|
const os = require("os");
|
|
46
46
|
const { spawnSync } = require("child_process");
|
|
47
47
|
|
|
48
|
+
// v0.12.16 (audit I P1-1): mirror the byte-stability normalize() contract
|
|
49
|
+
// from lib/sign.js + lib/verify.js + lib/refresh-network.js. Duplicated
|
|
50
|
+
// (not require'd) to keep this script's dep surface minimal and to ensure
|
|
51
|
+
// a bug in the normalize() implementation in lib/ doesn't simultaneously
|
|
52
|
+
// disable both the source-tree-verify path AND the shipped-tarball-verify
|
|
53
|
+
// gate (we want at least one independent check). ANY change to normalize()
|
|
54
|
+
// in any of these four files must be mirrored in all of them.
|
|
55
|
+
function normalizeSkillBytes(buf) {
|
|
56
|
+
let s = Buffer.isBuffer(buf) ? buf.toString("utf8") : String(buf);
|
|
57
|
+
if (s.length > 0 && s.charCodeAt(0) === 0xFEFF) s = s.slice(1);
|
|
58
|
+
return Buffer.from(s.replace(/\r\n/g, "\n"), "utf8");
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
const ROOT = path.resolve(__dirname, "..");
|
|
49
62
|
|
|
50
63
|
function emit(msg) { process.stdout.write(`[verify-shipped-tarball] ${msg}\n`); }
|
|
@@ -221,22 +234,38 @@ try {
|
|
|
221
234
|
failures.push(`${s.name}: file not found at ${s.path}`);
|
|
222
235
|
continue;
|
|
223
236
|
}
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
// v0.12.16 (audit I P1-1): the prior code passed the raw file bytes
|
|
238
|
+
// directly to crypto.verify. lib/sign.js + lib/verify.js both NORMALIZE
|
|
239
|
+
// bytes (strip UTF-8 BOM, convert CRLF -> LF) before sign/verify, per
|
|
240
|
+
// the byte-stability contract in lib/verify.js's normalize() header.
|
|
241
|
+
// Without the same normalization here, this gate (which was added
|
|
242
|
+
// specifically to catch the v0.11.x signature regression class!) would
|
|
243
|
+
// itself report 0/38 on any tree where line-ending normalization
|
|
244
|
+
// touched the source between sign and pack — a Windows contributor
|
|
245
|
+
// with `core.autocrlf=true`, or a tool like Prettier between sign and
|
|
246
|
+
// pack. CLAUDE.md flags this as the recurring CRLF-bypass class.
|
|
247
|
+
const rawContent = fs.readFileSync(skillPath);
|
|
248
|
+
const normalizedContent = normalizeSkillBytes(rawContent);
|
|
249
|
+
const ok = crypto.verify(null, normalizedContent, pubKey, Buffer.from(s.signature, "base64"));
|
|
226
250
|
if (ok) pass++;
|
|
227
251
|
else {
|
|
228
252
|
fail_count++;
|
|
229
253
|
// Forensic detail: log size + sha256 of tarball-extracted content vs source-tree content
|
|
230
254
|
// so we can pinpoint which bytes changed between npm pack and what was signed.
|
|
231
|
-
|
|
255
|
+
// v0.12.16: forensic logging uses rawContent (pre-normalization
|
|
256
|
+
// bytes) so an operator inspecting failures sees the actual on-disk
|
|
257
|
+
// shape, but tarSha is computed over the NORMALIZED bytes that
|
|
258
|
+
// were actually fed to crypto.verify — making the comparison to
|
|
259
|
+
// sign-time bytes meaningful.
|
|
260
|
+
const tarSha = crypto.createHash("sha256").update(normalizedContent).digest("hex").slice(0, 16);
|
|
232
261
|
let srcSha = "<missing>", srcSize = 0, srcContent;
|
|
233
262
|
if (fs.existsSync(sourceSkillPath)) {
|
|
234
263
|
srcContent = fs.readFileSync(sourceSkillPath);
|
|
235
264
|
srcSize = srcContent.length;
|
|
236
|
-
srcSha = crypto.createHash("sha256").update(srcContent).digest("hex").slice(0, 16);
|
|
265
|
+
srcSha = crypto.createHash("sha256").update(normalizeSkillBytes(srcContent)).digest("hex").slice(0, 16);
|
|
237
266
|
}
|
|
238
|
-
const equal = srcContent &&
|
|
239
|
-
failures.push(`${s.name}: signature did not verify (tarball size=${
|
|
267
|
+
const equal = srcContent && rawContent.equals(srcContent) ? "equal" : "DIFFER";
|
|
268
|
+
failures.push(`${s.name}: signature did not verify (tarball size=${rawContent.length} sha-normalized=${tarSha}; source size=${srcSize} sha-normalized=${srcSha}; raw bytes ${equal})`);
|
|
240
269
|
}
|
|
241
270
|
}
|
|
242
271
|
|