@blamejs/exceptd-skills 0.19.2 → 0.19.3
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 +14 -0
- package/data/_indexes/_meta.json +2 -2
- package/lib/validate-package.js +49 -1
- package/manifest.json +53 -53
- package/package.json +1 -1
- package/sbom.cdx.json +58 -20
- package/scripts/check-sbom-currency.js +5 -1
- package/scripts/refresh-sbom.js +84 -11
- package/scripts/release.js +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.3 — 2026-08-08
|
|
4
|
+
|
|
5
|
+
The SBOM's creation timestamp is a real date. It has to be reproducible, or the currency gate could never compare a committed artifact against a freshly generated one, and that reproducibility had been bought by folding the bundle hash into a date offset. The offset spanned 136 years, so the field routinely landed a century out — the shipped value read `2147-11-20`. It is now the release date the changelog declares for that version, which is both reproducible and true. Tooling that sorts, ages or expiry-checks SBOMs will read a sane value for the first time.
|
|
6
|
+
|
|
7
|
+
Two files that ship in every tarball are now hashed. npm includes `package.json` whether or not the file allowlist names it, and picks up `sources/README.md` on its own, so neither appeared in the inventory — including the one file that declares the executable entry point, the supported runtime floor and the dependency set. Both now carry SHA-256 and SHA3-512 entries and count toward the aggregate bundle digest, so a bundle verified against the SBOM covers 249 of the 268 files an operator receives rather than 247.
|
|
8
|
+
|
|
9
|
+
The SBOM says what it does not cover. The pre-computed index cache under `data/_indexes/` is deliberately excluded from per-file hashing — it is regenerated on demand, and pinning a hash would race any process that rebuilds it — but that reasoning existed only in a source comment, so an operator holding the artifact could not distinguish a partial inventory from a complete one. Two `exceptd:integrity:uncovered:*` properties now name the excluded prefix and the check that covers it instead. The publish gate additionally compares the real `npm pack` file list against the SBOM, so a file npm decides to ship that the allowlist never named fails a gate rather than shipping unhashed; the two files above are what it found.
|
|
10
|
+
|
|
11
|
+
Preparing a release no longer refreshes the test-count baseline before checking it. The refresh writes whatever count it observes, so a release that removed tests rebaselined downward and the shrinkage check — which runs later — then compared the new count against itself and passed. The check now runs first and stops the release on a drop; the refresh still follows it, so growth is still recorded.
|
|
12
|
+
|
|
13
|
+
The secret scanner's offline fallback moves to 8.30.1. It had been pinned to 8.21.2 while upstream reached 8.30.1, so an interruption to the release API would have scanned with a ruleset nine releases old and still reported success. The resolver now compares the two on every run and warns when they diverge, which is the part that was only ever a comment before.
|
|
14
|
+
|
|
15
|
+
The contributor Docker harness reports honestly. Checks that ask git what ships — line-ending coverage, tracked-file resolution — cannot answer in that image, because the repository directory is deliberately kept out of the build context so a contributor's history is never uploaded to a builder or written into an image layer. They were failing rather than saying so, which reads as a defect in the tree. They now skip with the reason stated, and the file-writing checks that were failing on directory ownership, plus the governance check that could not find files the image had excluded, work as intended. A skipped check is not a passing check: run the suite outside Docker, or read continuous integration, for the ones this image cannot cover. The ignore file previously claimed the repository directory was included when it was not, which is what made the gap look like an oversight rather than a decision.
|
|
16
|
+
|
|
3
17
|
## 0.19.2 — 2026-08-08
|
|
4
18
|
|
|
5
19
|
EPSS data on 115 catalog entries is corrected. A refresh had updated an entry's score without its percentile — and on 70 entries written a score with no percentile at all — leaving the two fields drawn from different daily publications. Because the percentile is the score's rank within its publication, the result was entries ranked in the top decile on a score that no longer supported it, which is the input exploit-prioritisation leans on hardest. Scores and percentiles are now written together. A new gate rejects any publication whose percentiles do not track its scores, requires an entry to carry both numbers or neither, and checks that the human-readable EPSS note on an entry restates the values the entry actually holds — 76 notes described an earlier publication than the fields beside them. The ordering check is a corruption detector rather than a provenance proof: it catches a stale value that contradicts the new score's rank, which is what a partial refresh produces, but two fields cannot be proven to share a publication from the catalog alone.
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-08-
|
|
3
|
+
"generated_at": "2026-08-08T19:32:48.059Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
5
|
"source_count": 64,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
7
|
+
"manifest.json": "ea761dae093a3f57552dc54d1c4cda0f8a0c1c48aac6a4fbaebf6f0fb1e89416",
|
|
8
8
|
"README.md": "0fa9b167172f104810e5ee6040f11ed741217f7a51c2552a15c69d2a15a164aa",
|
|
9
9
|
"data/atlas-ttps.json": "a14089671efcb4f06dd0f82d688fe49276c1370e167e4483d76e9c0a40ef41eb",
|
|
10
10
|
"data/attack-techniques.json": "6bc0619bcccceccc8d5c12aefa6c11197c625e5d7313e70474f2831e271b23f0",
|
package/lib/validate-package.js
CHANGED
|
@@ -106,6 +106,47 @@ function runNpmPack() {
|
|
|
106
106
|
return first;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/* SBOM coverage of the ACTUAL tarball.
|
|
110
|
+
*
|
|
111
|
+
* The SBOM's own completeness gate expands package.json `files`, but npm ships
|
|
112
|
+
* more than `files` names — package.json unconditionally, plus README files it
|
|
113
|
+
* collects itself. Those extras shipped unhashed and nothing noticed, because
|
|
114
|
+
* the generator and its checker both asked `files`: two sides agreeing on the
|
|
115
|
+
* same incomplete question. `npm pack` is the only authority on what actually
|
|
116
|
+
* ships, and this is the one gate holding its output, so the comparison belongs
|
|
117
|
+
* here.
|
|
118
|
+
*
|
|
119
|
+
* Exclusions are read from the SBOM's own declared properties instead of a
|
|
120
|
+
* second copy of the list, so a file can only be uncovered when the published
|
|
121
|
+
* artifact says out loud that it is. The single structural exception is the
|
|
122
|
+
* SBOM itself, which cannot contain its own hash.
|
|
123
|
+
*/
|
|
124
|
+
function sbomCoverageIssues(filePaths, sbom) {
|
|
125
|
+
const props = (sbom && sbom.metadata && sbom.metadata.properties) || [];
|
|
126
|
+
const uncoveredProp = props.find((p) => p && p.name === "exceptd:integrity:uncovered:prefix");
|
|
127
|
+
const uncoveredPrefixes = uncoveredProp
|
|
128
|
+
? String(uncoveredProp.value).split(",").map((s) => s.trim()).filter(Boolean)
|
|
129
|
+
: [];
|
|
130
|
+
const hashed = new Set(
|
|
131
|
+
((sbom && sbom.components) || [])
|
|
132
|
+
.filter((c) => c && typeof c["bom-ref"] === "string" && c["bom-ref"].startsWith("file:"))
|
|
133
|
+
.map((c) => c.name)
|
|
134
|
+
);
|
|
135
|
+
return filePaths
|
|
136
|
+
.filter(
|
|
137
|
+
(p) =>
|
|
138
|
+
p !== "sbom.cdx.json" &&
|
|
139
|
+
!hashed.has(p) &&
|
|
140
|
+
!uncoveredPrefixes.some((u) => p.startsWith(u))
|
|
141
|
+
)
|
|
142
|
+
.map(
|
|
143
|
+
(p) =>
|
|
144
|
+
`shipped file has no SHA in sbom.cdx.json and is not a declared exclusion: ${p} — ` +
|
|
145
|
+
`add it to ALWAYS_SHIPPED in scripts/refresh-sbom.js (and its mirror in ` +
|
|
146
|
+
`scripts/check-sbom-currency.js), then \`npm run refresh-sbom\``
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
109
150
|
function main() {
|
|
110
151
|
const issues = [];
|
|
111
152
|
|
|
@@ -155,6 +196,13 @@ function main() {
|
|
|
155
196
|
}
|
|
156
197
|
}
|
|
157
198
|
|
|
199
|
+
try {
|
|
200
|
+
const sbom = JSON.parse(fs.readFileSync(ABS("sbom.cdx.json"), "utf8"));
|
|
201
|
+
issues.push(...sbomCoverageIssues(filePaths, sbom));
|
|
202
|
+
} catch (err) {
|
|
203
|
+
issues.push(`could not read sbom.cdx.json to check tarball coverage: ${err.message}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
158
206
|
// Size budget. An absent/non-numeric `size` field is NOT a pass — it means
|
|
159
207
|
// the gate cannot evaluate the budget at all. Fail loudly instead of
|
|
160
208
|
// silently skipping (the absent-field-fails-open class, symmetric with the
|
|
@@ -187,4 +235,4 @@ function main() {
|
|
|
187
235
|
|
|
188
236
|
if (require.main === module) main();
|
|
189
237
|
|
|
190
|
-
module.exports = { main, REQUIRED_PATHS, FORBIDDEN_PATTERNS, SIZE_BUDGET_BYTES };
|
|
238
|
+
module.exports = { main, REQUIRED_PATHS, FORBIDDEN_PATTERNS, SIZE_BUDGET_BYTES, sbomCoverageIssues };
|
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exceptd-security",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation",
|
|
5
5
|
"homepage": "https://exceptd.com",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
],
|
|
58
58
|
"last_threat_review": "2026-05-15",
|
|
59
59
|
"signature": "0H+JfyUVmo/pVFEi5rLENATHjlukPVUqnOWmNPEH77wm8svKGK0aNJ46k6QU5GdHb8c9X9pVJKiuhON6AxDjDw==",
|
|
60
|
-
"signed_at": "2026-08-
|
|
60
|
+
"signed_at": "2026-08-08T19:32:46.994Z",
|
|
61
61
|
"cwe_refs": [
|
|
62
62
|
"CWE-125",
|
|
63
63
|
"CWE-362",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
],
|
|
134
134
|
"last_threat_review": "2026-06-10",
|
|
135
135
|
"signature": "hnKY1LYEKUurrzJIFcvwCZpclpk/XT8fMVJeCKqzrpOpfgov2d3AciuiEky85PhREzAmYGFfk2sLRC6ayJ6UDw==",
|
|
136
|
-
"signed_at": "2026-08-
|
|
136
|
+
"signed_at": "2026-08-08T19:32:46.995Z",
|
|
137
137
|
"cwe_refs": [
|
|
138
138
|
"CWE-1039",
|
|
139
139
|
"CWE-1426",
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
],
|
|
216
216
|
"last_threat_review": "2026-06-10",
|
|
217
217
|
"signature": "uiJt3Oj0lSLr7Nm0OoM2qI/z/oAIAiPwMfP12s97jVYeA7xfOlU21fc7zidT/9YulunfaSjBSAlgv6paWmosBg==",
|
|
218
|
-
"signed_at": "2026-08-
|
|
218
|
+
"signed_at": "2026-08-08T19:32:46.996Z",
|
|
219
219
|
"cwe_refs": [
|
|
220
220
|
"CWE-22",
|
|
221
221
|
"CWE-345",
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
"framework_gaps": [],
|
|
270
270
|
"last_threat_review": "2026-06-10",
|
|
271
271
|
"signature": "80LN540R3z/gcIMCF/8H6nh2V6xdudctYKE74Ve7bqecyPUQf2NfCA/8T9L18tIz7BTyBkiI/V5JcG4ClgNyCQ==",
|
|
272
|
-
"signed_at": "2026-08-
|
|
272
|
+
"signed_at": "2026-08-08T19:32:46.996Z"
|
|
273
273
|
},
|
|
274
274
|
{
|
|
275
275
|
"name": "compliance-theater",
|
|
@@ -301,7 +301,7 @@
|
|
|
301
301
|
],
|
|
302
302
|
"last_threat_review": "2026-06-10",
|
|
303
303
|
"signature": "Tsat4OgtCJ6yGJQeIQnz+XTU11B8SLgbPe1zmb2UFOzxqlBnRoKeOzIVwFsv7wM0mP1bXQvQgFFpIOxN2VeTCQ==",
|
|
304
|
-
"signed_at": "2026-08-
|
|
304
|
+
"signed_at": "2026-08-08T19:32:46.996Z"
|
|
305
305
|
},
|
|
306
306
|
{
|
|
307
307
|
"name": "exploit-scoring",
|
|
@@ -332,7 +332,7 @@
|
|
|
332
332
|
],
|
|
333
333
|
"last_threat_review": "2026-06-10",
|
|
334
334
|
"signature": "zxsj3SExhBJ+A7UDZEI4uWl4OCbnn5+ddCRCalhlHKFyRML9fcB9qd1v9a+hDoeVJXGr/OBXHR3MdyD8XEhrDQ==",
|
|
335
|
-
"signed_at": "2026-08-
|
|
335
|
+
"signed_at": "2026-08-08T19:32:46.997Z"
|
|
336
336
|
},
|
|
337
337
|
{
|
|
338
338
|
"name": "rag-pipeline-security",
|
|
@@ -374,7 +374,7 @@
|
|
|
374
374
|
],
|
|
375
375
|
"last_threat_review": "2026-06-10",
|
|
376
376
|
"signature": "lrj8/nJWYzgeOYPF9Ax59A0mxCXWKKhH9QI+88KQNiKly0Hq+pA5wdtL0J9LY24YrVWmqEhpSHueGlj03UNOAA==",
|
|
377
|
-
"signed_at": "2026-08-
|
|
377
|
+
"signed_at": "2026-08-08T19:32:46.997Z",
|
|
378
378
|
"cwe_refs": [
|
|
379
379
|
"CWE-1395",
|
|
380
380
|
"CWE-1426"
|
|
@@ -441,7 +441,7 @@
|
|
|
441
441
|
],
|
|
442
442
|
"last_threat_review": "2026-06-10",
|
|
443
443
|
"signature": "nqqZUnu7ZocLNJKs3KJO6NnoC8MgmS1iGP9TGrv51e+trjqb4Gf2mAjCTe7pINFivWDK00A0ZHazaMAKKbaNCA==",
|
|
444
|
-
"signed_at": "2026-08-
|
|
444
|
+
"signed_at": "2026-08-08T19:32:46.997Z",
|
|
445
445
|
"cwe_refs": [
|
|
446
446
|
"CWE-918"
|
|
447
447
|
],
|
|
@@ -482,7 +482,7 @@
|
|
|
482
482
|
"framework_gaps": [],
|
|
483
483
|
"last_threat_review": "2026-06-10",
|
|
484
484
|
"signature": "ZfFXIDjwGDwlZA30TOMPmNr0IK/sydbsiox7LYU0pGkaRlQW18/oSjkHZRgiQpP5yzQhuFsKdztA7Ec6BDQLAA==",
|
|
485
|
-
"signed_at": "2026-08-
|
|
485
|
+
"signed_at": "2026-08-08T19:32:46.998Z",
|
|
486
486
|
"cwe_refs": [
|
|
487
487
|
"CWE-1188"
|
|
488
488
|
],
|
|
@@ -517,7 +517,7 @@
|
|
|
517
517
|
"framework_gaps": [],
|
|
518
518
|
"last_threat_review": "2026-06-10",
|
|
519
519
|
"signature": "CtiEhtzaqg/hCGX1wmgEGq0O6o+UNf9RAM3xxn0rQVEkFt/IEmyYqsWd1qjpqMdp8kbEXgAsd816AwFwLYMaAA==",
|
|
520
|
-
"signed_at": "2026-08-
|
|
520
|
+
"signed_at": "2026-08-08T19:32:46.998Z",
|
|
521
521
|
"forward_watch": [
|
|
522
522
|
"New AI attack classes as ATLAS v6 publishes",
|
|
523
523
|
"Post-quantum adversary capability timeline",
|
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
"framework_gaps": [],
|
|
559
559
|
"last_threat_review": "2026-08-05",
|
|
560
560
|
"signature": "Eu2AnT4xyZH9n3OKjm5S9vaiHqUE+1N3oLAQbbt78OCp2HnAQMvqBkUn9rgl4Il7Il7yZW8N7c8hq3mkst+EAA==",
|
|
561
|
-
"signed_at": "2026-08-
|
|
561
|
+
"signed_at": "2026-08-08T19:32:46.999Z",
|
|
562
562
|
"d3fend_refs": [
|
|
563
563
|
"D3-EAL",
|
|
564
564
|
"D3-EFA",
|
|
@@ -600,7 +600,7 @@
|
|
|
600
600
|
"framework_gaps": [],
|
|
601
601
|
"last_threat_review": "2026-06-10",
|
|
602
602
|
"signature": "tlvk8q1fa1scoDsJMZnigCoRNO3dqoK03Ve8tuYE2/nPwAMAGlofHpoE0mI0BX4pPODPgCfSjzgKEUn6HkcZDw==",
|
|
603
|
-
"signed_at": "2026-08-
|
|
603
|
+
"signed_at": "2026-08-08T19:32:46.999Z",
|
|
604
604
|
"forward_watch": [
|
|
605
605
|
"New CISA KEV entries",
|
|
606
606
|
"New ATLAS TTP additions in each ATLAS release",
|
|
@@ -669,7 +669,7 @@
|
|
|
669
669
|
],
|
|
670
670
|
"last_threat_review": "2026-08-05",
|
|
671
671
|
"signature": "DNXmzLVK71XI/b9mkIBw30KVdVV5Wc9/0o/pP35RkferqtvlsMHjj4WJpoGXpIu8/hJyuMJRQrV7pzfR68iIAg==",
|
|
672
|
-
"signed_at": "2026-08-
|
|
672
|
+
"signed_at": "2026-08-08T19:32:47.000Z",
|
|
673
673
|
"cwe_refs": [
|
|
674
674
|
"CWE-327"
|
|
675
675
|
],
|
|
@@ -719,7 +719,7 @@
|
|
|
719
719
|
],
|
|
720
720
|
"last_threat_review": "2026-06-10",
|
|
721
721
|
"signature": "AzyfBZd5bxpQpaFb/S5ZJI2/NjeACLuq/u8GzKHehhlggWUqILIrS4aJ6eXn0I3UBhuXRcNBBx1mXriCSmhQAA==",
|
|
722
|
-
"signed_at": "2026-08-
|
|
722
|
+
"signed_at": "2026-08-08T19:32:47.000Z"
|
|
723
723
|
},
|
|
724
724
|
{
|
|
725
725
|
"name": "security-maturity-tiers",
|
|
@@ -759,7 +759,7 @@
|
|
|
759
759
|
],
|
|
760
760
|
"last_threat_review": "2026-08-05",
|
|
761
761
|
"signature": "8JHth6QjMcUuAD069/QvpMxgRMG+L/PVTE68/UdX9kG4SNA20ds7vHU15YzMNBmWWgiUvpLAE6hzctz1N7bWCg==",
|
|
762
|
-
"signed_at": "2026-08-
|
|
762
|
+
"signed_at": "2026-08-08T19:32:47.000Z",
|
|
763
763
|
"cwe_refs": [
|
|
764
764
|
"CWE-1188"
|
|
765
765
|
],
|
|
@@ -813,7 +813,7 @@
|
|
|
813
813
|
"framework_gaps": [],
|
|
814
814
|
"last_threat_review": "2026-05-11",
|
|
815
815
|
"signature": "iJWevUBurLvt2v8X+Ch2eHmZkPWpKeAtIpxTIP4MwbUHyco3igDeBywJCyaR2vURYRx8LkzzIMM8DxQM4LAXBQ==",
|
|
816
|
-
"signed_at": "2026-08-
|
|
816
|
+
"signed_at": "2026-08-08T19:32:47.001Z"
|
|
817
817
|
},
|
|
818
818
|
{
|
|
819
819
|
"name": "attack-surface-pentest",
|
|
@@ -889,7 +889,7 @@
|
|
|
889
889
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — Microsoft Edge 4-bug sandbox escape by Orange Tsai (DEVCORE); forward-watch only (browser sandbox, out of current playbook scope); track Microsoft Edge security advisory and KEV add"
|
|
890
890
|
],
|
|
891
891
|
"signature": "GuHxmoEU97+lQfU11chYwXVQhSMpddU0OS1iLkYDmEJhBkHRWWaOa2emYJoVUBDB9v/PTKcFEuEraZwYg+8nCw==",
|
|
892
|
-
"signed_at": "2026-08-
|
|
892
|
+
"signed_at": "2026-08-08T19:32:47.001Z"
|
|
893
893
|
},
|
|
894
894
|
{
|
|
895
895
|
"name": "fuzz-testing-strategy",
|
|
@@ -950,7 +950,7 @@
|
|
|
950
950
|
"OSS-Fuzz-Gen / AI-assisted harness generation becoming the default expectation for OSS maintainers"
|
|
951
951
|
],
|
|
952
952
|
"signature": "R2jcBorSMWFuZKHUugWEni9q/W7Qk73Kg0SztXlySYu9+D2Ee43gyYsUy0nSa0oCTS8pyuhFiFv2XN0EaweTBQ==",
|
|
953
|
-
"signed_at": "2026-08-
|
|
953
|
+
"signed_at": "2026-08-08T19:32:47.001Z"
|
|
954
954
|
},
|
|
955
955
|
{
|
|
956
956
|
"name": "dlp-gap-analysis",
|
|
@@ -1028,7 +1028,7 @@
|
|
|
1028
1028
|
"Quebec Law 25, India DPDPA, KSA PDPL enforcement actions naming AI-tool prompt data as in-scope personal information"
|
|
1029
1029
|
],
|
|
1030
1030
|
"signature": "uIQdYlbKIQw8qQRDeGnXv4D/wuPAvYFRzos3kqkyELx+v9rGmfmT7w5s1608lpJxXzGLIA7BSN2/wLJJAZmXCg==",
|
|
1031
|
-
"signed_at": "2026-08-
|
|
1031
|
+
"signed_at": "2026-08-08T19:32:47.002Z"
|
|
1032
1032
|
},
|
|
1033
1033
|
{
|
|
1034
1034
|
"name": "supply-chain-integrity",
|
|
@@ -1112,7 +1112,7 @@
|
|
|
1112
1112
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — NVIDIA Megatron Bridge path traversal by haehae; AI training-stack file-system trust boundary; track patch and SBOM-attestation impact"
|
|
1113
1113
|
],
|
|
1114
1114
|
"signature": "4EMvqqcYHnM+9fmlS156Utl3T248EqHdiB89zVyW8+wUYHAU/VLUOr27JiiSmj5iZrdY5Prq7t9Hsk3LuVx5Aw==",
|
|
1115
|
-
"signed_at": "2026-08-
|
|
1115
|
+
"signed_at": "2026-08-08T19:32:47.002Z"
|
|
1116
1116
|
},
|
|
1117
1117
|
{
|
|
1118
1118
|
"name": "defensive-countermeasure-mapping",
|
|
@@ -1169,7 +1169,7 @@
|
|
|
1169
1169
|
],
|
|
1170
1170
|
"last_threat_review": "2026-06-10",
|
|
1171
1171
|
"signature": "W8kg2Okd/VF521VmeVFGK2TmXkFPycuwgYdyNxLU2fMN+sR9Aals/X+Xqr/prrGEsqWnZsCInSq1TYzFr0wiDg==",
|
|
1172
|
-
"signed_at": "2026-08-
|
|
1172
|
+
"signed_at": "2026-08-08T19:32:47.002Z"
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "identity-assurance",
|
|
@@ -1243,7 +1243,7 @@
|
|
|
1243
1243
|
],
|
|
1244
1244
|
"last_threat_review": "2026-05-11",
|
|
1245
1245
|
"signature": "UV3458QXSkEpenzrOmdlTTfPHUD4hNyKMDHoeZDq/kiFb4mAG0ghQGTTgI9Ru8cJbSmYM1++m9N5TFIJ6JJPBg==",
|
|
1246
|
-
"signed_at": "2026-08-
|
|
1246
|
+
"signed_at": "2026-08-08T19:32:47.003Z"
|
|
1247
1247
|
},
|
|
1248
1248
|
{
|
|
1249
1249
|
"name": "ot-ics-security",
|
|
@@ -1302,7 +1302,7 @@
|
|
|
1302
1302
|
"d3fend_refs": [],
|
|
1303
1303
|
"last_threat_review": "2026-06-10",
|
|
1304
1304
|
"signature": "1PFZXMfQwM0dHsZQfo+rg5hJB00dfeOL41VA3J8gNF6cCUpplw9vQuZfODX/SwXI/WmDQwM9G2sd1X/i7LG9DA==",
|
|
1305
|
-
"signed_at": "2026-08-
|
|
1305
|
+
"signed_at": "2026-08-08T19:32:47.003Z"
|
|
1306
1306
|
},
|
|
1307
1307
|
{
|
|
1308
1308
|
"name": "coordinated-vuln-disclosure",
|
|
@@ -1362,7 +1362,7 @@
|
|
|
1362
1362
|
"NYDFS 23 NYCRR 500 amendments potentially adding explicit CVD program requirements"
|
|
1363
1363
|
],
|
|
1364
1364
|
"signature": "5b3J9mk/iEi6OzeC0O2hw/K/ofTrH8519l+ZUpK8gqB/v0XbDFceIIBPB8TQM8wCct5iG0Krb7OCDSIbU0jVBw==",
|
|
1365
|
-
"signed_at": "2026-08-
|
|
1365
|
+
"signed_at": "2026-08-08T19:32:47.003Z"
|
|
1366
1366
|
},
|
|
1367
1367
|
{
|
|
1368
1368
|
"name": "threat-modeling-methodology",
|
|
@@ -1416,7 +1416,7 @@
|
|
|
1416
1416
|
"PASTA v2 updates incorporating AI/ML application threats"
|
|
1417
1417
|
],
|
|
1418
1418
|
"signature": "fibgNRd+STEyN3ZlnIxJddfaOXISYosdjoxkQ/oNVTP3GKhN1A4c3Jh0HZPbhTdjhrbJM/mE5ufiIOs7+RCMCQ==",
|
|
1419
|
-
"signed_at": "2026-08-
|
|
1419
|
+
"signed_at": "2026-08-08T19:32:47.004Z"
|
|
1420
1420
|
},
|
|
1421
1421
|
{
|
|
1422
1422
|
"name": "webapp-security",
|
|
@@ -1499,7 +1499,7 @@
|
|
|
1499
1499
|
],
|
|
1500
1500
|
"last_threat_review": "2026-06-10",
|
|
1501
1501
|
"signature": "3qtC0X8QR9YufDfeL/AUiw3EeJwvSfSrUWojndEZVmeJ3MtM12I94OJmaQT1AWaTRWVa9f91owgLl6AgoTNVAA==",
|
|
1502
|
-
"signed_at": "2026-08-
|
|
1502
|
+
"signed_at": "2026-08-08T19:32:47.004Z",
|
|
1503
1503
|
"forward_watch": [
|
|
1504
1504
|
"NGINX Rift CVE-2026-42945 (disclosed 2026-05-13, source depthfirst) — KEV-watch predicted CISA KEV listing by 2026-05-29; AI-assisted discovery angle; track for active-exploitation confirmation and patch advisory affecting front-door web app deployments"
|
|
1505
1505
|
]
|
|
@@ -1559,7 +1559,7 @@
|
|
|
1559
1559
|
],
|
|
1560
1560
|
"last_threat_review": "2026-05-15",
|
|
1561
1561
|
"signature": "SBB7c3wNYfIdkyOp4g4nW0WP7xS+YokMzg32aaeJdbf14LTGQRzQUvSqb2TCj2HFUSHESOyKT1JpkAfyHLSQBQ==",
|
|
1562
|
-
"signed_at": "2026-08-
|
|
1562
|
+
"signed_at": "2026-08-08T19:32:47.004Z"
|
|
1563
1563
|
},
|
|
1564
1564
|
{
|
|
1565
1565
|
"name": "sector-healthcare",
|
|
@@ -1626,7 +1626,7 @@
|
|
|
1626
1626
|
],
|
|
1627
1627
|
"last_threat_review": "2026-06-10",
|
|
1628
1628
|
"signature": "Z/lPfIH5ARAOoeR81ATj6lQlekZP/8tzg23Pr1H9BxxdQedRsLGDNVIHu81qNuoA7GNRRMtxXpwrS7fXbMh5Cw==",
|
|
1629
|
-
"signed_at": "2026-08-
|
|
1629
|
+
"signed_at": "2026-08-08T19:32:47.005Z"
|
|
1630
1630
|
},
|
|
1631
1631
|
{
|
|
1632
1632
|
"name": "sector-financial",
|
|
@@ -1715,7 +1715,7 @@
|
|
|
1715
1715
|
"TIBER-EU framework v2.0 alignment with DORA TLPT RTS (JC 2024/40); cross-recognition with CBEST and iCAST"
|
|
1716
1716
|
],
|
|
1717
1717
|
"signature": "kPV8cEpIUAMKY2USvFxAn6JkkRMlBAM2mGLy6ViS9O3rv+3dsAgBqKgcBTBbuSoMZgY2KKruoG+SkrR3aoViAg==",
|
|
1718
|
-
"signed_at": "2026-08-
|
|
1718
|
+
"signed_at": "2026-08-08T19:32:47.005Z"
|
|
1719
1719
|
},
|
|
1720
1720
|
{
|
|
1721
1721
|
"name": "sector-federal-government",
|
|
@@ -1792,7 +1792,7 @@
|
|
|
1792
1792
|
"Australia PSPF 2024 revision and ISM quarterly updates — track for Essential Eight Maturity Level requirements for federal entities"
|
|
1793
1793
|
],
|
|
1794
1794
|
"signature": "CbxW5qhlaiqf+P3xIemSHlMz9OoWat2srh7F3+nAIsa0Y4nBr6WCXZXZlUUjrjptZ3Ny+Cw485HMLWRO9qbcBw==",
|
|
1795
|
-
"signed_at": "2026-08-
|
|
1795
|
+
"signed_at": "2026-08-08T19:32:47.006Z"
|
|
1796
1796
|
},
|
|
1797
1797
|
{
|
|
1798
1798
|
"name": "sector-energy",
|
|
@@ -1866,7 +1866,7 @@
|
|
|
1866
1866
|
"ICS-CERT advisory feed (https://www.cisa.gov/news-events/cybersecurity-advisories/ics-advisories) for vendor CVEs in Siemens, Rockwell, Schneider Electric, ABB, GE Vernova, Hitachi Energy, AVEVA / OSIsoft PI"
|
|
1867
1867
|
],
|
|
1868
1868
|
"signature": "lVHORFJzvkxNqJfT34inW28BzlA8dCWDfo0JS9tsiNW3PUxdijZS22g4GMbQJgaSKGv7F3ag5rWk75O+IChUAw==",
|
|
1869
|
-
"signed_at": "2026-08-
|
|
1869
|
+
"signed_at": "2026-08-08T19:32:47.006Z"
|
|
1870
1870
|
},
|
|
1871
1871
|
{
|
|
1872
1872
|
"name": "sector-telecom",
|
|
@@ -1952,7 +1952,7 @@
|
|
|
1952
1952
|
"O-RAN SFG / WG11 security specifications"
|
|
1953
1953
|
],
|
|
1954
1954
|
"signature": "NAtyzfLPXlUuB78Snb9nWmbZalC1CNlIYN9rYhdEmtB/xQGC6vVnThgrEAHlm7v/jMCFuknvEpUHKdscUnUADw==",
|
|
1955
|
-
"signed_at": "2026-08-
|
|
1955
|
+
"signed_at": "2026-08-08T19:32:47.006Z"
|
|
1956
1956
|
},
|
|
1957
1957
|
{
|
|
1958
1958
|
"name": "api-security",
|
|
@@ -2031,7 +2031,7 @@
|
|
|
2031
2031
|
],
|
|
2032
2032
|
"last_threat_review": "2026-06-10",
|
|
2033
2033
|
"signature": "hyLAsPCAkUkhNeaaFtgSg5XsKs2L8HuFoPka/Urzel54XPMQ0F3MwRD7j/ZURzIHQxvrAxmS3OCXEsBrgcFxAw==",
|
|
2034
|
-
"signed_at": "2026-08-
|
|
2034
|
+
"signed_at": "2026-08-08T19:32:47.007Z",
|
|
2035
2035
|
"forward_watch": [
|
|
2036
2036
|
"NGINX Rift CVE-2026-42945 (disclosed 2026-05-13, source depthfirst) — KEV-watch predicted CISA KEV listing by 2026-05-29; track for active-exploitation confirmation and patch advisory affecting API gateway / reverse-proxy deployments",
|
|
2037
2037
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — LiteLLM 3-bug SSRF + Code Injection chain by k3vg3n; LLM-proxy API surface; track upstream patch and CVE assignments",
|
|
@@ -2126,7 +2126,7 @@
|
|
|
2126
2126
|
"CISA KEV additions for cloud-control-plane CVEs (IMDSv1 abuses, federation token mishandling, cross-tenant boundary failures); CISA Cybersecurity Advisories for cross-cloud advisories"
|
|
2127
2127
|
],
|
|
2128
2128
|
"signature": "MfijBq1nzlyPQWf5/EcTn5Xx7ThdZ9BT8/W/+daxhATfMSoSTrMn9pYh1R83Chr9n2ahQeMoPUkSxL7Cr9V3Dw==",
|
|
2129
|
-
"signed_at": "2026-08-
|
|
2129
|
+
"signed_at": "2026-08-08T19:32:47.007Z"
|
|
2130
2130
|
},
|
|
2131
2131
|
{
|
|
2132
2132
|
"name": "container-runtime-security",
|
|
@@ -2198,7 +2198,7 @@
|
|
|
2198
2198
|
],
|
|
2199
2199
|
"last_threat_review": "2026-06-10",
|
|
2200
2200
|
"signature": "QJ8RF3ifPFc0mr3gYkloHqg5nuYe1GS4h+xbKYDCkM+HbA3iTd5keJ59P2P3z8TwVdOt8XM8WOsx6aRUrFL0Cw==",
|
|
2201
|
-
"signed_at": "2026-08-
|
|
2201
|
+
"signed_at": "2026-08-08T19:32:47.007Z",
|
|
2202
2202
|
"forward_watch": [
|
|
2203
2203
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — NVIDIA Container Toolkit container escape ($50K award) by chompie / IBM X-Force XOR; high-severity container/hypervisor boundary break; track patch and KEV add post-embargo"
|
|
2204
2204
|
]
|
|
@@ -2279,7 +2279,7 @@
|
|
|
2279
2279
|
"MITRE ATLAS v2026.07 (released June 2026) is additive over v2026.05 — it adds AML.T0113 (Steal Web Session Cookie), AML.T0091.001 (Use Alternate Authentication Material: Web Session Cookie), and AML.T0114 (AI Service Web Interface) and refreshes AML.T0054 (LLM Jailbreak), with no technique-ID removals. Earlier releases shipped the AML.T0010 sub-technique expansion and agentic-AI techniques (\"Publish Poisoned AI Agent Tool\", \"Escape to Host\") this forecast tracked. Forward watch: subsequent monthly ATLAS releases — track next-cadence updates to agentic-AI TTPs and MLOps-pipeline-specific techniques"
|
|
2280
2280
|
],
|
|
2281
2281
|
"signature": "e4uV8JvtEbC/lKGqJ6Y3ugEetF6aEv7R7CwJ/Y9N4thWNg8fconRcOPDS+045PW8xmcAqAbkSi+I4N1E6EPTAA==",
|
|
2282
|
-
"signed_at": "2026-08-
|
|
2282
|
+
"signed_at": "2026-08-08T19:32:47.008Z"
|
|
2283
2283
|
},
|
|
2284
2284
|
{
|
|
2285
2285
|
"name": "incident-response-playbook",
|
|
@@ -2353,7 +2353,7 @@
|
|
|
2353
2353
|
"NYDFS 23 NYCRR 500.17 amendments tightening ransom-payment 24h disclosure operationalization"
|
|
2354
2354
|
],
|
|
2355
2355
|
"signature": "asDHEy7Y2Bj4ikCkpP5MHRe33TIY8aQ1a+KN1UZgl89g9LyLcXzSg/weACafxJNzhOUkXnKBAtBrQIKW6p6nDQ==",
|
|
2356
|
-
"signed_at": "2026-08-
|
|
2356
|
+
"signed_at": "2026-08-08T19:32:47.008Z"
|
|
2357
2357
|
},
|
|
2358
2358
|
{
|
|
2359
2359
|
"name": "ransomware-response",
|
|
@@ -2433,7 +2433,7 @@
|
|
|
2433
2433
|
],
|
|
2434
2434
|
"last_threat_review": "2026-06-10",
|
|
2435
2435
|
"signature": "UTDsSMDvW5cpuSDBgZO5AzKowXWAR3WqeUeqyHXaikxslC6YBDL/gIojm9Km3/mgOS6pD5JKb/LLcfb4T/r4BQ==",
|
|
2436
|
-
"signed_at": "2026-08-
|
|
2436
|
+
"signed_at": "2026-08-08T19:32:47.008Z"
|
|
2437
2437
|
},
|
|
2438
2438
|
{
|
|
2439
2439
|
"name": "email-security-anti-phishing",
|
|
@@ -2501,7 +2501,7 @@
|
|
|
2501
2501
|
],
|
|
2502
2502
|
"last_threat_review": "2026-05-18",
|
|
2503
2503
|
"signature": "FVBn4ex2qPIo9SHMVJ6tntoz4tVwjbIq3m6wDjjZyv2JODlS+90GBYCOkNamxxkmw/6de6SMs0YHQiF/xjo/DQ==",
|
|
2504
|
-
"signed_at": "2026-08-
|
|
2504
|
+
"signed_at": "2026-08-08T19:32:47.009Z"
|
|
2505
2505
|
},
|
|
2506
2506
|
{
|
|
2507
2507
|
"name": "age-gates-child-safety",
|
|
@@ -2576,7 +2576,7 @@
|
|
|
2576
2576
|
"US state adult-site age-verification laws — 19+ states by mid-2026 (TX HB 18 upheld by SCOTUS June 2025 in Free Speech Coalition v. Paxton); track ongoing challenges in remaining states"
|
|
2577
2577
|
],
|
|
2578
2578
|
"signature": "l/jeAAnb7H2GQzp1x05bsdZwzC0NNTBi3ZuiwgDly5EVSoikbnVWpx921bT5G3OPkx4dqs2PohlvTG0gLxCrAA==",
|
|
2579
|
-
"signed_at": "2026-08-
|
|
2579
|
+
"signed_at": "2026-08-08T19:32:47.009Z"
|
|
2580
2580
|
},
|
|
2581
2581
|
{
|
|
2582
2582
|
"name": "cloud-iam-incident",
|
|
@@ -2656,7 +2656,7 @@
|
|
|
2656
2656
|
],
|
|
2657
2657
|
"last_threat_review": "2026-05-15",
|
|
2658
2658
|
"signature": "vrMvYLdYJLlEAC8YvOb/g3LJ8gU1YmYewZ94J5AFgxxh2EiDyszqo3D/WVpt5NTrDSS/N5OgOf5Vwom/KGlMCA==",
|
|
2659
|
-
"signed_at": "2026-08-
|
|
2659
|
+
"signed_at": "2026-08-08T19:32:47.009Z",
|
|
2660
2660
|
"forward_watch": [
|
|
2661
2661
|
"AWS IAM Identity Center session-policy refresh and step-up-on-admin enforcement (anticipated 2026-H2 release)",
|
|
2662
2662
|
"GCP Workload Identity Federation principal-set attribute mapping tightening (post-2026 Q3 Federation hardening guide)",
|
|
@@ -2750,7 +2750,7 @@
|
|
|
2750
2750
|
],
|
|
2751
2751
|
"last_threat_review": "2026-05-15",
|
|
2752
2752
|
"signature": "9mfDtMApMAg9V/lmwpniNxo/6gNZoOEoYDfyFvyWvKrPMtc7H9F8uz06FVoARe/J49saAKTVXOurNE1D/KtpCQ==",
|
|
2753
|
-
"signed_at": "2026-08-
|
|
2753
|
+
"signed_at": "2026-08-08T19:32:47.010Z",
|
|
2754
2754
|
"forward_watch": [
|
|
2755
2755
|
"Entra ID conditional access evolution post-Midnight Blizzard — Microsoft's 2025-2026 commitments on legacy-tenant MFA enforcement and OAuth-app consent gating",
|
|
2756
2756
|
"Okta IPSIE (Interoperability Profile for Secure Identity in the Enterprise) OpenID Foundation working-group output and adoption timeline",
|
|
@@ -2822,7 +2822,7 @@
|
|
|
2822
2822
|
"d3fend_refs": [],
|
|
2823
2823
|
"last_threat_review": "2026-06-02",
|
|
2824
2824
|
"signature": "dOFgANMtHm64uSFRjMfeA0fWZS9ISwMTt59I2CbjaF1PgTtbtb8yg/f+3pC4eXcXIET0KPGxRRmENycfIz3rAw==",
|
|
2825
|
-
"signed_at": "2026-08-
|
|
2825
|
+
"signed_at": "2026-08-08T19:32:47.010Z"
|
|
2826
2826
|
},
|
|
2827
2827
|
{
|
|
2828
2828
|
"name": "mail-server-hardening",
|
|
@@ -2881,7 +2881,7 @@
|
|
|
2881
2881
|
"d3fend_refs": [],
|
|
2882
2882
|
"last_threat_review": "2026-06-02",
|
|
2883
2883
|
"signature": "5x8RGzKo/T2IbYnFkYMZs16ThD9a5FEdrKHsnwvtMuGxdyyfZsKNIJVWw2I8O0um0UOXwwkl17Z3zhch26ymCQ==",
|
|
2884
|
-
"signed_at": "2026-08-
|
|
2884
|
+
"signed_at": "2026-08-08T19:32:47.010Z"
|
|
2885
2885
|
},
|
|
2886
2886
|
{
|
|
2887
2887
|
"name": "network-trust",
|
|
@@ -2937,7 +2937,7 @@
|
|
|
2937
2937
|
"d3fend_refs": [],
|
|
2938
2938
|
"last_threat_review": "2026-06-02",
|
|
2939
2939
|
"signature": "C/RdmnGjXKreKiGkwJfUESIxUwQzisGJ9A7KBdE9cBRBHBYHkAcScV89L+Z3kOG032Qax6LeIQai7Lr3nrQBCA==",
|
|
2940
|
-
"signed_at": "2026-08-
|
|
2940
|
+
"signed_at": "2026-08-08T19:32:47.010Z"
|
|
2941
2941
|
},
|
|
2942
2942
|
{
|
|
2943
2943
|
"name": "audit-log-integrity",
|
|
@@ -2992,7 +2992,7 @@
|
|
|
2992
2992
|
"d3fend_refs": [],
|
|
2993
2993
|
"last_threat_review": "2026-06-02",
|
|
2994
2994
|
"signature": "T7sFREX7P2QYrau+eTNXKkrU2aJ91dsX6GQWVJeexJ9SqbyFHtAnIKo4r6F6VdELADyVjaRXKk/fLuyUaCkGBA==",
|
|
2995
|
-
"signed_at": "2026-08-
|
|
2995
|
+
"signed_at": "2026-08-08T19:32:47.011Z"
|
|
2996
2996
|
},
|
|
2997
2997
|
{
|
|
2998
2998
|
"name": "self-update-integrity",
|
|
@@ -3046,7 +3046,7 @@
|
|
|
3046
3046
|
"d3fend_refs": [],
|
|
3047
3047
|
"last_threat_review": "2026-06-02",
|
|
3048
3048
|
"signature": "BOQZ8G9LdyG/tfpz6rCU4THz5Dq2HGJkUV7uCqSTCMrqnXH6seNXKM41FWawYo0s2VUlXtRgaO7ETp5qgxw+CQ==",
|
|
3049
|
-
"signed_at": "2026-08-
|
|
3049
|
+
"signed_at": "2026-08-08T19:32:47.011Z"
|
|
3050
3050
|
},
|
|
3051
3051
|
{
|
|
3052
3052
|
"name": "multitenancy-isolation",
|
|
@@ -3104,7 +3104,7 @@
|
|
|
3104
3104
|
"d3fend_refs": [],
|
|
3105
3105
|
"last_threat_review": "2026-06-02",
|
|
3106
3106
|
"signature": "bncN0VE4ns0lxtPe48xDR33lerw54BPVkSwX7XlrLQcMHTrV94lmjO8z4ZP4Ko61n+KpuP2SNU8v9JT0bGMmAA==",
|
|
3107
|
-
"signed_at": "2026-08-
|
|
3107
|
+
"signed_at": "2026-08-08T19:32:47.011Z"
|
|
3108
3108
|
},
|
|
3109
3109
|
{
|
|
3110
3110
|
"name": "decompression-dos",
|
|
@@ -3162,7 +3162,7 @@
|
|
|
3162
3162
|
"d3fend_refs": [],
|
|
3163
3163
|
"last_threat_review": "2026-06-02",
|
|
3164
3164
|
"signature": "03i0ZO5ScHIOjGvDKUEsws6m+20fnlJrEhSBtMU7PJzQutrPpmW9gULE0wbayTD5H9URh5nSKZuuVjvjVhZNCg==",
|
|
3165
|
-
"signed_at": "2026-08-
|
|
3165
|
+
"signed_at": "2026-08-08T19:32:47.011Z"
|
|
3166
3166
|
},
|
|
3167
3167
|
{
|
|
3168
3168
|
"name": "log-injection-telemetry",
|
|
@@ -3217,7 +3217,7 @@
|
|
|
3217
3217
|
"d3fend_refs": [],
|
|
3218
3218
|
"last_threat_review": "2026-06-02",
|
|
3219
3219
|
"signature": "twTmA2l+Am2k2PCzB2DNxDQwoYlGopJp/3QgQwBsP7h2LF+uNudisqfuOVV/bYnWfrUhuYZUWbsR3mhzbJCUBw==",
|
|
3220
|
-
"signed_at": "2026-08-
|
|
3220
|
+
"signed_at": "2026-08-08T19:32:47.011Z"
|
|
3221
3221
|
},
|
|
3222
3222
|
{
|
|
3223
3223
|
"name": "privacy-consent-ops",
|
|
@@ -3272,11 +3272,11 @@
|
|
|
3272
3272
|
"d3fend_refs": [],
|
|
3273
3273
|
"last_threat_review": "2026-06-02",
|
|
3274
3274
|
"signature": "0sfKSVrIf555c9bDGkXB96fUClN52fMAMYoQsNQ9eUUSzDiWUwdou+q0gYt43nObtj3m9Yb9X6q3oCXDVMgUDg==",
|
|
3275
|
-
"signed_at": "2026-08-
|
|
3275
|
+
"signed_at": "2026-08-08T19:32:47.012Z"
|
|
3276
3276
|
}
|
|
3277
3277
|
],
|
|
3278
3278
|
"manifest_signature": {
|
|
3279
3279
|
"algorithm": "Ed25519",
|
|
3280
|
-
"signature_base64": "
|
|
3280
|
+
"signature_base64": "/vLR1ucGYyI9/t/dTXMRb7BhLtqqmrpQ3CkyjkN0wZymwLSfx62A8meWOjenGeMj3XjMRqg1c/IhKQyBpiAPDw=="
|
|
3281
3281
|
}
|
|
3282
3282
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blamejs/exceptd-skills",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (1025 CVEs / 232 CWEs / 794 ATT&CK + ICS / 174 ATLAS / 468 D3FEND / 8889 RFCs), 35 jurisdictions, 10-class catalog gap detector + budget gate, real XML parser + canonical-form diff + content-pattern regression detection, Ed25519-signed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-security",
|
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:7f211e54-0c0b-4b04-9d54-f70a5568ac78",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "
|
|
7
|
+
"timestamp": "2026-08-08T00:00:00.000Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "blamejs",
|
|
11
11
|
"name": "scripts/refresh-sbom.js",
|
|
12
|
-
"version": "0.19.
|
|
12
|
+
"version": "0.19.3"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"component": {
|
|
16
|
-
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.19.
|
|
16
|
+
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.19.3",
|
|
17
17
|
"type": "application",
|
|
18
18
|
"name": "@blamejs/exceptd-skills",
|
|
19
|
-
"version": "0.19.
|
|
19
|
+
"version": "0.19.3",
|
|
20
20
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (1025 CVEs / 232 CWEs / 794 ATT&CK + ICS / 174 ATLAS / 468 D3FEND / 8889 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.19.
|
|
28
|
+
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.19.3",
|
|
29
29
|
"hashes": [
|
|
30
30
|
{
|
|
31
31
|
"alg": "SHA-256",
|
|
32
|
-
"content": "
|
|
32
|
+
"content": "534717aa72715652e635959c41d58e67926743edc15a0557b8f8570a174e6e60"
|
|
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.19.
|
|
38
|
+
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.19.3"
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"type": "vcs",
|
|
@@ -60,6 +60,14 @@
|
|
|
60
60
|
"name": "exceptd:integrity:method",
|
|
61
61
|
"value": "Ed25519 per-skill (lib/sign.js)"
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
"name": "exceptd:integrity:uncovered:prefix",
|
|
65
|
+
"value": "data/_indexes/"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "exceptd:integrity:uncovered:rationale",
|
|
69
|
+
"value": "Regenerated by `npm run build-indexes` and mutated by the test suite, so a pinned per-file hash would race any run between generation and verification. Covered instead by the pre-computed-index freshness gate in `npm run predeploy`."
|
|
70
|
+
},
|
|
63
71
|
{
|
|
64
72
|
"name": "exceptd:runtime:dependency:count",
|
|
65
73
|
"value": "0"
|
|
@@ -116,11 +124,11 @@
|
|
|
116
124
|
"hashes": [
|
|
117
125
|
{
|
|
118
126
|
"alg": "SHA-256",
|
|
119
|
-
"content": "
|
|
127
|
+
"content": "0886406bdf81bbb64f3b461d9c62d9deb53f5e5142af0fb955a90f38991d34bb"
|
|
120
128
|
},
|
|
121
129
|
{
|
|
122
130
|
"alg": "SHA3-512",
|
|
123
|
-
"content": "
|
|
131
|
+
"content": "5f8a142a79db22e647b8e61002361c1e94e3e41f4607d3202b7673a709dc50abc60e687639af283145cc40a3ece292dd4595b8a03683982f9ecbfb3bcfda9f52"
|
|
124
132
|
}
|
|
125
133
|
]
|
|
126
134
|
},
|
|
@@ -1811,11 +1819,11 @@
|
|
|
1811
1819
|
"hashes": [
|
|
1812
1820
|
{
|
|
1813
1821
|
"alg": "SHA-256",
|
|
1814
|
-
"content": "
|
|
1822
|
+
"content": "5aeebc43db5477b9a342f783d72a5a28a9632205b8aab6e08ea346d3310eac47"
|
|
1815
1823
|
},
|
|
1816
1824
|
{
|
|
1817
1825
|
"alg": "SHA3-512",
|
|
1818
|
-
"content": "
|
|
1826
|
+
"content": "08b23fc717d26133ee455690692b79c3a5bb8386cb4aaa54d6ba6f3e8705adab8e217881b3418534d38bf18b53761f76d8f6ccd1a20567ec5bc39e715a207304"
|
|
1819
1827
|
}
|
|
1820
1828
|
]
|
|
1821
1829
|
},
|
|
@@ -1946,11 +1954,11 @@
|
|
|
1946
1954
|
"hashes": [
|
|
1947
1955
|
{
|
|
1948
1956
|
"alg": "SHA-256",
|
|
1949
|
-
"content": "
|
|
1957
|
+
"content": "ea761dae093a3f57552dc54d1c4cda0f8a0c1c48aac6a4fbaebf6f0fb1e89416"
|
|
1950
1958
|
},
|
|
1951
1959
|
{
|
|
1952
1960
|
"alg": "SHA3-512",
|
|
1953
|
-
"content": "
|
|
1961
|
+
"content": "a399cae2a99e4a613878bfbe3de82d04604559f228bd615435ac43624671060f875641aa40d1c4978f6259b79767c42aad8d6e87a710bb33c223f97e0f9355d4"
|
|
1954
1962
|
}
|
|
1955
1963
|
]
|
|
1956
1964
|
},
|
|
@@ -2059,6 +2067,21 @@
|
|
|
2059
2067
|
}
|
|
2060
2068
|
]
|
|
2061
2069
|
},
|
|
2070
|
+
{
|
|
2071
|
+
"bom-ref": "file:package.json",
|
|
2072
|
+
"type": "file",
|
|
2073
|
+
"name": "package.json",
|
|
2074
|
+
"hashes": [
|
|
2075
|
+
{
|
|
2076
|
+
"alg": "SHA-256",
|
|
2077
|
+
"content": "a4f0243303f43e0aff7b62082761136da51b6157a6da1d53357e9c8b41659641"
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
"alg": "SHA3-512",
|
|
2081
|
+
"content": "7547730b7a85504e16231b8959b66322c79e85bf3e8629298ffccf1453a20a13eea71f27550a76d2a24c75bd90b021679eb4120d8c96db32000e57b954b3ef33"
|
|
2082
|
+
}
|
|
2083
|
+
]
|
|
2084
|
+
},
|
|
2062
2085
|
{
|
|
2063
2086
|
"bom-ref": "file:scripts/audit-catalog-gaps.js",
|
|
2064
2087
|
"type": "file",
|
|
@@ -2471,11 +2494,11 @@
|
|
|
2471
2494
|
"hashes": [
|
|
2472
2495
|
{
|
|
2473
2496
|
"alg": "SHA-256",
|
|
2474
|
-
"content": "
|
|
2497
|
+
"content": "c360d8fce5cb264662a355b05224fa2a3f16a25ff3d6199ad5db1c08919754e2"
|
|
2475
2498
|
},
|
|
2476
2499
|
{
|
|
2477
2500
|
"alg": "SHA3-512",
|
|
2478
|
-
"content": "
|
|
2501
|
+
"content": "f364223d705ed8b4dcf6e54d234891b3508cd79c0fe5832706514c9dc3079b594322fb63e16ea9fe1d135181b93e0c153ad073fb92cdc40d59386d781006eed0"
|
|
2479
2502
|
}
|
|
2480
2503
|
]
|
|
2481
2504
|
},
|
|
@@ -2741,11 +2764,11 @@
|
|
|
2741
2764
|
"hashes": [
|
|
2742
2765
|
{
|
|
2743
2766
|
"alg": "SHA-256",
|
|
2744
|
-
"content": "
|
|
2767
|
+
"content": "c5f38a759980ae125f1f30195abd60dae2c4d9547895ee6e8290f47c80bab0c4"
|
|
2745
2768
|
},
|
|
2746
2769
|
{
|
|
2747
2770
|
"alg": "SHA3-512",
|
|
2748
|
-
"content": "
|
|
2771
|
+
"content": "a5b7a4bed681c7c066aa51316bb1d602134721906eeada0ab6ce8a67227f09eb191dce0e530a6c15486a1f308bc71b304916d45dec15ec8fc53b6f0aebf910e3"
|
|
2749
2772
|
}
|
|
2750
2773
|
]
|
|
2751
2774
|
},
|
|
@@ -2771,11 +2794,11 @@
|
|
|
2771
2794
|
"hashes": [
|
|
2772
2795
|
{
|
|
2773
2796
|
"alg": "SHA-256",
|
|
2774
|
-
"content": "
|
|
2797
|
+
"content": "7425bd4cefc0185b889e7389a1bdb952ad4f576cab03e63928ad4b991f48ccc1"
|
|
2775
2798
|
},
|
|
2776
2799
|
{
|
|
2777
2800
|
"alg": "SHA3-512",
|
|
2778
|
-
"content": "
|
|
2801
|
+
"content": "4b169deaefb58b617f0748a65409277c0592db50b7024f03cc290eda17299ec4aa4d682a294ba2f2251f015331ebbe07b3ca88549d354d5ee9b51589bd778ce7"
|
|
2779
2802
|
}
|
|
2780
2803
|
]
|
|
2781
2804
|
},
|
|
@@ -3619,6 +3642,21 @@
|
|
|
3619
3642
|
}
|
|
3620
3643
|
]
|
|
3621
3644
|
},
|
|
3645
|
+
{
|
|
3646
|
+
"bom-ref": "file:sources/README.md",
|
|
3647
|
+
"type": "file",
|
|
3648
|
+
"name": "sources/README.md",
|
|
3649
|
+
"hashes": [
|
|
3650
|
+
{
|
|
3651
|
+
"alg": "SHA-256",
|
|
3652
|
+
"content": "37356d40c4db4a0b5060911cd20f7a4ec3fc96c8b394308de646ba17e69493b7"
|
|
3653
|
+
},
|
|
3654
|
+
{
|
|
3655
|
+
"alg": "SHA3-512",
|
|
3656
|
+
"content": "963c00719163eedb931bcc4713be3f2aca2377f3d6492ff44c2d3e8dd37c6d6ffc4411ecfeda697c0406fffc2bb8eaeb38195b230d9e6a0ecfbfe4671ac0b7c3"
|
|
3657
|
+
}
|
|
3658
|
+
]
|
|
3659
|
+
},
|
|
3622
3660
|
{
|
|
3623
3661
|
"bom-ref": "file:sources/validators/atlas-validator.js",
|
|
3624
3662
|
"type": "file",
|
|
@@ -59,6 +59,10 @@ function catalogEntryCount(dataDir, file) {
|
|
|
59
59
|
// emits one for.
|
|
60
60
|
const SBOM_SELF_EXCLUDED = new Set(["sbom.cdx.json"]);
|
|
61
61
|
const SBOM_DERIVABLE_PREFIXES = ["data/_indexes/"];
|
|
62
|
+
// Mirrors refresh-sbom's ALWAYS_SHIPPED: npm adds package.json to every tarball
|
|
63
|
+
// without it appearing in `files`, so the completeness check has to expect a
|
|
64
|
+
// component for it the same way the generator now emits one.
|
|
65
|
+
const SBOM_ALWAYS_SHIPPED = ["package.json", "sources/README.md"];
|
|
62
66
|
|
|
63
67
|
function sbomIsDerivable(rel) {
|
|
64
68
|
return SBOM_DERIVABLE_PREFIXES.some(
|
|
@@ -93,7 +97,7 @@ function walkFilesAbs(absDir) {
|
|
|
93
97
|
// module-level root.
|
|
94
98
|
function expandAllowlistAt(allowlist, root) {
|
|
95
99
|
const abs = [];
|
|
96
|
-
for (const entry of allowlist) {
|
|
100
|
+
for (const entry of [...allowlist, ...SBOM_ALWAYS_SHIPPED]) {
|
|
97
101
|
const full = path.join(root, entry);
|
|
98
102
|
let stat;
|
|
99
103
|
try { stat = fs.statSync(full); }
|
package/scripts/refresh-sbom.js
CHANGED
|
@@ -12,9 +12,14 @@
|
|
|
12
12
|
* - bomFormat / specVersion CycloneDX 1.6
|
|
13
13
|
* - serialNumber urn:uuid v4 derived from a stable
|
|
14
14
|
* hash of (project name + version +
|
|
15
|
-
*
|
|
16
|
-
* UUID
|
|
17
|
-
*
|
|
15
|
+
* bundle digest), so identical content
|
|
16
|
+
* reproduces the identical UUID and a
|
|
17
|
+
* rerun that changed nothing is a no-op
|
|
18
|
+
* rather than a spurious diff.
|
|
19
|
+
* - metadata.timestamp the release date this version's
|
|
20
|
+
* CHANGELOG heading declares — NOT the
|
|
21
|
+
* wall-clock moment of generation, which
|
|
22
|
+
* would make the artifact irreproducible
|
|
18
23
|
* - metadata.tools this script itself, version pulled
|
|
19
24
|
* from package.json at refresh time
|
|
20
25
|
* - metadata.component application entry for exceptd-skills,
|
|
@@ -145,13 +150,31 @@ const SELF_EXCLUDED = new Set(['sbom.cdx.json']);
|
|
|
145
150
|
* side check for the cache. */
|
|
146
151
|
const DERIVABLE_PREFIXES = ['data/_indexes/'];
|
|
147
152
|
|
|
153
|
+
/* Files npm puts in every tarball regardless of the `files` allowlist.
|
|
154
|
+
* package.json is never listed in `files` (npm adds it unconditionally), so
|
|
155
|
+
* expanding the allowlist alone left the one file that declares the bin
|
|
156
|
+
* entrypoint, the engines floor and the dependency set outside the hashed
|
|
157
|
+
* inventory — the SBOM described 247 of the 268 files an operator receives and
|
|
158
|
+
* said nothing about the gap. It is not derivable and not self-referential, so
|
|
159
|
+
* nothing but the omission kept it out. README.md and LICENSE get the same
|
|
160
|
+
* unconditional treatment from npm but are already named in `files`, so a
|
|
161
|
+
* union covers the general rule without double-counting them. sources/README.md
|
|
162
|
+
* is here for the same reason: npm collects README files it finds, `files` never
|
|
163
|
+
* names that directory, and it shipped unhashed.
|
|
164
|
+
*
|
|
165
|
+
* This list is maintained by hand, which is only safe because something else
|
|
166
|
+
* checks it: lib/validate-package.js compares the real `npm pack` output against
|
|
167
|
+
* this SBOM, so a file npm decides to ship that is missing here fails a gate
|
|
168
|
+
* instead of shipping silently. */
|
|
169
|
+
const ALWAYS_SHIPPED = ['package.json', 'sources/README.md'];
|
|
170
|
+
|
|
148
171
|
function isDerivable(rel) {
|
|
149
172
|
return DERIVABLE_PREFIXES.some((p) => rel === p.replace(/\/$/, '') || rel.startsWith(p));
|
|
150
173
|
}
|
|
151
174
|
|
|
152
175
|
function expandAllowlist(allowlist) {
|
|
153
176
|
const abs = [];
|
|
154
|
-
for (const entry of allowlist) {
|
|
177
|
+
for (const entry of [...allowlist, ...ALWAYS_SHIPPED]) {
|
|
155
178
|
const full = path.join(REPO_ROOT, entry);
|
|
156
179
|
if (!fs.existsSync(full)) continue; // tolerate a stale entry; predeploy gate flags
|
|
157
180
|
const stat = fs.statSync(full);
|
|
@@ -171,6 +194,38 @@ function expandAllowlist(allowlist) {
|
|
|
171
194
|
return rel;
|
|
172
195
|
}
|
|
173
196
|
|
|
197
|
+
/* metadata.timestamp — the release date this version's CHANGELOG heading
|
|
198
|
+
* declares, as an ISO-8601 instant.
|
|
199
|
+
*
|
|
200
|
+
* The field has to be deterministic: the SBOM-currency gate compares the
|
|
201
|
+
* committed artifact against a freshly generated one, so a wall-clock value
|
|
202
|
+
* would differ on every run and the comparison could never mean anything.
|
|
203
|
+
* The previous approach kept determinism by folding the bundle hash into a
|
|
204
|
+
* date offset, but the offset was a full uint32 of SECONDS — a 136-year
|
|
205
|
+
* spread — so the field routinely landed a century or more in the future
|
|
206
|
+
* (the shipped value read 2147-11-20). Deterministic, and untrue: consumers
|
|
207
|
+
* that sort or age-check SBOMs read that as a real creation date.
|
|
208
|
+
*
|
|
209
|
+
* The CHANGELOG heading is both deterministic and true. Its format is already
|
|
210
|
+
* enforced by scripts/check-changelog-extract.js, which the release flow runs
|
|
211
|
+
* before this script, so the date is guaranteed present by the time a release
|
|
212
|
+
* regenerates the SBOM. Refusing is deliberate when it is absent — inventing a
|
|
213
|
+
* placeholder is what produced the 2147 date in the first place. */
|
|
214
|
+
function releaseTimestamp(version) {
|
|
215
|
+
const changelogPath = path.join(REPO_ROOT, 'CHANGELOG.md');
|
|
216
|
+
const text = fs.readFileSync(changelogPath, 'utf8');
|
|
217
|
+
const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
218
|
+
const m = text.match(new RegExp('^## ' + escaped + ' [—-] (\\d{4}-\\d{2}-\\d{2})\\s*$', 'm'));
|
|
219
|
+
if (!m) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
`refresh-sbom: CHANGELOG.md has no dated heading for ${version}. ` +
|
|
222
|
+
`Add "## ${version} — YYYY-MM-DD" before regenerating — metadata.timestamp ` +
|
|
223
|
+
`is the release date, and there is no honest value to fall back to.`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
return `${m[1]}T00:00:00.000Z`;
|
|
227
|
+
}
|
|
228
|
+
|
|
174
229
|
function toPosixRel(absPath) {
|
|
175
230
|
return path
|
|
176
231
|
.relative(REPO_ROOT, absPath)
|
|
@@ -303,12 +358,7 @@ function buildSbom() {
|
|
|
303
358
|
// time of a refresh should read the file's mtime or refresh-report.json.
|
|
304
359
|
const seed = `${pkg.name}@${pkg.version}@${bundleSha}`;
|
|
305
360
|
const serialNumber = 'urn:uuid:' + uuidV4FromSeed(seed);
|
|
306
|
-
|
|
307
|
-
// CycloneDX 1.6 metadata.timestamp schema requirement (must be an
|
|
308
|
-
// ISO-8601 string) while remaining content-stable.
|
|
309
|
-
const seedHash = crypto.createHash('sha256').update(seed).digest();
|
|
310
|
-
const offsetSeconds = seedHash.readUInt32BE(0); // deterministic offset
|
|
311
|
-
const timestamp = new Date(Date.UTC(2026, 0, 1) + offsetSeconds * 1000).toISOString();
|
|
361
|
+
const timestamp = releaseTimestamp(pkg.version);
|
|
312
362
|
|
|
313
363
|
const dataflowInput = catalogs
|
|
314
364
|
.map((c) => `data/${c}`)
|
|
@@ -366,6 +416,22 @@ function buildSbom() {
|
|
|
366
416
|
name: 'exceptd:integrity:method',
|
|
367
417
|
value: 'Ed25519 per-skill (lib/sign.js)',
|
|
368
418
|
},
|
|
419
|
+
// An operator verifying the bundle holds the SBOM, not this script.
|
|
420
|
+
// Without these two properties the only record of what the inventory
|
|
421
|
+
// deliberately omits was a source comment they never see, so a partial
|
|
422
|
+
// inventory was indistinguishable from a complete one. State the
|
|
423
|
+
// uncovered prefix and the check that covers it instead.
|
|
424
|
+
{
|
|
425
|
+
name: 'exceptd:integrity:uncovered:prefix',
|
|
426
|
+
value: DERIVABLE_PREFIXES.join(','),
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'exceptd:integrity:uncovered:rationale',
|
|
430
|
+
value:
|
|
431
|
+
'Regenerated by `npm run build-indexes` and mutated by the test suite, so a ' +
|
|
432
|
+
'pinned per-file hash would race any run between generation and verification. ' +
|
|
433
|
+
'Covered instead by the pre-computed-index freshness gate in `npm run predeploy`.',
|
|
434
|
+
},
|
|
369
435
|
{
|
|
370
436
|
name: 'exceptd:runtime:dependency:count',
|
|
371
437
|
value: String(Object.keys(pkg.dependencies || {}).length),
|
|
@@ -409,4 +475,11 @@ if (require.main === module) {
|
|
|
409
475
|
main();
|
|
410
476
|
}
|
|
411
477
|
|
|
412
|
-
module.exports = {
|
|
478
|
+
module.exports = {
|
|
479
|
+
buildSbom,
|
|
480
|
+
expandAllowlist,
|
|
481
|
+
bundleDigest,
|
|
482
|
+
releaseTimestamp,
|
|
483
|
+
ALWAYS_SHIPPED,
|
|
484
|
+
DERIVABLE_PREFIXES,
|
|
485
|
+
};
|
package/scripts/release.js
CHANGED
|
@@ -295,8 +295,15 @@ function cmdPrepare(opts) {
|
|
|
295
295
|
_ok("signed + indexes + snapshot + sbom regenerated");
|
|
296
296
|
|
|
297
297
|
_section("test-count baseline");
|
|
298
|
-
//
|
|
299
|
-
//
|
|
298
|
+
// Check BEFORE refreshing. `--update-baseline` writes whatever it observes,
|
|
299
|
+
// so calling it unconditionally rebaselined a shrunken suite downward and the
|
|
300
|
+
// shrinkage gate — which runs later, in `gates` — then compared the new count
|
|
301
|
+
// against itself and passed. Releasing was the one path that disarmed the
|
|
302
|
+
// guard, which is the path it exists to guard. Run the gate first so a drop
|
|
303
|
+
// stops the release here; refresh only once it has agreed nothing was lost,
|
|
304
|
+
// which still captures growth. A deliberate removal is re-baselined by hand
|
|
305
|
+
// with the command the gate's own failure message prints.
|
|
306
|
+
_run("node", ["scripts/check-test-count.js"]);
|
|
300
307
|
_run("node", ["scripts/check-test-count.js", "--update-baseline"]);
|
|
301
308
|
|
|
302
309
|
_section("codebase-patterns currency (advisory)");
|