@blamejs/exceptd-skills 0.18.16 → 0.18.17
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 +26 -0
- package/data/_indexes/_meta.json +3 -3
- package/data/global-frameworks.json +1 -0
- package/lib/auto-discovery.js +10 -3
- package/lib/collectors/ai-api.js +10 -0
- package/lib/collectors/citation-hygiene.js +46 -4
- package/lib/collectors/cred-stores.js +10 -1
- package/lib/collectors/mcp.js +7 -1
- package/lib/collectors/runtime.js +11 -0
- package/lib/collectors/secrets.js +13 -2
- package/lib/cross-ref-api.js +56 -2
- package/lib/framework-gap.js +22 -1
- package/lib/playbook-runner.js +38 -3
- package/lib/prefetch.js +61 -15
- package/lib/refresh-external.js +16 -2
- package/lib/scoring.js +22 -3
- package/lib/source-ghsa.js +12 -4
- package/lib/source-osv.js +11 -4
- package/manifest.json +53 -53
- package/package.json +1 -1
- package/sbom.cdx.json +52 -52
- package/scripts/check-codebase-patterns.js +11 -0
- package/scripts/check-test-subjects.js +16 -1
- package/scripts/check-version-bump.js +35 -5
- package/sources/validators/cve-validator.js +5 -1
package/sbom.cdx.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.6",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:a669df68-9ee7-49b0-a6f6-a6af16e33aac",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "
|
|
7
|
+
"timestamp": "2114-06-23T07:25:28.000Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "blamejs",
|
|
11
11
|
"name": "scripts/refresh-sbom.js",
|
|
12
|
-
"version": "0.18.
|
|
12
|
+
"version": "0.18.17"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"component": {
|
|
16
|
-
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.18.
|
|
16
|
+
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.18.17",
|
|
17
17
|
"type": "application",
|
|
18
18
|
"name": "@blamejs/exceptd-skills",
|
|
19
|
-
"version": "0.18.
|
|
19
|
+
"version": "0.18.17",
|
|
20
20
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (459 CVEs / 181 CWEs / 805 ATT&CK + ICS / 170 ATLAS / 468 D3FEND / 8888 RFCs), 35 jurisdictions, 10-class catalog gap detector + budget gate, real XML parser + canonical-form diff + content-pattern regression detection, Ed25519-signed.",
|
|
21
21
|
"licenses": [
|
|
22
22
|
{
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.18.
|
|
28
|
+
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.18.17",
|
|
29
29
|
"hashes": [
|
|
30
30
|
{
|
|
31
31
|
"alg": "SHA-256",
|
|
32
|
-
"content": "
|
|
32
|
+
"content": "1318b262815af6ac5752134970991bbec0dca6f6123499630ac651aa58006dd5"
|
|
33
33
|
}
|
|
34
34
|
],
|
|
35
35
|
"externalReferences": [
|
|
36
36
|
{
|
|
37
37
|
"type": "distribution",
|
|
38
|
-
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.18.
|
|
38
|
+
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.18.17"
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"type": "vcs",
|
|
@@ -116,11 +116,11 @@
|
|
|
116
116
|
"hashes": [
|
|
117
117
|
{
|
|
118
118
|
"alg": "SHA-256",
|
|
119
|
-
"content": "
|
|
119
|
+
"content": "ba5db5165c011166420abc3a2bb4bfe76a2ee735092839e2e13d93fed7ef3ea1"
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
"alg": "SHA3-512",
|
|
123
|
-
"content": "
|
|
123
|
+
"content": "215b731e8432a2a94d762859600f09b757f504c4cd23fad8b5b9155c031859fb2a3cfe9bec6c45146567b068ceabd25233de55ca13fcb6314dd0ed0fec15c672"
|
|
124
124
|
}
|
|
125
125
|
]
|
|
126
126
|
},
|
|
@@ -416,11 +416,11 @@
|
|
|
416
416
|
"hashes": [
|
|
417
417
|
{
|
|
418
418
|
"alg": "SHA-256",
|
|
419
|
-
"content": "
|
|
419
|
+
"content": "20b18a851b3ab82e57cd159b49476d69fe544f02523398b2015189ab81c7c3f8"
|
|
420
420
|
},
|
|
421
421
|
{
|
|
422
422
|
"alg": "SHA3-512",
|
|
423
|
-
"content": "
|
|
423
|
+
"content": "cf9fbeb7612dee44871bf92f1c974fa448fb3371f5cd196d7bd2b236d4758f38bc2a77ae3cc471cd73ac4274d883d438d6ab8fcc352bff506c2817229bd53377"
|
|
424
424
|
}
|
|
425
425
|
]
|
|
426
426
|
},
|
|
@@ -986,11 +986,11 @@
|
|
|
986
986
|
"hashes": [
|
|
987
987
|
{
|
|
988
988
|
"alg": "SHA-256",
|
|
989
|
-
"content": "
|
|
989
|
+
"content": "e3592884030676bfc6449123fe65fd52541a03f9cc5cf069f6e63df60d0e03d3"
|
|
990
990
|
},
|
|
991
991
|
{
|
|
992
992
|
"alg": "SHA3-512",
|
|
993
|
-
"content": "
|
|
993
|
+
"content": "a396f9c1df33b1e10ccc94a91385e4d12da5e2ea38da9ee1f6f670364ff99a7a02cf6c8e04ed5adb01373f453246d63b8a1201fc6186298448047dc2fc481951"
|
|
994
994
|
}
|
|
995
995
|
]
|
|
996
996
|
},
|
|
@@ -1046,11 +1046,11 @@
|
|
|
1046
1046
|
"hashes": [
|
|
1047
1047
|
{
|
|
1048
1048
|
"alg": "SHA-256",
|
|
1049
|
-
"content": "
|
|
1049
|
+
"content": "81d2d7d668b9a4a7f088c5d0d2be98a6d84f30f0fb2370fc1552f523bada4c45"
|
|
1050
1050
|
},
|
|
1051
1051
|
{
|
|
1052
1052
|
"alg": "SHA3-512",
|
|
1053
|
-
"content": "
|
|
1053
|
+
"content": "8f29c5d05c1137917c6aa743a3803bc2e3130a1f255c723bf3bd7f87b4053635d3a067ae256ee089569229a68622faeb2a5660d3acc869a21940c665540c8197"
|
|
1054
1054
|
}
|
|
1055
1055
|
]
|
|
1056
1056
|
},
|
|
@@ -1076,11 +1076,11 @@
|
|
|
1076
1076
|
"hashes": [
|
|
1077
1077
|
{
|
|
1078
1078
|
"alg": "SHA-256",
|
|
1079
|
-
"content": "
|
|
1079
|
+
"content": "0563377693810171aec9aa5d73562e0dcf05a982cce298ab4aafa10ff442570d"
|
|
1080
1080
|
},
|
|
1081
1081
|
{
|
|
1082
1082
|
"alg": "SHA3-512",
|
|
1083
|
-
"content": "
|
|
1083
|
+
"content": "ddaf110edfa4ce1d3ce3a7a4794554d3faf1721f818343008028c3544d1403809b1c336d6f89a29d3d470ab66a66b23c275c5f80b7ed2b89e7fa321196a847b7"
|
|
1084
1084
|
}
|
|
1085
1085
|
]
|
|
1086
1086
|
},
|
|
@@ -1106,11 +1106,11 @@
|
|
|
1106
1106
|
"hashes": [
|
|
1107
1107
|
{
|
|
1108
1108
|
"alg": "SHA-256",
|
|
1109
|
-
"content": "
|
|
1109
|
+
"content": "6b75a971b4db38b8b693893121b9704478d18182e73b2a3d324d7f6509eec6b0"
|
|
1110
1110
|
},
|
|
1111
1111
|
{
|
|
1112
1112
|
"alg": "SHA3-512",
|
|
1113
|
-
"content": "
|
|
1113
|
+
"content": "aa3dd740a72c0073d87ef2ab9868963cb6ed0dde71bac66edef434042a09dab7f6154882cab7c3ee2a250fce875cefcd90a4c15680324eb057c5c3a16baef103"
|
|
1114
1114
|
}
|
|
1115
1115
|
]
|
|
1116
1116
|
},
|
|
@@ -1196,11 +1196,11 @@
|
|
|
1196
1196
|
"hashes": [
|
|
1197
1197
|
{
|
|
1198
1198
|
"alg": "SHA-256",
|
|
1199
|
-
"content": "
|
|
1199
|
+
"content": "7daee73eab185c024321d18c22f268fe37b489467da9e3cb4ab9a7c100b0bbec"
|
|
1200
1200
|
},
|
|
1201
1201
|
{
|
|
1202
1202
|
"alg": "SHA3-512",
|
|
1203
|
-
"content": "
|
|
1203
|
+
"content": "399b0b252b6d1c185a6078e78816584687a4f0d83644964bee9a9bbcfd0f30a3e51dfbc962018adbcc49bc860e1d4f49f69392a26c84824f75718136223eb9ef"
|
|
1204
1204
|
}
|
|
1205
1205
|
]
|
|
1206
1206
|
},
|
|
@@ -1211,11 +1211,11 @@
|
|
|
1211
1211
|
"hashes": [
|
|
1212
1212
|
{
|
|
1213
1213
|
"alg": "SHA-256",
|
|
1214
|
-
"content": "
|
|
1214
|
+
"content": "882206c6ab43971c1561bb162468d26ff46e3affdbd536edf7dd0f39813d265c"
|
|
1215
1215
|
},
|
|
1216
1216
|
{
|
|
1217
1217
|
"alg": "SHA3-512",
|
|
1218
|
-
"content": "
|
|
1218
|
+
"content": "da0c7b482fc1790ed5b4cac00703133a4f3f9eed5888478426f13a1e30fb5d1ba21cff9ff927974203dedf167d67a5c9529011a0e124f9b6631efa59f45b12f6"
|
|
1219
1219
|
}
|
|
1220
1220
|
]
|
|
1221
1221
|
},
|
|
@@ -1256,11 +1256,11 @@
|
|
|
1256
1256
|
"hashes": [
|
|
1257
1257
|
{
|
|
1258
1258
|
"alg": "SHA-256",
|
|
1259
|
-
"content": "
|
|
1259
|
+
"content": "6cb25dd2529d87922b2867caf9847efe392f551bc9b7201b089d303ec0bbfc5e"
|
|
1260
1260
|
},
|
|
1261
1261
|
{
|
|
1262
1262
|
"alg": "SHA3-512",
|
|
1263
|
-
"content": "
|
|
1263
|
+
"content": "598b63a7525e87363e57389de9a7c471370630b0dd4d5708236897ca324969afdb742c7698a690b926b0d025c45e30496d4652c9143ddd21c8d2f14cd2a5fa7a"
|
|
1264
1264
|
}
|
|
1265
1265
|
]
|
|
1266
1266
|
},
|
|
@@ -1271,11 +1271,11 @@
|
|
|
1271
1271
|
"hashes": [
|
|
1272
1272
|
{
|
|
1273
1273
|
"alg": "SHA-256",
|
|
1274
|
-
"content": "
|
|
1274
|
+
"content": "2745253dcd37d4fad715822782b51b1ecbdae8c57f7b87020c702fbd42139ee2"
|
|
1275
1275
|
},
|
|
1276
1276
|
{
|
|
1277
1277
|
"alg": "SHA3-512",
|
|
1278
|
-
"content": "
|
|
1278
|
+
"content": "99288b8c52ac608808648dd577b532c6bc8feea4d75d5878e61096c68f9088c45714fc362ef844bca9c7cea275cb63c0bca51ae6066080bf495cb660c354e366"
|
|
1279
1279
|
}
|
|
1280
1280
|
]
|
|
1281
1281
|
},
|
|
@@ -1391,11 +1391,11 @@
|
|
|
1391
1391
|
"hashes": [
|
|
1392
1392
|
{
|
|
1393
1393
|
"alg": "SHA-256",
|
|
1394
|
-
"content": "
|
|
1394
|
+
"content": "b424f20ced1c3dd04ddbe9b619589d15612afed8ede27cbd0e5e607c4413bc0c"
|
|
1395
1395
|
},
|
|
1396
1396
|
{
|
|
1397
1397
|
"alg": "SHA3-512",
|
|
1398
|
-
"content": "
|
|
1398
|
+
"content": "2fad9d2dd2098f3ee6ecab410bd217cfe626d237fce5ae3b637e3c4d9c6385f3fcfb53ebfa6a35c4f8a9e16d7ef79277fdae8a9235fb3f4b6cc4cbdcd15294f7"
|
|
1399
1399
|
}
|
|
1400
1400
|
]
|
|
1401
1401
|
},
|
|
@@ -1466,11 +1466,11 @@
|
|
|
1466
1466
|
"hashes": [
|
|
1467
1467
|
{
|
|
1468
1468
|
"alg": "SHA-256",
|
|
1469
|
-
"content": "
|
|
1469
|
+
"content": "1831ac95db126ce8c7484fd00e72af15d9dadbde2760df1bd464b999155fe835"
|
|
1470
1470
|
},
|
|
1471
1471
|
{
|
|
1472
1472
|
"alg": "SHA3-512",
|
|
1473
|
-
"content": "
|
|
1473
|
+
"content": "6ff829a0527ced16b0dab613cead773929bcb7bda298a9533d0d8e97330ea71a97d3ee9893c4d23a86c3b2cd858174ac42cdbcb02e5edc5b5b604bc05b1b4b0c"
|
|
1474
1474
|
}
|
|
1475
1475
|
]
|
|
1476
1476
|
},
|
|
@@ -1481,11 +1481,11 @@
|
|
|
1481
1481
|
"hashes": [
|
|
1482
1482
|
{
|
|
1483
1483
|
"alg": "SHA-256",
|
|
1484
|
-
"content": "
|
|
1484
|
+
"content": "bc754f99d1bb551f014544e9d457791dc414fc8937e33f88402b8339e5d2ab67"
|
|
1485
1485
|
},
|
|
1486
1486
|
{
|
|
1487
1487
|
"alg": "SHA3-512",
|
|
1488
|
-
"content": "
|
|
1488
|
+
"content": "173edd3e912a39832f02efdaea50f6b4a28487ab6cd11fec42711f040123a12b7e1d830593c4230bc053035a93907422bc66bc986755b1716fbbadab68da854c"
|
|
1489
1489
|
}
|
|
1490
1490
|
]
|
|
1491
1491
|
},
|
|
@@ -1496,11 +1496,11 @@
|
|
|
1496
1496
|
"hashes": [
|
|
1497
1497
|
{
|
|
1498
1498
|
"alg": "SHA-256",
|
|
1499
|
-
"content": "
|
|
1499
|
+
"content": "fd38ac9c367f81d64349fabc3ee329b4a22dfeb467e329d533de6cb67f7dd546"
|
|
1500
1500
|
},
|
|
1501
1501
|
{
|
|
1502
1502
|
"alg": "SHA3-512",
|
|
1503
|
-
"content": "
|
|
1503
|
+
"content": "a38f35d39d5df9a7aab0fd0e3b28427ee871a0c487970f500cac1205b566ab444c301066c1497f294f7af714e46638c1b98890c9d0b8825661758e2676fbb59f"
|
|
1504
1504
|
}
|
|
1505
1505
|
]
|
|
1506
1506
|
},
|
|
@@ -1601,11 +1601,11 @@
|
|
|
1601
1601
|
"hashes": [
|
|
1602
1602
|
{
|
|
1603
1603
|
"alg": "SHA-256",
|
|
1604
|
-
"content": "
|
|
1604
|
+
"content": "d168673402a5e2e72b58a5f682efb6bfd8b82fe45d7c9f00a8ac49b758560779"
|
|
1605
1605
|
},
|
|
1606
1606
|
{
|
|
1607
1607
|
"alg": "SHA3-512",
|
|
1608
|
-
"content": "
|
|
1608
|
+
"content": "c6e6e6b87712d7bd0730a837d2f7a50359d958a5beb8a33ed1d6e4a2d6263081429d790ec98f56cdd873978de0c08d52ff187c3a1874a5cbe5e62513e62c9a31"
|
|
1609
1609
|
}
|
|
1610
1610
|
]
|
|
1611
1611
|
},
|
|
@@ -1646,11 +1646,11 @@
|
|
|
1646
1646
|
"hashes": [
|
|
1647
1647
|
{
|
|
1648
1648
|
"alg": "SHA-256",
|
|
1649
|
-
"content": "
|
|
1649
|
+
"content": "95e9a694148e603420fc13210f1871ec5c71673b98a72687b7c5ee4afe08d066"
|
|
1650
1650
|
},
|
|
1651
1651
|
{
|
|
1652
1652
|
"alg": "SHA3-512",
|
|
1653
|
-
"content": "
|
|
1653
|
+
"content": "2fe26bebc37e82c694de624db45591087c52b73bac272f24eef017de21ba02c871933427f7f0e29b6aafa54f8ca0fed36f83d5bfc9cf6321ba4e17cc95633953"
|
|
1654
1654
|
}
|
|
1655
1655
|
]
|
|
1656
1656
|
},
|
|
@@ -1661,11 +1661,11 @@
|
|
|
1661
1661
|
"hashes": [
|
|
1662
1662
|
{
|
|
1663
1663
|
"alg": "SHA-256",
|
|
1664
|
-
"content": "
|
|
1664
|
+
"content": "affbff89838149de89b6cd3e1ccfd720ead90da8735c4475ea7a1bcd4e6312f1"
|
|
1665
1665
|
},
|
|
1666
1666
|
{
|
|
1667
1667
|
"alg": "SHA3-512",
|
|
1668
|
-
"content": "
|
|
1668
|
+
"content": "e9eea4ed5d2c238cf8eb51fc1f918e9bcdf72c998660474f8a274377ba335060465850d8876fc6fea6f32592aeac14376b9ad1b88bf1ddd9e8d04ab245db4719"
|
|
1669
1669
|
}
|
|
1670
1670
|
]
|
|
1671
1671
|
},
|
|
@@ -1901,11 +1901,11 @@
|
|
|
1901
1901
|
"hashes": [
|
|
1902
1902
|
{
|
|
1903
1903
|
"alg": "SHA-256",
|
|
1904
|
-
"content": "
|
|
1904
|
+
"content": "20836959eb7562901f9fb4445fa930f3e6b9890439eb97edefa00de23ff40d93"
|
|
1905
1905
|
},
|
|
1906
1906
|
{
|
|
1907
1907
|
"alg": "SHA3-512",
|
|
1908
|
-
"content": "
|
|
1908
|
+
"content": "cab2fb9df9cca2d52bcc4c466cd3f8d9387ad1d768bdcb3a1f0bf6db396009f3b8b1c41c532e2e0f1df487f024657ccfe2d8218106123d9f32dd1ddcccaabb49"
|
|
1909
1909
|
}
|
|
1910
1910
|
]
|
|
1911
1911
|
},
|
|
@@ -2366,11 +2366,11 @@
|
|
|
2366
2366
|
"hashes": [
|
|
2367
2367
|
{
|
|
2368
2368
|
"alg": "SHA-256",
|
|
2369
|
-
"content": "
|
|
2369
|
+
"content": "d0b57da174483089efbf20181c3ea43152eb002ae42dfc9a33a153562537cd02"
|
|
2370
2370
|
},
|
|
2371
2371
|
{
|
|
2372
2372
|
"alg": "SHA3-512",
|
|
2373
|
-
"content": "
|
|
2373
|
+
"content": "a138c111c0c17f3a1883b51359bd2a29aac1a044a0f9f194b56163bff0c33332f51691a3e0b5585a9adbb909105308978e007522d673c01dcbc4c5e2b882ffc3"
|
|
2374
2374
|
}
|
|
2375
2375
|
]
|
|
2376
2376
|
},
|
|
@@ -2456,11 +2456,11 @@
|
|
|
2456
2456
|
"hashes": [
|
|
2457
2457
|
{
|
|
2458
2458
|
"alg": "SHA-256",
|
|
2459
|
-
"content": "
|
|
2459
|
+
"content": "5d9d5fe4a2c58f1bada78b28d8f17fe05aa66aa0874c4f802e4295d10c2d87a1"
|
|
2460
2460
|
},
|
|
2461
2461
|
{
|
|
2462
2462
|
"alg": "SHA3-512",
|
|
2463
|
-
"content": "
|
|
2463
|
+
"content": "cb90b9bdbfaca2ce24d5a14bed33e49a39e9022e5f8c51cfa79a658899064ec525cd8f4c63e19d015139581d2d22268ae8a4bda885bde9a9150b67f8ea43c39b"
|
|
2464
2464
|
}
|
|
2465
2465
|
]
|
|
2466
2466
|
},
|
|
@@ -2471,11 +2471,11 @@
|
|
|
2471
2471
|
"hashes": [
|
|
2472
2472
|
{
|
|
2473
2473
|
"alg": "SHA-256",
|
|
2474
|
-
"content": "
|
|
2474
|
+
"content": "997cbd87ac54147cd8c4dd502ace121f99254156857ff0075c17d88265dfb21a"
|
|
2475
2475
|
},
|
|
2476
2476
|
{
|
|
2477
2477
|
"alg": "SHA3-512",
|
|
2478
|
-
"content": "
|
|
2478
|
+
"content": "f9f0b44749cf0cba50eb009df8ec29d5e89274fa8df85add89f6ee5557be23d9f4aec9f84ece9a57a1c8fa56033583a6aea424d468d95e351ea2f86e3c0df0eb"
|
|
2479
2479
|
}
|
|
2480
2480
|
]
|
|
2481
2481
|
},
|
|
@@ -3536,11 +3536,11 @@
|
|
|
3536
3536
|
"hashes": [
|
|
3537
3537
|
{
|
|
3538
3538
|
"alg": "SHA-256",
|
|
3539
|
-
"content": "
|
|
3539
|
+
"content": "6deef99c16d4ba41846c64d8ce5668fe0c3200cac8665be0b036e4f0f2d30a11"
|
|
3540
3540
|
},
|
|
3541
3541
|
{
|
|
3542
3542
|
"alg": "SHA3-512",
|
|
3543
|
-
"content": "
|
|
3543
|
+
"content": "0e872fb6add28c917b0cae102c5e17a5e2fe7b9de2bd7e65b3ea8373580a6e817dcc73eb3a1dd9dd0e57b06582d8ecb7b232d8da2cfed413c6b1a96795f774ef"
|
|
3544
3544
|
}
|
|
3545
3545
|
]
|
|
3546
3546
|
},
|
|
@@ -564,6 +564,17 @@ const CLASSES = [
|
|
|
564
564
|
];
|
|
565
565
|
|
|
566
566
|
function main() {
|
|
567
|
+
// Fail closed if the scan universe is empty. Each detector scopes to a subset
|
|
568
|
+
// of these roots and silently finds no hits when its root list is
|
|
569
|
+
// unreadable/empty — so a wholesale missing source tree would make every
|
|
570
|
+
// class report "clean" and the gate pass without scanning anything (the
|
|
571
|
+
// absent-input false-pass class). Refuse to call zero-files-scanned "clean".
|
|
572
|
+
const universe = filesUnder(["bin/exceptd.js", "lib", "orchestrator", "scripts"]);
|
|
573
|
+
if (universe.length === 0) {
|
|
574
|
+
console.error("[check-codebase-patterns] FAIL — zero source files found under bin/lib/orchestrator/scripts; refusing to report clean without scanning anything.");
|
|
575
|
+
process.exitCode = 1;
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
567
578
|
let hardFail = 0;
|
|
568
579
|
let warnTotal = 0;
|
|
569
580
|
let n = 0;
|
|
@@ -91,7 +91,13 @@ function deriveSubjects() {
|
|
|
91
91
|
try { const cat = JSON.parse(read("data/cve-catalog.json")); for (const k of Object.keys(cat)) if (k !== "_meta") { add(k.toLowerCase(), "cve-primitive"); cveDerived++; } }
|
|
92
92
|
catch (e) { throw new Error("check-test-subjects: cannot read/parse data/cve-catalog.json — refusing to derive subjects (reverse coverage would falsely pass with no CVE coverage): " + e.message); }
|
|
93
93
|
if (cveDerived === 0) throw new Error("check-test-subjects: data/cve-catalog.json yielded zero CVE entries — refusing to let reverse coverage pass with no CVE coverage.");
|
|
94
|
-
|
|
94
|
+
// Playbook-primitive subjects. Mirror the CVE-catalog guard above: an
|
|
95
|
+
// unreadable / empty data/playbooks must NOT silently derive zero playbook
|
|
96
|
+
// subjects — that lets the reverse-coverage gate pass with no playbook
|
|
97
|
+
// coverage (the same absent-input false-pass class). Fail loud instead.
|
|
98
|
+
let pbDerived = 0;
|
|
99
|
+
for (const e of ls("data/playbooks")) if (e.isFile() && e.name.endsWith(".json")) { const b = e.name.replace(/\.json$/, ""); add(b, "playbook-primitive"); add("playbook-" + b, "alias:playbook"); pbDerived++; }
|
|
100
|
+
if (pbDerived === 0) throw new Error("check-test-subjects: data/playbooks/ yielded zero playbooks — refusing to let reverse coverage pass with no playbook coverage.");
|
|
95
101
|
// workflows
|
|
96
102
|
for (const e of ls(".github/workflows")) if (/\.ya?ml$/.test(e.name)) { const b = e.name.replace(/\.ya?ml$/, ""); add(b, "workflow"); add(b + "-workflow", "workflow"); }
|
|
97
103
|
|
|
@@ -110,6 +116,15 @@ function deriveSubjects() {
|
|
|
110
116
|
add("playbooks", "aggregate:data/playbooks");
|
|
111
117
|
add("workflows", "aggregate:.github/workflows");
|
|
112
118
|
add("governance", "repo:governance-files"); // LICENSE/NOTICE/FUNDING/CoC/gitignore/gitleaks presence + integrity
|
|
119
|
+
// Module-subject floor. The source walk over lib/orchestrator/scripts/bin
|
|
120
|
+
// uses ls(), which returns [] on a read failure — so an unreadable source
|
|
121
|
+
// tree would derive zero reverse-required module subjects and let the gate
|
|
122
|
+
// pass with no module coverage (the absent-input false-pass class, same as
|
|
123
|
+
// the CVE/playbook guards). The repo always has dozens of modules; zero is an
|
|
124
|
+
// anomaly. Fail loud.
|
|
125
|
+
let moduleCount = 0;
|
|
126
|
+
for (const kind of subjects.values()) if (typeof kind === "string" && kind.startsWith("module:")) moduleCount++;
|
|
127
|
+
if (moduleCount === 0) throw new Error("check-test-subjects: zero source-module subjects derived (lib/orchestrator/scripts/bin unreadable?) — refusing to let reverse coverage pass with no module coverage.");
|
|
113
128
|
return subjects;
|
|
114
129
|
}
|
|
115
130
|
|
|
@@ -107,6 +107,25 @@ function suggestPatch(prev) {
|
|
|
107
107
|
return a ? `${a.major}.${a.minor}.${a.patch + 1}` : null;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// Resolve the previous version from CHANGELOG text, or fail closed. Pure;
|
|
111
|
+
// exported for unit tests. A release gate must NOT treat an unreadable or
|
|
112
|
+
// heading-less CHANGELOG as a "first release" — doing so silently authorized
|
|
113
|
+
// ANY bump (including an unapproved major), because checkBump(null, ...) takes
|
|
114
|
+
// the initial-release pass. `text` is the CHANGELOG contents, or null when the
|
|
115
|
+
// read failed. Returns { ok, prev?, reason? }: ok:false fails the gate; ok:true
|
|
116
|
+
// yields prev, which is null ONLY for a genuine first release whose sole
|
|
117
|
+
// `## X.Y.Z` heading equals cur (versions === [cur]).
|
|
118
|
+
function determinePrevious(text, cur) {
|
|
119
|
+
if (text == null) {
|
|
120
|
+
return { ok: false, reason: 'CHANGELOG.md could not be read' };
|
|
121
|
+
}
|
|
122
|
+
const versions = changelogVersions(text);
|
|
123
|
+
if (versions.length === 0) {
|
|
124
|
+
return { ok: false, reason: 'no `## X.Y.Z` headings found in CHANGELOG.md — cannot determine previous version' };
|
|
125
|
+
}
|
|
126
|
+
return { ok: true, prev: versions.find((v) => v !== cur) || null };
|
|
127
|
+
}
|
|
128
|
+
|
|
110
129
|
function readAck() {
|
|
111
130
|
if (!fs.existsSync(ACK_PATH)) return null;
|
|
112
131
|
try {
|
|
@@ -130,11 +149,22 @@ function main() {
|
|
|
130
149
|
}
|
|
131
150
|
const cur = pkg.version;
|
|
132
151
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
152
|
+
// Fail closed when CHANGELOG is unreadable or carries no version headings.
|
|
153
|
+
// Swallowing a read error to '' previously made versions=[] -> prev=null ->
|
|
154
|
+
// checkBump's initial-release pass, so a missing/malformed CHANGELOG silently
|
|
155
|
+
// authorized any bump. A genuine first release still passes: its sole
|
|
156
|
+
// `## X.Y.Z` heading equals cur, so determinePrevious returns prev=null with
|
|
157
|
+
// ok:true and checkBump takes the legitimate initial path.
|
|
158
|
+
let changelogText = null;
|
|
159
|
+
try { changelogText = fs.readFileSync(CHANGELOG_PATH, 'utf8'); } catch (_e) { changelogText = null; }
|
|
160
|
+
const prevRes = determinePrevious(changelogText, cur);
|
|
161
|
+
if (!prevRes.ok) {
|
|
162
|
+
process.stderr.write(`[check-version-bump] FAIL — ${prevRes.reason}; failing closed (cannot validate cadence).\n`);
|
|
163
|
+
process.exitCode = 1;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
136
166
|
// prev = the most recent heading that differs from the current version.
|
|
137
|
-
const prev =
|
|
167
|
+
const prev = prevRes.prev;
|
|
138
168
|
|
|
139
169
|
const ack = readAck();
|
|
140
170
|
const res = checkBump(prev, cur, ack);
|
|
@@ -170,4 +200,4 @@ function main() {
|
|
|
170
200
|
|
|
171
201
|
if (require.main === module) main();
|
|
172
202
|
|
|
173
|
-
module.exports = { classifyBump, checkBump, changelogVersions };
|
|
203
|
+
module.exports = { classifyBump, checkBump, changelogVersions, determinePrevious };
|
|
@@ -145,7 +145,11 @@ function extractEpss(epssJson, cveId) {
|
|
|
145
145
|
// FIRST EPSS response shape: { status: "OK", data: [ { cve, epss, percentile, date } ] }
|
|
146
146
|
const data = Array.isArray(epssJson?.data) ? epssJson.data : [];
|
|
147
147
|
if (data.length === 0) return null;
|
|
148
|
-
|
|
148
|
+
// Match by id. The old `|| data[0]` blanket fallback attributed a DIFFERENT
|
|
149
|
+
// CVE's EPSS to this id when the payload held another CVE's row; accept the
|
|
150
|
+
// single-row fallback only for a keyless legacy payload.
|
|
151
|
+
let row = data.find(r => r?.cve === cveId);
|
|
152
|
+
if (!row && data.length === 1 && data[0]?.cve == null) row = data[0];
|
|
149
153
|
if (!row) return null;
|
|
150
154
|
// EPSS returns strings; coerce defensively.
|
|
151
155
|
const score = row.epss !== undefined && row.epss !== null ? Number(row.epss) : null;
|