@blamejs/exceptd-skills 0.19.33 → 0.19.35
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 +28 -0
- package/bin/exceptd.js +895 -2828
- package/data/_indexes/_meta.json +2 -2
- package/lib/auto-discovery.js +56 -286
- package/lib/canonical-eq.js +7 -40
- package/lib/citation-resolve.js +22 -70
- package/lib/collectors/ai-api.js +170 -76
- package/lib/collectors/cicd-pipeline-compromise.js +113 -136
- package/lib/collectors/citation-hygiene.js +72 -210
- package/lib/collectors/containers.js +41 -130
- package/lib/collectors/cred-stores.js +31 -115
- package/lib/collectors/crypto-codebase.js +55 -138
- package/lib/collectors/crypto.js +24 -54
- package/lib/collectors/hardening.js +20 -78
- package/lib/collectors/kernel.js +16 -46
- package/lib/collectors/library-author.js +198 -211
- package/lib/collectors/mcp.js +24 -70
- package/lib/collectors/runtime.js +24 -86
- package/lib/collectors/sbom.js +130 -118
- package/lib/collectors/scan-excludes.js +33 -139
- package/lib/collectors/secrets.js +62 -178
- package/lib/cross-ref-api.js +39 -123
- package/lib/currency-severity.js +8 -27
- package/lib/cve-batch.js +13 -21
- package/lib/cve-cli.js +13 -20
- package/lib/cve-curation.js +72 -239
- package/lib/cve-regression-watcher.js +29 -155
- package/lib/cvss.js +13 -54
- package/lib/doctor-bucketing.js +3 -19
- package/lib/exit-codes.js +10 -42
- package/lib/flag-suggest.js +7 -25
- package/lib/framework-gap.js +39 -113
- package/lib/gap-detectors.js +37 -159
- package/lib/id-validation.js +9 -30
- package/lib/job-queue.js +13 -36
- package/lib/lint-skills.js +88 -236
- package/lib/playbook-runner.js +759 -2107
- package/lib/prefetch.js +101 -376
- package/lib/refresh-external.js +199 -633
- package/lib/refresh-network.js +78 -311
- package/lib/rfc-cli.js +23 -68
- package/lib/scoring.js +85 -146
- package/lib/sign.js +43 -229
- package/lib/source-advisories.js +43 -194
- package/lib/source-ghsa.js +37 -120
- package/lib/source-osv.js +94 -266
- package/lib/ttp-mapper.js +28 -27
- package/lib/upstream-check-cli.js +36 -29
- package/lib/upstream-check.js +19 -44
- package/lib/validate-catalog-meta.js +17 -61
- package/lib/validate-cve-catalog.js +52 -121
- package/lib/validate-indexes.js +25 -76
- package/lib/validate-package.js +16 -62
- package/lib/validate-playbooks.js +78 -286
- package/lib/validate-vendor.js +16 -49
- package/lib/verify.js +56 -286
- package/lib/version-pins.js +5 -34
- package/lib/worker-pool.js +11 -30
- package/lib/xml-tokenizer.js +47 -152
- package/manifest.json +53 -53
- package/orchestrator/dispatcher.js +17 -68
- package/orchestrator/event-bus.js +11 -74
- package/orchestrator/index.js +138 -413
- package/orchestrator/pipeline.js +28 -85
- package/orchestrator/scanner.js +34 -138
- package/orchestrator/scheduler.js +20 -84
- package/package.json +1 -1
- package/sbom.cdx.json +242 -242
- package/scripts/audit-catalog-gaps.js +9 -62
- package/scripts/audit-cross-skill.js +5 -31
- package/scripts/audit-perf.js +29 -28
- package/scripts/backfill-theater-test.js +7 -64
- package/scripts/bootstrap.js +12 -44
- package/scripts/build-indexes.js +40 -154
- package/scripts/builders/activity-feed.js +4 -14
- package/scripts/builders/catalog-summaries.js +3 -10
- package/scripts/builders/currency.js +7 -20
- package/scripts/builders/cwe-chains.js +7 -30
- package/scripts/builders/did-ladders.js +6 -13
- package/scripts/builders/frequency.js +5 -19
- package/scripts/builders/jurisdiction-clocks.js +6 -25
- package/scripts/builders/recipes.js +6 -14
- package/scripts/builders/section-offsets.js +13 -51
- package/scripts/builders/stale-content.js +7 -28
- package/scripts/builders/summary-cards.js +8 -29
- package/scripts/builders/theater-fingerprints.js +21 -31
- package/scripts/builders/token-budget.js +4 -31
- package/scripts/check-agents-md-collectors.js +26 -57
- package/scripts/check-catalog-gap-budget.js +15 -32
- package/scripts/check-changelog-extract.js +18 -48
- package/scripts/check-codebase-patterns-currency.js +6 -22
- package/scripts/check-codebase-patterns.js +63 -143
- package/scripts/check-epss-consistency.js +9 -64
- package/scripts/check-framework-gap-coverage.js +13 -31
- package/scripts/check-manifest-snapshot.js +62 -81
- package/scripts/check-sbom-currency.js +44 -142
- package/scripts/check-test-count.js +15 -52
- package/scripts/check-test-coverage.js +83 -198
- package/scripts/check-test-subjects.js +21 -62
- package/scripts/check-ttp-references.js +14 -38
- package/scripts/check-ttp-upstream.js +8 -40
- package/scripts/check-version-bump.js +9 -61
- package/scripts/check-version-tags.js +20 -121
- package/scripts/predeploy.js +38 -184
- package/scripts/refresh-manifest-snapshot.js +16 -38
- package/scripts/refresh-mitre-atlas.js +7 -8
- package/scripts/refresh-mitre-attack.js +1 -8
- package/scripts/refresh-mitre-d3fend.js +3 -9
- package/scripts/refresh-mitre-ics-attack.js +7 -8
- package/scripts/refresh-reverse-refs.js +27 -94
- package/scripts/refresh-rfc-index.js +7 -10
- package/scripts/refresh-sbom.js +31 -161
- package/scripts/refresh-upstream-catalogs.js +63 -148
- package/scripts/release.js +69 -234
- package/scripts/run-e2e-scenarios.js +26 -73
- package/scripts/sync-manifest-metadata.js +10 -34
- package/scripts/sync-package-description.js +8 -17
- package/scripts/validate-vendor-online.js +13 -44
- package/scripts/verify-shipped-tarball.js +35 -141
package/lib/rfc-cli.js
CHANGED
|
@@ -2,21 +2,14 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* datatracker lookup to disambiguate obsoleted-vs-nonexistent. Resolves an RFC
|
|
9
|
-
* number to its title + status so an agent can confirm a citation (e.g. "is
|
|
10
|
-
* RFC 9404 the Sieve spec?") without the datatracker. Optional --check
|
|
11
|
-
* "<claimed title>" reports whether the claimed title matches.
|
|
5
|
+
* `exceptd rfc <number>` — resolves an RFC number to its title and status:
|
|
6
|
+
* local index, then resolved cache, then one datatracker lookup to separate
|
|
7
|
+
* obsoleted from nonexistent.
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
10
|
const { resolveRfc } = require("./citation-resolve.js");
|
|
15
11
|
|
|
16
|
-
// Stopwords
|
|
17
|
-
// run preceded by one of these in the index title is still a clean match; a run
|
|
18
|
-
// preceded by a CONTENT word (e.g. "datagram" before "transport layer security")
|
|
19
|
-
// is the tail of a more-specific title and must NOT be accepted as a match.
|
|
12
|
+
// Stopwords don't disambiguate one RFC title from another.
|
|
20
13
|
const TITLE_STOPWORDS = new Set(["the", "a", "an", "of", "for", "to", "in", "on", "and", "or"]);
|
|
21
14
|
|
|
22
15
|
function normTitle(s) {
|
|
@@ -24,37 +17,19 @@ function normTitle(s) {
|
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* Replaces the old lenient bidirectional substring test (`a.includes(b) ||
|
|
30
|
-
* b.includes(a)`), which let "TLS" match the DTLS title (substring of "dtls")
|
|
31
|
-
* and let "Transport Layer Security" match the DTLS title (tail-of-phrase).
|
|
32
|
-
* The comparison is now whole-word and phrase-aware:
|
|
33
|
-
*
|
|
34
|
-
* 1. Every claimed token must appear as a WHOLE word in the index title
|
|
35
|
-
* (so "tls" never matches inside "dtls").
|
|
36
|
-
* 2. The claimed token sequence must appear as a CONTIGUOUS run in the index
|
|
37
|
-
* title, OR the claim must cover enough of the index title (containment
|
|
38
|
-
* ratio floor) to be unambiguous.
|
|
39
|
-
* 3. A contiguous run that is immediately preceded by a distinguishing
|
|
40
|
-
* CONTENT word in the index title is rejected — it is the tail of a
|
|
41
|
-
* more-specific title (the "datagram transport layer security" trap).
|
|
42
|
-
*
|
|
43
|
-
* Returns true / false. Only called when both a claim and an index title exist.
|
|
20
|
+
* Whole-word, phrase-aware comparison of a claimed RFC title against the
|
|
21
|
+
* authoritative index title. Called only when both exist.
|
|
44
22
|
*/
|
|
45
23
|
function titleMatches(claimed, indexTitle) {
|
|
46
24
|
const claimTokens = normTitle(claimed).split(" ").filter(Boolean);
|
|
47
25
|
const titleTokens = normTitle(indexTitle).split(" ").filter(Boolean);
|
|
48
26
|
if (claimTokens.length === 0 || titleTokens.length === 0) return false;
|
|
49
27
|
|
|
50
|
-
// (1) Whole-word containment: every claimed token must be a standalone token
|
|
51
|
-
// in the index title. Kills the tls-inside-dtls substring false positive.
|
|
52
28
|
const titleSet = new Set(titleTokens);
|
|
53
29
|
for (const t of claimTokens) {
|
|
54
30
|
if (!titleSet.has(t)) return false;
|
|
55
31
|
}
|
|
56
32
|
|
|
57
|
-
// Find every contiguous run of the claim inside the index title.
|
|
58
33
|
const runStarts = [];
|
|
59
34
|
for (let i = 0; i + claimTokens.length <= titleTokens.length; i++) {
|
|
60
35
|
let hit = true;
|
|
@@ -65,16 +40,12 @@ function titleMatches(claimed, indexTitle) {
|
|
|
65
40
|
}
|
|
66
41
|
|
|
67
42
|
if (runStarts.length > 0) {
|
|
68
|
-
// A single-token claim that
|
|
69
|
-
// its own —
|
|
70
|
-
// (e.g. "tls" is NOT a token inside "dtls"), so "TLS" correctly matches the
|
|
71
|
-
// 8446 title (standalone "tls" token) but not the 9147 DTLS title.
|
|
43
|
+
// A single-token claim that survived the whole-word check is unambiguous on
|
|
44
|
+
// its own — "tls" is not a token inside "dtls".
|
|
72
45
|
if (claimTokens.length === 1) return true;
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
// qualifier (e.g. "datagram" before "transport layer security") is the
|
|
77
|
-
// tail of a more-specific title and must not be accepted as a match.
|
|
46
|
+
// A multi-token run counts only where some occurrence begins the title or
|
|
47
|
+
// is preceded by a stopword. Preceded by a content qualifier ("datagram"
|
|
48
|
+
// before "transport layer security") it is the tail of a different title.
|
|
78
49
|
for (const start of runStarts) {
|
|
79
50
|
if (start === 0) return true;
|
|
80
51
|
const prev = titleTokens[start - 1];
|
|
@@ -83,13 +54,9 @@ function titleMatches(claimed, indexTitle) {
|
|
|
83
54
|
return false;
|
|
84
55
|
}
|
|
85
56
|
|
|
86
|
-
// No contiguous run,
|
|
87
|
-
// claim covers a strong majority of the
|
|
88
|
-
//
|
|
89
|
-
// not a match. Count DISTINCT claim tokens that appear in the title: counting
|
|
90
|
-
// non-distinct tokens lets a repeated-token claim (e.g. "security security
|
|
91
|
-
// security security") inflate the ratio past the floor and falsely match an
|
|
92
|
-
// unrelated title.
|
|
57
|
+
// No contiguous run, all tokens present out of order: accept only when the
|
|
58
|
+
// claim covers a strong majority of the title's tokens. DISTINCT claim tokens
|
|
59
|
+
// are counted, or a repeated-token claim inflates the ratio past the floor.
|
|
93
60
|
const distinct = new Set(claimTokens);
|
|
94
61
|
const present = [...distinct].filter((t) => titleSet.has(t)).length;
|
|
95
62
|
const ratio = present / titleTokens.length;
|
|
@@ -99,9 +66,8 @@ function titleMatches(claimed, indexTitle) {
|
|
|
99
66
|
async function main() {
|
|
100
67
|
const argv = process.argv.slice(2);
|
|
101
68
|
const flags = new Set(argv.filter((a) => a.startsWith("--")));
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
// a flag, so it isn't checked here.
|
|
69
|
+
// Unknown flags are rejected, as in the in-process verbs. `--check` consumes
|
|
70
|
+
// the following token, which is a positional and so isn't checked here.
|
|
105
71
|
const KNOWN = new Set(["--json", "--pretty", "--air-gap", "--no-network", "--check", "--help", "-h"]);
|
|
106
72
|
const unknown = [...flags].filter((f) => !KNOWN.has(f));
|
|
107
73
|
if (unknown.length > 0) {
|
|
@@ -112,10 +78,8 @@ async function main() {
|
|
|
112
78
|
process.exitCode = 1;
|
|
113
79
|
return;
|
|
114
80
|
}
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
// the RFC number resolves correctly regardless of flag order
|
|
118
|
-
// (`rfc --check "Some Title" 9404` reads id=9404, not id="Some Title").
|
|
81
|
+
// The `--check` value token is excluded from the positional pool by INDEX, so
|
|
82
|
+
// `rfc --check "Some Title" 9404` reads id=9404, not id="Some Title".
|
|
119
83
|
const checkIdx = argv.indexOf("--check");
|
|
120
84
|
const checkValueIdx = (checkIdx !== -1 && argv[checkIdx + 1] && !argv[checkIdx + 1].startsWith("--")) ? checkIdx + 1 : -1;
|
|
121
85
|
const positionals = argv.filter((a, i) => !a.startsWith("--") && i !== checkValueIdx);
|
|
@@ -123,9 +87,7 @@ async function main() {
|
|
|
123
87
|
const pretty = flags.has("--pretty");
|
|
124
88
|
const json = flags.has("--json") || pretty;
|
|
125
89
|
|
|
126
|
-
//
|
|
127
|
-
// checkValueIdx so the two never diverge); a trailing `--check` with no value
|
|
128
|
-
// leaves it null.
|
|
90
|
+
// Exactly the excluded value token; a trailing `--check` with no value is null.
|
|
129
91
|
let claimedTitle = null;
|
|
130
92
|
if (checkValueIdx !== -1) claimedTitle = argv[checkValueIdx];
|
|
131
93
|
|
|
@@ -143,10 +105,7 @@ async function main() {
|
|
|
143
105
|
if (claimedTitle && r.title) {
|
|
144
106
|
titleMatch = titleMatches(claimedTitle, r.title);
|
|
145
107
|
}
|
|
146
|
-
//
|
|
147
|
-
// code is derived below — a non-zero exit (status nonexistent OR an explicit
|
|
148
|
-
// title mismatch) must carry ok:false, not the inverted ok:true the envelope
|
|
149
|
-
// previously hardcoded.
|
|
108
|
+
// `ok` derives from the same condition as the exit code below.
|
|
150
109
|
const fails = r.status === "nonexistent" || titleMatch === false;
|
|
151
110
|
const body = { verb: "rfc", ...r, ...(claimedTitle ? { claimed_title: claimedTitle, title_match: titleMatch } : {}), ok: !fails };
|
|
152
111
|
|
|
@@ -171,15 +130,11 @@ async function main() {
|
|
|
171
130
|
if (fails) process.exitCode = 2;
|
|
172
131
|
}
|
|
173
132
|
|
|
174
|
-
//
|
|
175
|
-
// test the IIFE must not fire — it would read process.argv and write to stdout —
|
|
176
|
-
// so the pure title-match helper can be exercised in-process.
|
|
133
|
+
// Under require it would read process.argv and write stdout; keep it testable.
|
|
177
134
|
if (require.main === module) {
|
|
178
135
|
main().catch((err) => {
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
// envelope rather than crashing with a raw stack trace, and signal failure
|
|
182
|
-
// via exitCode so the event loop drains stderr before exit.
|
|
136
|
+
// Any unexpected throw becomes the {ok:false,error} envelope, not a raw
|
|
137
|
+
// stack; `process.exitCode`, not `process.exit()`, so stderr drains.
|
|
183
138
|
process.stderr.write(JSON.stringify({ ok: false, verb: "rfc", error: String((err && err.message) || err) }) + "\n");
|
|
184
139
|
process.exitCode = 1;
|
|
185
140
|
});
|