@skillsmith/core 0.5.4 → 0.5.5
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 +4 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/api/client.d.ts +4 -66
- package/dist/src/api/client.d.ts.map +1 -1
- package/dist/src/api/client.events.d.ts.map +1 -1
- package/dist/src/api/client.events.js +10 -1
- package/dist/src/api/client.events.js.map +1 -1
- package/dist/src/api/client.js +40 -66
- package/dist/src/api/client.js.map +1 -1
- package/dist/src/api/client.token-refresh.d.ts +3 -0
- package/dist/src/api/client.token-refresh.d.ts.map +1 -0
- package/dist/src/api/client.token-refresh.js +19 -0
- package/dist/src/api/client.token-refresh.js.map +1 -0
- package/dist/src/api/client.token-refresh.test.d.ts +2 -0
- package/dist/src/api/client.token-refresh.test.d.ts.map +1 -0
- package/dist/src/api/client.token-refresh.test.js +73 -0
- package/dist/src/api/client.token-refresh.test.js.map +1 -0
- package/dist/src/api/client.types.d.ts +2 -0
- package/dist/src/api/client.types.d.ts.map +1 -1
- package/dist/src/api/index.d.ts +1 -1
- package/dist/src/api/index.d.ts.map +1 -1
- package/dist/src/api/index.js +1 -1
- package/dist/src/api/index.js.map +1 -1
- package/dist/src/api/schemas.d.ts +319 -70
- package/dist/src/config/index.d.ts +4 -0
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/index.js +6 -0
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/token-credentials.d.ts +13 -0
- package/dist/src/config/token-credentials.d.ts.map +1 -0
- package/dist/src/config/token-credentials.js +126 -0
- package/dist/src/config/token-credentials.js.map +1 -0
- package/dist/src/config/token-credentials.test.d.ts +10 -0
- package/dist/src/config/token-credentials.test.d.ts.map +1 -0
- package/dist/src/config/token-credentials.test.js +91 -0
- package/dist/src/config/token-credentials.test.js.map +1 -0
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js +34 -5
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
- package/dist/src/scripts/github-import/blocklist.d.ts +65 -0
- package/dist/src/scripts/github-import/blocklist.d.ts.map +1 -0
- package/dist/src/scripts/github-import/blocklist.js +124 -0
- package/dist/src/scripts/github-import/blocklist.js.map +1 -0
- package/dist/src/scripts/github-import/index.d.ts +1 -0
- package/dist/src/scripts/github-import/index.d.ts.map +1 -1
- package/dist/src/scripts/github-import/index.js +3 -0
- package/dist/src/scripts/github-import/index.js.map +1 -1
- package/dist/src/scripts/github-import/signal-of-intent.d.ts +87 -0
- package/dist/src/scripts/github-import/signal-of-intent.d.ts.map +1 -0
- package/dist/src/scripts/github-import/signal-of-intent.js +213 -0
- package/dist/src/scripts/github-import/signal-of-intent.js.map +1 -0
- package/dist/src/scripts/github-import/types.d.ts +22 -0
- package/dist/src/scripts/github-import/types.d.ts.map +1 -1
- package/dist/src/scripts/github-import/types.js.map +1 -1
- package/dist/src/scripts/import-github-skills.js +73 -3
- package/dist/src/scripts/import-github-skills.js.map +1 -1
- package/dist/src/scripts/skill-scanner/allowlist.d.ts +38 -0
- package/dist/src/scripts/skill-scanner/allowlist.d.ts.map +1 -0
- package/dist/src/scripts/skill-scanner/allowlist.js +178 -0
- package/dist/src/scripts/skill-scanner/allowlist.js.map +1 -0
- package/dist/src/scripts/skill-scanner/scanner.d.ts +10 -2
- package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/scanner.js +15 -3
- package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
- package/dist/src/scripts/skill-scanner/trust-scorer.d.ts +20 -6
- package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
- package/dist/src/scripts/skill-scanner/trust-scorer.js +28 -9
- package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
- package/dist/src/scripts/skill-scanner/types.d.ts +50 -0
- package/dist/src/scripts/skill-scanner/types.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.d.ts +18 -0
- package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.js +54 -6
- package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
- package/dist/src/security/scanner/patterns.d.ts.map +1 -1
- package/dist/src/security/scanner/patterns.js +45 -5
- package/dist/src/security/scanner/patterns.js.map +1 -1
- package/dist/tests/api/client.events.test.d.ts +10 -0
- package/dist/tests/api/client.events.test.d.ts.map +1 -0
- package/dist/tests/api/client.events.test.js +85 -0
- package/dist/tests/api/client.events.test.js.map +1 -0
- package/dist/tests/github-import/blocklist.test.d.ts +15 -0
- package/dist/tests/github-import/blocklist.test.d.ts.map +1 -0
- package/dist/tests/github-import/blocklist.test.js +182 -0
- package/dist/tests/github-import/blocklist.test.js.map +1 -0
- package/dist/tests/github-import/signal-of-intent.test.d.ts +15 -0
- package/dist/tests/github-import/signal-of-intent.test.d.ts.map +1 -0
- package/dist/tests/github-import/signal-of-intent.test.js +171 -0
- package/dist/tests/github-import/signal-of-intent.test.js.map +1 -0
- package/dist/tests/security/scanner-regression-guard.test.d.ts +12 -0
- package/dist/tests/security/scanner-regression-guard.test.d.ts.map +1 -1
- package/dist/tests/security/scanner-regression-guard.test.js +15 -3
- package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
- package/dist/tests/security/scanner-wave2-fixtures.test.d.ts +12 -0
- package/dist/tests/security/scanner-wave2-fixtures.test.d.ts.map +1 -0
- package/dist/tests/security/scanner-wave2-fixtures.test.js +173 -0
- package/dist/tests/security/scanner-wave2-fixtures.test.js.map +1 -0
- package/dist/tests/security.test.js +1 -0
- package/dist/tests/security.test.js.map +1 -1
- package/dist/tests/skill-scanner/allowlist.test.d.ts +16 -0
- package/dist/tests/skill-scanner/allowlist.test.d.ts.map +1 -0
- package/dist/tests/skill-scanner/allowlist.test.js +332 -0
- package/dist/tests/skill-scanner/allowlist.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -19,7 +19,12 @@ import { log, sleep } from './github-import/utils.js';
|
|
|
19
19
|
import { checkRateLimit, fetchGitHubSearch } from './github-import/github-client.js';
|
|
20
20
|
import { saveCheckpoint, loadCheckpoint, clearCheckpoint } from './github-import/checkpoint.js';
|
|
21
21
|
import { deduplicateSkills } from './github-import/deduplication.js';
|
|
22
|
+
import { loadBlocklist } from './github-import/blocklist.js';
|
|
23
|
+
import { computeSignalScore, shouldIngest } from './github-import/signal-of-intent.js';
|
|
22
24
|
import { saveOutput } from './github-import/output.js';
|
|
25
|
+
// SMI-4408: blocklist file path — mirror the OUTPUT_PATH env-override pattern
|
|
26
|
+
// so the importer can be pointed at a non-default blocklist in CI/test runs.
|
|
27
|
+
const BLOCKLIST_PATH = process.env.INDEXER_BLOCKLIST_PATH || './data/indexer-blocklist.json';
|
|
23
28
|
async function main() {
|
|
24
29
|
const startTime = Date.now();
|
|
25
30
|
const shouldResume = process.argv.includes('--resume');
|
|
@@ -46,6 +51,8 @@ async function main() {
|
|
|
46
51
|
total_found: 0,
|
|
47
52
|
total_imported: 0,
|
|
48
53
|
duplicates_removed: 0,
|
|
54
|
+
blocked_count: 0,
|
|
55
|
+
blocked_repos: [],
|
|
49
56
|
queries_completed: [],
|
|
50
57
|
errors: [],
|
|
51
58
|
started_at: new Date().toISOString(),
|
|
@@ -57,6 +64,17 @@ async function main() {
|
|
|
57
64
|
if (checkpoint) {
|
|
58
65
|
allSkills = checkpoint.skills;
|
|
59
66
|
stats = checkpoint.stats;
|
|
67
|
+
// SMI-4408: backfill new stats fields if resuming from a pre-SMI-4408
|
|
68
|
+
// checkpoint (JSON load casts to Checkpoint but old files lack fields).
|
|
69
|
+
if (typeof stats.blocked_count !== 'number')
|
|
70
|
+
stats.blocked_count = 0;
|
|
71
|
+
if (!Array.isArray(stats.blocked_repos))
|
|
72
|
+
stats.blocked_repos = [];
|
|
73
|
+
// SMI-4415: backfill intent-gate fields (resume from a pre-SMI-4415
|
|
74
|
+
// checkpoint leaves them undefined). Dropped on the final re-assignment
|
|
75
|
+
// below, but keeps the stats object well-typed during the run.
|
|
76
|
+
stats.rejected_for_intent_count ??= 0;
|
|
77
|
+
stats.rejected_for_intent_reasons ??= [];
|
|
60
78
|
const lastQueryIndex = SEARCH_QUERIES.findIndex((q) => q.name === checkpoint.last_query);
|
|
61
79
|
if (lastQueryIndex >= 0) {
|
|
62
80
|
startQueryIndex = lastQueryIndex;
|
|
@@ -125,14 +143,63 @@ async function main() {
|
|
|
125
143
|
log('Deduplicating results...');
|
|
126
144
|
const { unique, duplicateCount } = deduplicateSkills(allSkills);
|
|
127
145
|
stats.duplicates_removed = duplicateCount;
|
|
128
|
-
stats.total_imported = unique.length;
|
|
129
146
|
log(`Removed ${duplicateCount} duplicates`);
|
|
130
|
-
log(`
|
|
147
|
+
log(`Post-dedup count: ${unique.length} unique skills`);
|
|
148
|
+
console.log();
|
|
149
|
+
// SMI-4415: Apply signal-of-intent gate BEFORE the SMI-4408 blocklist.
|
|
150
|
+
// Drops repos that don't exhibit structural signals of being a Claude skill
|
|
151
|
+
// (topic tag OR HIGH_TRUST_OWNERS membership) combined with a composite
|
|
152
|
+
// score ≥ SIGNAL_THRESHOLD. Per-skill reason captured for audit.
|
|
153
|
+
log('Applying signal-of-intent gate...');
|
|
154
|
+
const admitted = [];
|
|
155
|
+
const rejectedReasons = [];
|
|
156
|
+
for (const skill of unique) {
|
|
157
|
+
if (shouldIngest(skill)) {
|
|
158
|
+
admitted.push(skill);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const { signals } = computeSignalScore(skill);
|
|
162
|
+
rejectedReasons.push(signals.length > 0 ? signals.join('+') : 'no-signal');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const rejectedForIntent = unique.length - admitted.length;
|
|
166
|
+
stats.rejected_for_intent_count = rejectedForIntent;
|
|
167
|
+
stats.rejected_for_intent_reasons = rejectedReasons;
|
|
168
|
+
stats.intent_admit_rate = unique.length > 0 ? admitted.length / unique.length : 1;
|
|
169
|
+
log(`Rejected ${rejectedForIntent} for intent`);
|
|
170
|
+
log(`Intent admit rate: ${(stats.intent_admit_rate * 100).toFixed(1)}%`);
|
|
171
|
+
log(`Post-gate count: ${admitted.length} skills`);
|
|
172
|
+
console.log();
|
|
173
|
+
// SMI-4408: Apply indexer blocklist — filters known non-skill repos
|
|
174
|
+
// before they reach data/imported-skills.json. Exact owner/name match.
|
|
175
|
+
log('Applying indexer blocklist...');
|
|
176
|
+
const blocklist = loadBlocklist(BLOCKLIST_PATH);
|
|
177
|
+
const filtered = [];
|
|
178
|
+
const blockedRepos = [];
|
|
179
|
+
for (const skill of admitted) {
|
|
180
|
+
const repoKey = `${skill.author}/${skill.name}`;
|
|
181
|
+
if (blocklist.isBlocked(repoKey)) {
|
|
182
|
+
blockedRepos.push(repoKey);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
filtered.push(skill);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
stats.blocked_count = blockedRepos.length;
|
|
189
|
+
stats.blocked_repos = blockedRepos;
|
|
190
|
+
stats.total_imported = filtered.length;
|
|
191
|
+
log(`Blocked ${blockedRepos.length} non-skill repo(s)`);
|
|
192
|
+
if (blockedRepos.length > 0) {
|
|
193
|
+
for (const repo of blockedRepos) {
|
|
194
|
+
log(` - ${repo}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
log(`Final count: ${filtered.length} skills`);
|
|
131
198
|
console.log();
|
|
132
199
|
stats.completed_at = new Date().toISOString();
|
|
133
200
|
stats.duration_ms = Date.now() - startTime;
|
|
134
201
|
log('Saving output...');
|
|
135
|
-
saveOutput(
|
|
202
|
+
saveOutput(filtered, stats);
|
|
136
203
|
clearCheckpoint();
|
|
137
204
|
console.log();
|
|
138
205
|
console.log('======================================================================');
|
|
@@ -140,6 +207,9 @@ async function main() {
|
|
|
140
207
|
console.log('======================================================================');
|
|
141
208
|
console.log(` Total Found: ${stats.total_found}`);
|
|
142
209
|
console.log(` Duplicates Removed: ${stats.duplicates_removed}`);
|
|
210
|
+
console.log(` Rejected for Intent: ${stats.rejected_for_intent_count ?? 0}`);
|
|
211
|
+
console.log(` Intent Gate Admit Rate: ${((stats.intent_admit_rate ?? 1) * 100).toFixed(1)}%`);
|
|
212
|
+
console.log(` Blocked (SMI-4408): ${stats.blocked_count}`);
|
|
143
213
|
console.log(` Total Imported: ${stats.total_imported}`);
|
|
144
214
|
console.log(` Duration: ${(stats.duration_ms / 1000).toFixed(2)}s`);
|
|
145
215
|
console.log(` Queries Completed: ${stats.queries_completed.join(', ')}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-github-skills.js","sourceRoot":"","sources":["../../../src/scripts/import-github-skills.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"import-github-skills.js","sourceRoot":"","sources":["../../../src/scripts/import-github-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4396: Imported-skills security allowlist.
|
|
3
|
+
*
|
|
4
|
+
* Loads data/skills-security-allowlist.json and produces an AllowlistMatcher
|
|
5
|
+
* that shouldQuarantine + scanSkill consult to drop known false-positive
|
|
6
|
+
* findings from the quarantine predicate.
|
|
7
|
+
*
|
|
8
|
+
* Design invariants:
|
|
9
|
+
* - Per-(skillId, findingType, messagePattern, matchField) scope — never whole-skill bypass.
|
|
10
|
+
* - 90-day expiry enforced at match time; expired entries behave as absent.
|
|
11
|
+
* - ReDoS-hardened: load-time regex validation rejects nested quantifiers and
|
|
12
|
+
* unbounded wildcards; runtime uses safeRegexTest with length cap.
|
|
13
|
+
* - Fail-safe toward quarantine: malformed entries throw at load; unknown
|
|
14
|
+
* matchField rejects.
|
|
15
|
+
*/
|
|
16
|
+
import type { AllowlistEntry, AllowlistFile, AllowlistMatcher } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Parse a raw allowlist file object. Throws on malformed shape, invalid
|
|
19
|
+
* dates, unsafe regex, or missing required fields.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseAllowlistFile(raw: unknown): AllowlistFile;
|
|
22
|
+
/** Reset expiry-warning dedupe cache. Exposed for tests. */
|
|
23
|
+
export declare function _resetExpiryWarningCache(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Empty matcher — returns false for every check. Used when the allowlist file
|
|
26
|
+
* is absent and for callers that want to opt out without conditional plumbing.
|
|
27
|
+
*/
|
|
28
|
+
export declare const EMPTY_ALLOWLIST: AllowlistMatcher;
|
|
29
|
+
/**
|
|
30
|
+
* Load + validate an allowlist JSON file and return a matcher.
|
|
31
|
+
*
|
|
32
|
+
* If `path` does not exist, returns EMPTY_ALLOWLIST. A malformed file throws
|
|
33
|
+
* (fail-safe toward quarantine — never silently skip validation).
|
|
34
|
+
*/
|
|
35
|
+
export declare function loadAllowlist(path: string): AllowlistMatcher;
|
|
36
|
+
/** Build a matcher from an in-memory entry list (test + inline use). */
|
|
37
|
+
export declare function buildMatcher(entries: AllowlistEntry[]): AllowlistMatcher;
|
|
38
|
+
//# sourceMappingURL=allowlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAmB,MAAM,YAAY,CAAA;AA0ElG;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CAgB9D;AAsDD,4DAA4D;AAC5D,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,gBAI7B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAa5D;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,gBAAgB,CAIxE"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-4396: Imported-skills security allowlist.
|
|
3
|
+
*
|
|
4
|
+
* Loads data/skills-security-allowlist.json and produces an AllowlistMatcher
|
|
5
|
+
* that shouldQuarantine + scanSkill consult to drop known false-positive
|
|
6
|
+
* findings from the quarantine predicate.
|
|
7
|
+
*
|
|
8
|
+
* Design invariants:
|
|
9
|
+
* - Per-(skillId, findingType, messagePattern, matchField) scope — never whole-skill bypass.
|
|
10
|
+
* - 90-day expiry enforced at match time; expired entries behave as absent.
|
|
11
|
+
* - ReDoS-hardened: load-time regex validation rejects nested quantifiers and
|
|
12
|
+
* unbounded wildcards; runtime uses safeRegexTest with length cap.
|
|
13
|
+
* - Fail-safe toward quarantine: malformed entries throw at load; unknown
|
|
14
|
+
* matchField rejects.
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import { safeRegexCheck } from '../../security/scanner/regex-utils.js';
|
|
18
|
+
const REQUIRED_ENTRY_FIELDS = [
|
|
19
|
+
'skillId',
|
|
20
|
+
'findingType',
|
|
21
|
+
'messagePattern',
|
|
22
|
+
'reason',
|
|
23
|
+
'reviewedBy',
|
|
24
|
+
'reviewedAt',
|
|
25
|
+
'expiresAt',
|
|
26
|
+
];
|
|
27
|
+
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
28
|
+
/**
|
|
29
|
+
* Reject regex patterns known to cause catastrophic backtracking.
|
|
30
|
+
* Callers must catch; signals a bad allowlist file at load time.
|
|
31
|
+
*/
|
|
32
|
+
function validateRegexSafety(pattern, entryIndex) {
|
|
33
|
+
// Nested quantifier: (x+)+, (x*)*, (x+)*, etc.
|
|
34
|
+
if (/\([^)]*[*+?][^)]*\)[*+?]/.test(pattern)) {
|
|
35
|
+
throw new Error(`Allowlist entry #${entryIndex} messagePattern has nested quantifier (ReDoS risk): ${pattern}`);
|
|
36
|
+
}
|
|
37
|
+
// Unbounded greedy wildcard outside a character class: .* or .+ without upper bound.
|
|
38
|
+
// Character-class forms like [^x]* are allowed since they bound the repeated set.
|
|
39
|
+
if (/(?<!\[[^\]]*)\.[*+](?!\?)/.test(pattern)) {
|
|
40
|
+
throw new Error(`Allowlist entry #${entryIndex} messagePattern has unbounded .*/.+ (ReDoS risk). ` +
|
|
41
|
+
`Use bounded form like .{0,100}? or a character class instead: ${pattern}`);
|
|
42
|
+
}
|
|
43
|
+
// Compile to surface any other regex syntax errors up-front.
|
|
44
|
+
try {
|
|
45
|
+
new RegExp(pattern);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
throw new Error(`Allowlist entry #${entryIndex} messagePattern is invalid regex: ${err.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function validateEntryShape(entry, entryIndex) {
|
|
52
|
+
if (typeof entry !== 'object' || entry === null) {
|
|
53
|
+
throw new Error(`Allowlist entry #${entryIndex} is not an object`);
|
|
54
|
+
}
|
|
55
|
+
const e = entry;
|
|
56
|
+
for (const field of REQUIRED_ENTRY_FIELDS) {
|
|
57
|
+
if (typeof e[field] !== 'string' || e[field].length === 0) {
|
|
58
|
+
throw new Error(`Allowlist entry #${entryIndex} missing or empty required field: ${String(field)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (e.matchField !== undefined && e.matchField !== 'message' && e.matchField !== 'location') {
|
|
62
|
+
throw new Error(`Allowlist entry #${entryIndex} matchField must be 'message' or 'location', got: ${String(e.matchField)}`);
|
|
63
|
+
}
|
|
64
|
+
if (!DATE_PATTERN.test(e.reviewedAt)) {
|
|
65
|
+
throw new Error(`Allowlist entry #${entryIndex} reviewedAt must be YYYY-MM-DD, got: ${String(e.reviewedAt)}`);
|
|
66
|
+
}
|
|
67
|
+
if (!DATE_PATTERN.test(e.expiresAt)) {
|
|
68
|
+
throw new Error(`Allowlist entry #${entryIndex} expiresAt must be YYYY-MM-DD, got: ${String(e.expiresAt)}`);
|
|
69
|
+
}
|
|
70
|
+
validateRegexSafety(e.messagePattern, entryIndex);
|
|
71
|
+
return e;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse a raw allowlist file object. Throws on malformed shape, invalid
|
|
75
|
+
* dates, unsafe regex, or missing required fields.
|
|
76
|
+
*/
|
|
77
|
+
export function parseAllowlistFile(raw) {
|
|
78
|
+
if (typeof raw !== 'object' || raw === null) {
|
|
79
|
+
throw new Error('Allowlist file root must be an object');
|
|
80
|
+
}
|
|
81
|
+
const r = raw;
|
|
82
|
+
if (r.version !== 1) {
|
|
83
|
+
throw new Error(`Unsupported allowlist file version: ${String(r.version)} (expected 1)`);
|
|
84
|
+
}
|
|
85
|
+
if (typeof r.generatedAt !== 'string') {
|
|
86
|
+
throw new Error('Allowlist file missing generatedAt (ISO-8601 string)');
|
|
87
|
+
}
|
|
88
|
+
if (!Array.isArray(r.allowlist)) {
|
|
89
|
+
throw new Error('Allowlist file .allowlist must be an array');
|
|
90
|
+
}
|
|
91
|
+
const entries = r.allowlist.map((entry, i) => validateEntryShape(entry, i));
|
|
92
|
+
return { version: 1, generatedAt: r.generatedAt, allowlist: entries };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Matcher implementation backed by a pre-validated entry list.
|
|
96
|
+
*/
|
|
97
|
+
class EntryListMatcher {
|
|
98
|
+
compiledEntries;
|
|
99
|
+
constructor(entries) {
|
|
100
|
+
this.compiledEntries = entries.map((entry) => ({
|
|
101
|
+
entry,
|
|
102
|
+
regex: new RegExp(entry.messagePattern),
|
|
103
|
+
expiresAt: new Date(`${entry.expiresAt}T23:59:59Z`),
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
isAllowed(skillId, finding, today = new Date()) {
|
|
107
|
+
for (const compiled of this.compiledEntries) {
|
|
108
|
+
const { entry, regex, expiresAt } = compiled;
|
|
109
|
+
if (entry.skillId !== skillId)
|
|
110
|
+
continue;
|
|
111
|
+
if (entry.findingType !== finding.type)
|
|
112
|
+
continue;
|
|
113
|
+
if (today > expiresAt) {
|
|
114
|
+
// Expired entry: log once per (skillId, findingType) and fall through to next.
|
|
115
|
+
logExpiryWarning(entry);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const field = entry.matchField ?? 'message';
|
|
119
|
+
const target = field === 'location' ? (finding.location ?? '') : finding.message;
|
|
120
|
+
if (safeRegexCheck(regex, target)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** Tracks already-logged expiry warnings so we don't spam on every finding. */
|
|
128
|
+
const loggedExpirySet = new Set();
|
|
129
|
+
function logExpiryWarning(entry) {
|
|
130
|
+
const key = `${entry.skillId}::${entry.findingType}::${entry.expiresAt}`;
|
|
131
|
+
if (loggedExpirySet.has(key))
|
|
132
|
+
return;
|
|
133
|
+
loggedExpirySet.add(key);
|
|
134
|
+
console.warn(`allowlist:expired skillId=${entry.skillId} findingType=${entry.findingType} ` +
|
|
135
|
+
`expiredAt=${entry.expiresAt} — entry behaving as absent (fail-safe). ` +
|
|
136
|
+
`Refresh reviewedAt/expiresAt in data/skills-security-allowlist.json or remove.`);
|
|
137
|
+
}
|
|
138
|
+
/** Reset expiry-warning dedupe cache. Exposed for tests. */
|
|
139
|
+
export function _resetExpiryWarningCache() {
|
|
140
|
+
loggedExpirySet.clear();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Empty matcher — returns false for every check. Used when the allowlist file
|
|
144
|
+
* is absent and for callers that want to opt out without conditional plumbing.
|
|
145
|
+
*/
|
|
146
|
+
export const EMPTY_ALLOWLIST = {
|
|
147
|
+
isAllowed() {
|
|
148
|
+
return false;
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Load + validate an allowlist JSON file and return a matcher.
|
|
153
|
+
*
|
|
154
|
+
* If `path` does not exist, returns EMPTY_ALLOWLIST. A malformed file throws
|
|
155
|
+
* (fail-safe toward quarantine — never silently skip validation).
|
|
156
|
+
*/
|
|
157
|
+
export function loadAllowlist(path) {
|
|
158
|
+
if (!fs.existsSync(path)) {
|
|
159
|
+
return EMPTY_ALLOWLIST;
|
|
160
|
+
}
|
|
161
|
+
const raw = fs.readFileSync(path, 'utf-8');
|
|
162
|
+
let parsed;
|
|
163
|
+
try {
|
|
164
|
+
parsed = JSON.parse(raw);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
throw new Error(`Allowlist file ${path} is not valid JSON: ${err.message}`);
|
|
168
|
+
}
|
|
169
|
+
const file = parseAllowlistFile(parsed);
|
|
170
|
+
return new EntryListMatcher(file.allowlist);
|
|
171
|
+
}
|
|
172
|
+
/** Build a matcher from an in-memory entry list (test + inline use). */
|
|
173
|
+
export function buildMatcher(entries) {
|
|
174
|
+
// Run the same validation pass as file load to catch unsafe patterns.
|
|
175
|
+
entries.forEach((entry, i) => validateEntryShape(entry, i));
|
|
176
|
+
return new EntryListMatcher(entries);
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=allowlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/allowlist.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Main scanning logic for imported skills.
|
|
5
5
|
*/
|
|
6
6
|
import { SecurityScanner } from '../../security/index.js';
|
|
7
|
-
import type { ImportedSkill, SkillScanResult, ScannerCliOptions } from './types.js';
|
|
7
|
+
import type { AllowlistMatcher, ImportedSkill, SkillScanResult, ScannerCliOptions } from './types.js';
|
|
8
8
|
import { type TrustScorerConfig } from './trust-scorer.js';
|
|
9
9
|
/**
|
|
10
10
|
* Scanner configuration
|
|
@@ -22,18 +22,26 @@ export interface ScannerConfig {
|
|
|
22
22
|
trustConfig: TrustScorerConfig;
|
|
23
23
|
/** Progress logging interval */
|
|
24
24
|
progressInterval: number;
|
|
25
|
+
/** SMI-4396: Path to the version-controlled allowlist file. */
|
|
26
|
+
allowlistPath: string;
|
|
25
27
|
}
|
|
26
28
|
/** Default scanner configuration */
|
|
27
29
|
export declare const DEFAULT_CONFIG: ScannerConfig;
|
|
28
30
|
/**
|
|
29
31
|
* Scan a single skill and return the result
|
|
30
32
|
*
|
|
33
|
+
* SMI-4396: accepts an optional AllowlistMatcher. Findings whose
|
|
34
|
+
* (skillId, type, message/location) match a non-expired allowlist entry are
|
|
35
|
+
* excluded from the quarantine decision. severityCategory still reflects
|
|
36
|
+
* the raw findings so the security report preserves audit visibility.
|
|
37
|
+
*
|
|
31
38
|
* @param skill - The skill to scan
|
|
32
39
|
* @param scanner - The security scanner instance
|
|
33
40
|
* @param config - Trust scorer configuration
|
|
41
|
+
* @param allowlist - Optional per-skill allowlist (SMI-4396)
|
|
34
42
|
* @returns The scan result
|
|
35
43
|
*/
|
|
36
|
-
export declare function scanSkill(skill: ImportedSkill, scanner: SecurityScanner, config?: TrustScorerConfig): SkillScanResult;
|
|
44
|
+
export declare function scanSkill(skill: ImportedSkill, scanner: SecurityScanner, config?: TrustScorerConfig, allowlist?: AllowlistMatcher): SkillScanResult;
|
|
37
45
|
/** Default CLI options */
|
|
38
46
|
export declare const DEFAULT_CLI_OPTIONS: ScannerCliOptions;
|
|
39
47
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/scanner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAEf,iBAAiB,EAElB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/scanner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EAEf,iBAAiB,EAElB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAKL,KAAK,iBAAiB,EAEvB,MAAM,mBAAmB,CAAA;AA8B1B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,sBAAsB;IACtB,cAAc,EAAE;QACd,aAAa,EAAE,MAAM,CAAA;KACtB,CAAA;IACD,0BAA0B;IAC1B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAA;IACxB,+DAA+D;IAC/D,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,oCAAoC;AACpC,eAAO,MAAM,cAAc,EAAE,aAS5B,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,MAAM,GAAE,iBAAwC,EAChD,SAAS,GAAE,gBAAkC,GAC5C,eAAe,CAgBjB;AAED,0BAA0B;AAC1B,eAAO,MAAM,mBAAmB,EAAE,iBAKjC,CAAA;AA0DD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,aAA8B,EACtC,UAAU,GAAE,OAAO,CAAC,iBAAiB,CAAM,GAC1C,OAAO,CAAC,IAAI,CAAC,CAmLf"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { SecurityScanner } from '../../security/index.js';
|
|
8
|
+
import { EMPTY_ALLOWLIST, loadAllowlist } from './allowlist.js';
|
|
8
9
|
import { shouldQuarantine, getPassFailStats, calculateAverageRiskScore, calculateMaxRiskScore, DEFAULT_TRUST_CONFIG, } from './trust-scorer.js';
|
|
9
10
|
import { determineSeverityCategory, countBySeverity } from './categorizer.js';
|
|
10
11
|
import { extractScannableContent, readImportedSkills, ensureDirectoryExists, fileExists, writeJsonFile, } from './file-scanner.js';
|
|
@@ -19,19 +20,26 @@ export const DEFAULT_CONFIG = {
|
|
|
19
20
|
},
|
|
20
21
|
trustConfig: DEFAULT_TRUST_CONFIG,
|
|
21
22
|
progressInterval: 100,
|
|
23
|
+
allowlistPath: './data/skills-security-allowlist.json',
|
|
22
24
|
};
|
|
23
25
|
/**
|
|
24
26
|
* Scan a single skill and return the result
|
|
25
27
|
*
|
|
28
|
+
* SMI-4396: accepts an optional AllowlistMatcher. Findings whose
|
|
29
|
+
* (skillId, type, message/location) match a non-expired allowlist entry are
|
|
30
|
+
* excluded from the quarantine decision. severityCategory still reflects
|
|
31
|
+
* the raw findings so the security report preserves audit visibility.
|
|
32
|
+
*
|
|
26
33
|
* @param skill - The skill to scan
|
|
27
34
|
* @param scanner - The security scanner instance
|
|
28
35
|
* @param config - Trust scorer configuration
|
|
36
|
+
* @param allowlist - Optional per-skill allowlist (SMI-4396)
|
|
29
37
|
* @returns The scan result
|
|
30
38
|
*/
|
|
31
|
-
export function scanSkill(skill, scanner, config = DEFAULT_TRUST_CONFIG) {
|
|
39
|
+
export function scanSkill(skill, scanner, config = DEFAULT_TRUST_CONFIG, allowlist = EMPTY_ALLOWLIST) {
|
|
32
40
|
const content = extractScannableContent(skill);
|
|
33
41
|
const report = scanner.scan(skill.id, content);
|
|
34
|
-
const isQuarantined = shouldQuarantine(report, config);
|
|
42
|
+
const isQuarantined = shouldQuarantine(report, config, allowlist);
|
|
35
43
|
const severityCategory = determineSeverityCategory(report.findings);
|
|
36
44
|
return {
|
|
37
45
|
skillId: skill.id,
|
|
@@ -148,6 +156,10 @@ export async function scanImportedSkills(inputPath, config = DEFAULT_CONFIG, cli
|
|
|
148
156
|
}
|
|
149
157
|
// Initialize scanner
|
|
150
158
|
const scanner = new SecurityScanner(config.scannerOptions);
|
|
159
|
+
// SMI-4396: Load the security allowlist (returns EMPTY_ALLOWLIST if the file
|
|
160
|
+
// doesn't exist, so pre-SMI-4396 environments keep working). A malformed
|
|
161
|
+
// file throws — fail-safe toward quarantine, never silently proceed.
|
|
162
|
+
const allowlist = loadAllowlist(config.allowlistPath);
|
|
151
163
|
// Scan all skills
|
|
152
164
|
const results = [];
|
|
153
165
|
const allFindings = [];
|
|
@@ -156,7 +168,7 @@ export async function scanImportedSkills(inputPath, config = DEFAULT_CONFIG, cli
|
|
|
156
168
|
const useProgressBar = !options.json && !options.quiet && process.stdout.isTTY;
|
|
157
169
|
for (const skill of skills) {
|
|
158
170
|
processedCount++;
|
|
159
|
-
const result = scanSkill(skill, scanner, config.trustConfig);
|
|
171
|
+
const result = scanSkill(skill, scanner, config.trustConfig, allowlist);
|
|
160
172
|
results.push(result);
|
|
161
173
|
// Collect findings with skill context
|
|
162
174
|
for (const finding of result.scanReport.findings) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/scanner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SMI-1189: Trust Scorer
|
|
3
|
+
* SMI-4396: Allowlist-aware quarantine predicate.
|
|
3
4
|
*
|
|
4
5
|
* Trust score calculation and quarantine decision logic.
|
|
5
6
|
*/
|
|
6
7
|
import type { ScanReport } from '../../security/index.js';
|
|
8
|
+
import type { AllowlistMatcher } from './types.js';
|
|
7
9
|
/**
|
|
8
10
|
* Configuration for trust scoring
|
|
9
11
|
*/
|
|
@@ -14,18 +16,30 @@ export interface TrustScorerConfig {
|
|
|
14
16
|
/** Default trust scorer configuration */
|
|
15
17
|
export declare const DEFAULT_TRUST_CONFIG: TrustScorerConfig;
|
|
16
18
|
/**
|
|
17
|
-
* Determines if a skill should be quarantined based on findings
|
|
19
|
+
* Determines if a skill should be quarantined based on findings.
|
|
18
20
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* SMI-4396: when an allowlist matcher is provided, findings the matcher
|
|
22
|
+
* approves are removed BEFORE the quarantine check runs, and the risk score
|
|
23
|
+
* is recomputed from the filtered set rather than trusting report.riskScore
|
|
24
|
+
* (which was computed pre-allowlist inside SecurityScanner.scan).
|
|
25
|
+
*
|
|
26
|
+
* !report.passed is intentionally NOT part of the predicate: `passed` is
|
|
27
|
+
* also computed pre-allowlist, so keeping it here would re-quarantine every
|
|
28
|
+
* allowlisted skill whose raw scan had critical/high findings — defeating
|
|
29
|
+
* the allowlist's purpose. The new two-clause predicate still covers the old
|
|
30
|
+
* semantics: any scan that was `passed: false` must have had at least one
|
|
31
|
+
* critical/high finding OR score >= threshold, both of which are still caught.
|
|
32
|
+
*
|
|
33
|
+
* A skill is quarantined if ANY of:
|
|
34
|
+
* 1. Post-allowlist findings contain a critical or high severity entry
|
|
35
|
+
* 2. Post-allowlist risk score >= quarantineThreshold
|
|
23
36
|
*
|
|
24
37
|
* @param report - The scan report for the skill
|
|
25
38
|
* @param config - Trust scorer configuration
|
|
39
|
+
* @param allowlist - Optional per-skill allowlist (SMI-4396)
|
|
26
40
|
* @returns true if the skill should be quarantined
|
|
27
41
|
*/
|
|
28
|
-
export declare function shouldQuarantine(report: ScanReport, config?: TrustScorerConfig): boolean;
|
|
42
|
+
export declare function shouldQuarantine(report: ScanReport, config?: TrustScorerConfig, allowlist?: AllowlistMatcher): boolean;
|
|
29
43
|
/**
|
|
30
44
|
* Calculate average risk score from results
|
|
31
45
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trust-scorer.d.ts","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/trust-scorer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"trust-scorer.d.ts","sourceRoot":"","sources":["../../../../src/scripts/skill-scanner/trust-scorer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAA;CAC5B;AAED,yCAAyC;AACzC,eAAO,MAAM,oBAAoB,EAAE,iBAElC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,iBAAwC,EAChD,SAAS,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAWT;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,GAAG,MAAM,CAM5F;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,GAAG,MAAM,CAGxF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG;IAC5E,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB,CAKA"}
|