@skillsmith/core 0.11.2 → 0.11.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 +15 -0
- package/README.md +6 -7
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/analysis/McpReferenceExtractor.d.ts +59 -5
- package/dist/src/analysis/McpReferenceExtractor.d.ts.map +1 -1
- package/dist/src/analysis/McpReferenceExtractor.hardening.test.d.ts +2 -0
- package/dist/src/analysis/McpReferenceExtractor.hardening.test.d.ts.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.hardening.test.js +278 -0
- package/dist/src/analysis/McpReferenceExtractor.hardening.test.js.map +1 -0
- package/dist/src/analysis/McpReferenceExtractor.js +276 -20
- package/dist/src/analysis/McpReferenceExtractor.js.map +1 -1
- package/dist/src/analysis/McpReferenceExtractor.test.js +4 -0
- package/dist/src/analysis/McpReferenceExtractor.test.js.map +1 -1
- package/dist/src/config/config-atomic-write.d.ts +58 -0
- package/dist/src/config/config-atomic-write.d.ts.map +1 -0
- package/dist/src/config/config-atomic-write.js +151 -0
- package/dist/src/config/config-atomic-write.js.map +1 -0
- package/dist/src/config/config-atomic-write.test.d.ts +9 -0
- package/dist/src/config/config-atomic-write.test.d.ts.map +1 -0
- package/dist/src/config/config-atomic-write.test.js +92 -0
- package/dist/src/config/config-atomic-write.test.js.map +1 -0
- package/dist/src/config/device-identity.d.ts +16 -0
- package/dist/src/config/device-identity.d.ts.map +1 -1
- package/dist/src/config/device-identity.js +82 -14
- package/dist/src/config/device-identity.js.map +1 -1
- package/dist/src/config/device-identity.test.js +158 -1
- package/dist/src/config/device-identity.test.js.map +1 -1
- package/dist/src/config/index.d.ts +14 -0
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/index.js +31 -15
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/exports/services.d.ts +2 -1
- package/dist/src/exports/services.d.ts.map +1 -1
- package/dist/src/exports/services.js +1 -0
- package/dist/src/exports/services.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexer/SwarmIndexer.d.ts +1 -1
- package/dist/src/indexer/SwarmIndexer.js +2 -2
- package/dist/src/indexer/SwarmIndexer.js.map +1 -1
- package/dist/src/install/paths.d.ts +1 -1
- package/dist/src/install/paths.d.ts.map +1 -1
- package/dist/src/install/paths.js +2 -0
- package/dist/src/install/paths.js.map +1 -1
- package/dist/src/install/paths.test.js +10 -1
- package/dist/src/install/paths.test.js.map +1 -1
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js +5 -0
- package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
- package/dist/src/security/audit-types.d.ts +1 -1
- package/dist/src/security/audit-types.d.ts.map +1 -1
- package/dist/src/security/audit-types.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.exec.d.ts +7 -0
- package/dist/src/security/scanner/SecurityScanner.exec.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.exec.js +10 -74
- package/dist/src/security/scanner/SecurityScanner.exec.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.formatters.d.ts +14 -1
- package/dist/src/security/scanner/SecurityScanner.formatters.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.formatters.js +33 -0
- package/dist/src/security/scanner/SecurityScanner.formatters.js.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.formatters.test.d.ts +9 -0
- package/dist/src/security/scanner/SecurityScanner.formatters.test.d.ts.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.formatters.test.js +65 -0
- package/dist/src/security/scanner/SecurityScanner.formatters.test.js.map +1 -0
- package/dist/src/security/scanner/SecurityScanner.helpers.d.ts.map +1 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.js +15 -1
- package/dist/src/security/scanner/SecurityScanner.helpers.js.map +1 -1
- package/dist/src/security/scanner/confusables.d.ts +28 -0
- package/dist/src/security/scanner/confusables.d.ts.map +1 -0
- package/dist/src/security/scanner/confusables.js +87 -0
- package/dist/src/security/scanner/confusables.js.map +1 -0
- package/dist/src/security/scanner/confusables.test.d.ts +10 -0
- package/dist/src/security/scanner/confusables.test.d.ts.map +1 -0
- package/dist/src/security/scanner/confusables.test.js +44 -0
- package/dist/src/security/scanner/confusables.test.js.map +1 -0
- package/dist/src/security/scanner/index.d.ts +7 -1
- package/dist/src/security/scanner/index.d.ts.map +1 -1
- package/dist/src/security/scanner/index.js +13 -0
- package/dist/src/security/scanner/index.js.map +1 -1
- package/dist/src/security/scanner/types.d.ts +14 -1
- package/dist/src/security/scanner/types.d.ts.map +1 -1
- package/dist/src/security/scanner/typosquat-reference-list.d.ts +54 -0
- package/dist/src/security/scanner/typosquat-reference-list.d.ts.map +1 -0
- package/dist/src/security/scanner/typosquat-reference-list.js +55 -0
- package/dist/src/security/scanner/typosquat-reference-list.js.map +1 -0
- package/dist/src/security/scanner/typosquat-reference-list.test.d.ts +5 -0
- package/dist/src/security/scanner/typosquat-reference-list.test.d.ts.map +1 -0
- package/dist/src/security/scanner/typosquat-reference-list.test.js +52 -0
- package/dist/src/security/scanner/typosquat-reference-list.test.js.map +1 -0
- package/dist/src/security/scanner/typosquat.d.ts +100 -0
- package/dist/src/security/scanner/typosquat.d.ts.map +1 -0
- package/dist/src/security/scanner/typosquat.js +256 -0
- package/dist/src/security/scanner/typosquat.js.map +1 -0
- package/dist/src/security/scanner/typosquat.test.d.ts +12 -0
- package/dist/src/security/scanner/typosquat.test.d.ts.map +1 -0
- package/dist/src/security/scanner/typosquat.test.js +140 -0
- package/dist/src/security/scanner/typosquat.test.js.map +1 -0
- package/dist/src/security/scanner/weights.d.ts.map +1 -1
- package/dist/src/security/scanner/weights.js +10 -0
- package/dist/src/security/scanner/weights.js.map +1 -1
- package/dist/src/services/skill-installation.helpers.d.ts +21 -0
- package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
- package/dist/src/services/skill-installation.helpers.js +46 -2
- package/dist/src/services/skill-installation.helpers.js.map +1 -1
- package/dist/src/services/skill-installation.helpers.test.d.ts +2 -0
- package/dist/src/services/skill-installation.helpers.test.d.ts.map +1 -0
- package/dist/src/services/skill-installation.helpers.test.js +80 -0
- package/dist/src/services/skill-installation.helpers.test.js.map +1 -0
- package/dist/src/sync/inventory-collector.d.ts +15 -4
- package/dist/src/sync/inventory-collector.d.ts.map +1 -1
- package/dist/src/sync/inventory-collector.js +73 -24
- package/dist/src/sync/inventory-collector.js.map +1 -1
- package/dist/src/sync/inventory-collector.test.d.ts +15 -1
- package/dist/src/sync/inventory-collector.test.d.ts.map +1 -1
- package/dist/src/sync/inventory-collector.test.js +75 -5
- package/dist/src/sync/inventory-collector.test.js.map +1 -1
- package/dist/src/telemetry/tracer-imports.d.ts +1 -1
- package/dist/src/telemetry/tracer-imports.js +1 -1
- package/dist/src/telemetry/tracer.js +1 -1
- package/dist/tests/SecurityScanner.scoring.test.js +60 -0
- package/dist/tests/SecurityScanner.scoring.test.js.map +1 -1
- package/dist/tests/SwarmIndexer.test.js +4 -5
- package/dist/tests/SwarmIndexer.test.js.map +1 -1
- package/dist/tests/security/scanner-regression-guard.test.js +1 -0
- package/dist/tests/security/scanner-regression-guard.test.js.map +1 -1
- package/dist/tests/services/aidefence-feedback.test.js +1 -0
- package/dist/tests/services/aidefence-feedback.test.js.map +1 -1
- package/dist/tests/skill-scanner/allowlist.test.js +1 -0
- package/dist/tests/skill-scanner/allowlist.test.js.map +1 -1
- package/package.json +13 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typosquat.js","sourceRoot":"","sources":["../../../../src/security/scanner/typosquat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-595: typosquat.ts — detector tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers the Wave 1 acceptance criteria directly:
|
|
5
|
+
* - exact-skeleton impersonation (fires on exact fold match only, never
|
|
6
|
+
* substring/affix)
|
|
7
|
+
* - Levenshtein edit-distance <= 2
|
|
8
|
+
* - authority-claiming affix, independent of the exact-skeleton rule
|
|
9
|
+
* - enforcement-mode severity capping
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=typosquat.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typosquat.test.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/typosquat.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-595: typosquat.ts — detector tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers the Wave 1 acceptance criteria directly:
|
|
5
|
+
* - exact-skeleton impersonation (fires on exact fold match only, never
|
|
6
|
+
* substring/affix)
|
|
7
|
+
* - Levenshtein edit-distance <= 2
|
|
8
|
+
* - authority-claiming affix, independent of the exact-skeleton rule
|
|
9
|
+
* - enforcement-mode severity capping
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect } from 'vitest';
|
|
12
|
+
import { BRAND_ALIASES, levenshteinDistance, scanTyposquat, applyTyposquatEnforcementMode, resolveTyposquatEnforcementMode, detectTyposquat, DEFAULT_TYPOSQUAT_ENFORCEMENT_MODE, } from './typosquat.js';
|
|
13
|
+
import { HIGH_TRUST_OWNERS } from '../../scripts/github-import/signal-of-intent.js';
|
|
14
|
+
const findByCategory = (findings, category) => findings.filter((f) => f.category === category);
|
|
15
|
+
describe('BRAND_ALIASES (SMI-595 §3)', () => {
|
|
16
|
+
it('maps every alias to a real HIGH_TRUST_OWNERS entry', () => {
|
|
17
|
+
for (const owner of Object.values(BRAND_ALIASES)) {
|
|
18
|
+
expect(HIGH_TRUST_OWNERS.has(owner)).toBe(true);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it('keys are lowercase brand tokens', () => {
|
|
22
|
+
for (const brand of Object.keys(BRAND_ALIASES)) {
|
|
23
|
+
expect(brand).toBe(brand.toLowerCase());
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('levenshteinDistance', () => {
|
|
28
|
+
it('is 0 for identical strings', () => {
|
|
29
|
+
expect(levenshteinDistance('anthropic', 'anthropic')).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
it('counts a single substitution as distance 1', () => {
|
|
32
|
+
expect(levenshteinDistance('claude-code', 'claude-cude')).toBe(1);
|
|
33
|
+
});
|
|
34
|
+
it('counts a single deletion as distance 1', () => {
|
|
35
|
+
expect(levenshteinDistance('claude-code', 'claude-cod')).toBe(1);
|
|
36
|
+
});
|
|
37
|
+
it('matches the classic kitten/sitting example (distance 3)', () => {
|
|
38
|
+
expect(levenshteinDistance('kitten', 'sitting')).toBe(3);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('scanTyposquat — exact-skeleton impersonation (rule 1)', () => {
|
|
42
|
+
it('flags a homoglyph-substituted exact match (Cyrillic а for Latin a)', () => {
|
|
43
|
+
const referenceNames = new Set(['anthropic']);
|
|
44
|
+
const findings = scanTyposquat('аnthropic', referenceNames); // Cyrillic а (U+0430)
|
|
45
|
+
expect(findByCategory(findings, 'typosquat:impersonation-exact-skeleton')).toHaveLength(1);
|
|
46
|
+
expect(findings[0].severity).toBe('critical');
|
|
47
|
+
expect(findings[0].confidence).toBe('high');
|
|
48
|
+
});
|
|
49
|
+
it('does NOT flag a substring match (anthropic-community-tools) by this rule alone', () => {
|
|
50
|
+
const referenceNames = new Set(['anthropic']);
|
|
51
|
+
const findings = scanTyposquat('anthropic-community-tools', referenceNames);
|
|
52
|
+
expect(findByCategory(findings, 'typosquat:impersonation-exact-skeleton')).toHaveLength(0);
|
|
53
|
+
// and, more strongly for this specific case, no other rule fires either
|
|
54
|
+
// (no Levenshtein-range match, no authority-claiming affix present).
|
|
55
|
+
expect(findings).toHaveLength(0);
|
|
56
|
+
});
|
|
57
|
+
it('does NOT flag a pure case difference (not a confusable substitution)', () => {
|
|
58
|
+
const referenceNames = new Set(['anthropic']);
|
|
59
|
+
const findings = scanTyposquat('Anthropic', referenceNames);
|
|
60
|
+
expect(findByCategory(findings, 'typosquat:impersonation-exact-skeleton')).toHaveLength(0);
|
|
61
|
+
});
|
|
62
|
+
it('does NOT flag the reference name matching itself', () => {
|
|
63
|
+
const referenceNames = new Set(['anthropic']);
|
|
64
|
+
const findings = scanTyposquat('anthropic', referenceNames);
|
|
65
|
+
expect(findings).toHaveLength(0);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('scanTyposquat — Levenshtein edit-distance <= 2 (rule 2)', () => {
|
|
69
|
+
const referenceNames = new Set(['claude-code']); // models a HIGH_TRUST_OWNERS-published skill name
|
|
70
|
+
it('flags an edit-distance-1 variant', () => {
|
|
71
|
+
const findings = scanTyposquat('claude-cod', referenceNames);
|
|
72
|
+
expect(findByCategory(findings, 'typosquat:levenshtein')).toHaveLength(1);
|
|
73
|
+
expect(findings[0].severity).toBe('high');
|
|
74
|
+
});
|
|
75
|
+
it('flags an edit-distance-2 variant', () => {
|
|
76
|
+
const findings = scanTyposquat('claude-cudo', referenceNames); // 2 substitutions
|
|
77
|
+
expect(findByCategory(findings, 'typosquat:levenshtein')).toHaveLength(1);
|
|
78
|
+
});
|
|
79
|
+
it('does NOT flag an edit-distance-3+ variant (same length, no shared characters)', () => {
|
|
80
|
+
const findings = scanTyposquat('zzzzzzzzzzz', referenceNames); // same length as "claude-code" (11)
|
|
81
|
+
expect(findByCategory(findings, 'typosquat:levenshtein')).toHaveLength(0);
|
|
82
|
+
});
|
|
83
|
+
it('does NOT flag an unrelated name', () => {
|
|
84
|
+
const findings = scanTyposquat('a-totally-unrelated-skill-name', referenceNames);
|
|
85
|
+
expect(findings).toHaveLength(0);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('scanTyposquat — authority-claiming affix, independent of rule 1 (Change #5)', () => {
|
|
89
|
+
// Same base brand token ("anthropic") used for both the flagged and
|
|
90
|
+
// not-flagged cases, proving the two checks are genuinely independent.
|
|
91
|
+
const referenceNames = new Set(['anthropic']);
|
|
92
|
+
it('flags a brand token + authority-claiming affix (anthropic-mcp-official)', () => {
|
|
93
|
+
const findings = scanTyposquat('anthropic-mcp-official', referenceNames);
|
|
94
|
+
expect(findByCategory(findings, 'typosquat:authority-affix')).toHaveLength(1);
|
|
95
|
+
expect(findings.find((f) => f.category === 'typosquat:authority-affix')?.severity).toBe('critical');
|
|
96
|
+
});
|
|
97
|
+
it('does NOT flag a brand token + benign functional affix (anthropic-mcp)', () => {
|
|
98
|
+
const findings = scanTyposquat('anthropic-mcp', referenceNames);
|
|
99
|
+
expect(findings).toHaveLength(0);
|
|
100
|
+
});
|
|
101
|
+
it('does NOT flag a brand token + benign functional affix (anthropic-tools)', () => {
|
|
102
|
+
const findings = scanTyposquat('anthropic-tools', referenceNames);
|
|
103
|
+
expect(findings).toHaveLength(0);
|
|
104
|
+
});
|
|
105
|
+
it('does NOT flag other claimed-authority affixes without a brand token', () => {
|
|
106
|
+
const findings = scanTyposquat('totally-unrelated-official', referenceNames);
|
|
107
|
+
expect(findings).toHaveLength(0);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('applyTyposquatEnforcementMode / resolveTyposquatEnforcementMode (§6)', () => {
|
|
111
|
+
it('defaults to warn', () => {
|
|
112
|
+
expect(DEFAULT_TYPOSQUAT_ENFORCEMENT_MODE).toBe('warn');
|
|
113
|
+
expect(resolveTyposquatEnforcementMode(undefined)).toBe('warn');
|
|
114
|
+
});
|
|
115
|
+
it('resolves an explicit mode unchanged', () => {
|
|
116
|
+
expect(resolveTyposquatEnforcementMode('block')).toBe('block');
|
|
117
|
+
expect(resolveTyposquatEnforcementMode('off')).toBe('off');
|
|
118
|
+
});
|
|
119
|
+
it('warn mode caps critical/high severity at medium, regardless of raw confidence', () => {
|
|
120
|
+
const raw = scanTyposquat('anthropic-mcp-official', new Set(['anthropic']));
|
|
121
|
+
expect(raw[0].severity).toBe('critical'); // raw, uncapped
|
|
122
|
+
const capped = applyTyposquatEnforcementMode(raw, 'warn');
|
|
123
|
+
expect(capped[0].severity).toBe('medium');
|
|
124
|
+
expect(capped[0].confidence).toBe('high'); // confidence is untouched, only severity is capped
|
|
125
|
+
});
|
|
126
|
+
it('off mode discards all findings', () => {
|
|
127
|
+
const raw = scanTyposquat('anthropic-mcp-official', new Set(['anthropic']));
|
|
128
|
+
expect(applyTyposquatEnforcementMode(raw, 'off')).toHaveLength(0);
|
|
129
|
+
});
|
|
130
|
+
it('block mode passes findings through at raw severity', () => {
|
|
131
|
+
const raw = scanTyposquat('anthropic-mcp-official', new Set(['anthropic']));
|
|
132
|
+
const passed = applyTyposquatEnforcementMode(raw, 'block');
|
|
133
|
+
expect(passed[0].severity).toBe('critical');
|
|
134
|
+
});
|
|
135
|
+
it('detectTyposquat is a one-shot detect + apply-mode convenience wrapper, defaulting to warn', () => {
|
|
136
|
+
const findings = detectTyposquat('anthropic-mcp-official', new Set(['anthropic']));
|
|
137
|
+
expect(findings[0].severity).toBe('medium');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=typosquat.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typosquat.test.js","sourceRoot":"","sources":["../../../../src/security/scanner/typosquat.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"weights.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/weights.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAK7D,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"weights.d.ts","sourceRoot":"","sources":["../../../../src/security/scanner/weights.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAK7D,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA4BnD,CAAA"}
|
|
@@ -33,5 +33,15 @@ export const CATEGORY_WEIGHTS = {
|
|
|
33
33
|
// on its own (50 * 2.0 * 1.0 = 100 -> capped 100 -> * 0.40 = 40).
|
|
34
34
|
code_execution: 2.0,
|
|
35
35
|
obfuscated_directive: 2.0,
|
|
36
|
+
// SMI-595: a naming-similarity heuristic is advisory, not damning on its own —
|
|
37
|
+
// deliberately the same tier as sensitive_path/url, NOT the 1.7-2.0 tier used
|
|
38
|
+
// for jailbreak/exfiltration-class findings. Paired with the 0.04 coefficient
|
|
39
|
+
// in calculateRiskScore (the same coefficient already used for
|
|
40
|
+
// sensitivePaths/externalUrls/ssrf): a single medium-severity, high-confidence
|
|
41
|
+
// finding scores 15 * 1.2 * 1.0 = 18 -> contributes 18 * 0.04 = 0.72 (rounds to
|
|
42
|
+
// ~1) to the total; a saturated breakdown (capped at 100) contributes 4 —
|
|
43
|
+
// comfortably under the riskThreshold: 40 quarantine cutoff on its own. See the
|
|
44
|
+
// stacked-risk test in SecurityScanner.scoring.test.ts.
|
|
45
|
+
typosquat: 1.2,
|
|
36
46
|
};
|
|
37
47
|
//# sourceMappingURL=weights.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"weights.js","sourceRoot":"","sources":["../../../../src/security/scanner/weights.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqC;IAChE,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,QAAQ,EAAE,EAAE;CACb,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,SAAS,EAAE,GAAG;IACd,kBAAkB,EAAE,GAAG;IACvB,cAAc,EAAE,GAAG;IACnB,iBAAiB,EAAE,GAAG;IACtB,oBAAoB,EAAE,GAAG;IACzB,kBAAkB,EAAE,GAAG;IACvB,cAAc,EAAE,GAAG;IACnB,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,GAAG,EAAE,iDAAiD;IAClE,IAAI,EAAE,GAAG,EAAE,uCAAuC;IAClD,GAAG,EAAE,GAAG,EAAE,8CAA8C;IACxD,8EAA8E;IAC9E,iFAAiF;IACjF,kFAAkF;IAClF,kEAAkE;IAClE,cAAc,EAAE,GAAG;IACnB,oBAAoB,EAAE,GAAG;
|
|
1
|
+
{"version":3,"file":"weights.js","sourceRoot":"","sources":["../../../../src/security/scanner/weights.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqC;IAChE,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,QAAQ,EAAE,EAAE;CACb,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,SAAS,EAAE,GAAG;IACd,kBAAkB,EAAE,GAAG;IACvB,cAAc,EAAE,GAAG;IACnB,iBAAiB,EAAE,GAAG;IACtB,oBAAoB,EAAE,GAAG;IACzB,kBAAkB,EAAE,GAAG;IACvB,cAAc,EAAE,GAAG;IACnB,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,GAAG,EAAE,iDAAiD;IAClE,IAAI,EAAE,GAAG,EAAE,uCAAuC;IAClD,GAAG,EAAE,GAAG,EAAE,8CAA8C;IACxD,8EAA8E;IAC9E,iFAAiF;IACjF,kFAAkF;IAClF,kEAAkE;IAClE,cAAc,EAAE,GAAG;IACnB,oBAAoB,EAAE,GAAG;IACzB,+EAA+E;IAC/E,8EAA8E;IAC9E,8EAA8E;IAC9E,+DAA+D;IAC/D,+EAA+E;IAC/E,gFAAgF;IAChF,0EAA0E;IAC1E,gFAAgF;IAChF,wDAAwD;IACxD,SAAS,EAAE,GAAG;CACf,CAAA"}
|
|
@@ -26,6 +26,27 @@ export interface OptimizationResult {
|
|
|
26
26
|
}
|
|
27
27
|
export declare function hashContent(content: string): string;
|
|
28
28
|
export declare function generateTips(skillName: string, optimizationInfo: OptimizationInfo): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Read the MCP server names registered in the consuming project's
|
|
31
|
+
* `.mcp.json` (SMI-5676). Used to cross-check `extractMcpReferences`
|
|
32
|
+
* candidates against what's *actually* configured, so a stale/renamed
|
|
33
|
+
* reference (e.g. `claude-flow` after this project's own rename to `ruflo`)
|
|
34
|
+
* gets tagged `unregistered` in `serverResolutions` instead of silently
|
|
35
|
+
* asserted as a real dependency — without ever dropping a candidate that
|
|
36
|
+
* simply isn't installed *yet*.
|
|
37
|
+
*
|
|
38
|
+
* Fails open: returns `undefined` (not `[]`) when `.mcp.json` is missing,
|
|
39
|
+
* unreadable, or unparseable — `extractMcpReferences` treats `undefined` as
|
|
40
|
+
* "no information available" (`serverResolutions` = `'unknown'`), whereas
|
|
41
|
+
* `[]` would mean "zero servers registered", incorrectly tagging every real
|
|
42
|
+
* candidate `unregistered`.
|
|
43
|
+
*
|
|
44
|
+
* @param projectRoot - Directory to look for `.mcp.json` in (defaults to
|
|
45
|
+
* `process.cwd()`, matching the convention used elsewhere in the codebase
|
|
46
|
+
* for locating a consuming project's config, e.g.
|
|
47
|
+
* `packages/mcp-server/src/context/project-detector.ts`).
|
|
48
|
+
*/
|
|
49
|
+
export declare function getRegisteredMcpServers(projectRoot?: string): string[] | undefined;
|
|
29
50
|
export declare function extractDepIntel(skillMdContent: string): DepIntelResult;
|
|
30
51
|
/**
|
|
31
52
|
* Extract + persist dependency intelligence for a skill.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-installation.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"skill-installation.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* file to meet the 500-line standard.
|
|
8
8
|
*/
|
|
9
9
|
import * as fs from 'fs/promises';
|
|
10
|
+
import { existsSync, readFileSync } from 'fs';
|
|
10
11
|
import * as path from 'path';
|
|
11
12
|
import { createHash } from 'crypto';
|
|
12
13
|
import { extractMcpReferences } from '../analysis/McpReferenceExtractor.js';
|
|
@@ -39,10 +40,53 @@ export function generateTips(skillName, optimizationInfo) {
|
|
|
39
40
|
tips.push('', 'To uninstall: use the uninstall_skill tool');
|
|
40
41
|
return tips;
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Read the MCP server names registered in the consuming project's
|
|
45
|
+
* `.mcp.json` (SMI-5676). Used to cross-check `extractMcpReferences`
|
|
46
|
+
* candidates against what's *actually* configured, so a stale/renamed
|
|
47
|
+
* reference (e.g. `claude-flow` after this project's own rename to `ruflo`)
|
|
48
|
+
* gets tagged `unregistered` in `serverResolutions` instead of silently
|
|
49
|
+
* asserted as a real dependency — without ever dropping a candidate that
|
|
50
|
+
* simply isn't installed *yet*.
|
|
51
|
+
*
|
|
52
|
+
* Fails open: returns `undefined` (not `[]`) when `.mcp.json` is missing,
|
|
53
|
+
* unreadable, or unparseable — `extractMcpReferences` treats `undefined` as
|
|
54
|
+
* "no information available" (`serverResolutions` = `'unknown'`), whereas
|
|
55
|
+
* `[]` would mean "zero servers registered", incorrectly tagging every real
|
|
56
|
+
* candidate `unregistered`.
|
|
57
|
+
*
|
|
58
|
+
* @param projectRoot - Directory to look for `.mcp.json` in (defaults to
|
|
59
|
+
* `process.cwd()`, matching the convention used elsewhere in the codebase
|
|
60
|
+
* for locating a consuming project's config, e.g.
|
|
61
|
+
* `packages/mcp-server/src/context/project-detector.ts`).
|
|
62
|
+
*/
|
|
63
|
+
export function getRegisteredMcpServers(projectRoot = process.cwd()) {
|
|
64
|
+
const mcpJsonPath = path.join(projectRoot, '.mcp.json');
|
|
65
|
+
if (!existsSync(mcpJsonPath))
|
|
66
|
+
return undefined;
|
|
67
|
+
try {
|
|
68
|
+
const raw = readFileSync(mcpJsonPath, 'utf-8');
|
|
69
|
+
const parsed = JSON.parse(raw);
|
|
70
|
+
if (!parsed || typeof parsed !== 'object')
|
|
71
|
+
return undefined;
|
|
72
|
+
const mcpServers = parsed.mcpServers;
|
|
73
|
+
if (!mcpServers || typeof mcpServers !== 'object' || Array.isArray(mcpServers)) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
return Object.keys(mcpServers);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
42
82
|
export function extractDepIntel(skillMdContent) {
|
|
43
|
-
const mcpResult = extractMcpReferences(skillMdContent);
|
|
83
|
+
const mcpResult = extractMcpReferences(skillMdContent, getRegisteredMcpServers());
|
|
44
84
|
const warnings = [];
|
|
45
85
|
for (const server of mcpResult.highConfidenceServers) {
|
|
86
|
+
// Don't warn about a server we positively confirmed IS configured —
|
|
87
|
+
// only flag servers we couldn't confirm (unregistered/unknown).
|
|
88
|
+
if (mcpResult.serverResolutions?.[server] === 'registered')
|
|
89
|
+
continue;
|
|
46
90
|
warnings.push("MCP server '" + server + "' is referenced but may not be configured");
|
|
47
91
|
}
|
|
48
92
|
return {
|
|
@@ -64,7 +108,7 @@ export function extractDepIntel(skillMdContent) {
|
|
|
64
108
|
* value directly.
|
|
65
109
|
*/
|
|
66
110
|
export function persistDependencies(repo, skillId, content, declared) {
|
|
67
|
-
const mcpResult = extractMcpReferences(content);
|
|
111
|
+
const mcpResult = extractMcpReferences(content, getRegisteredMcpServers());
|
|
68
112
|
const merged = mergeDependencies(declared, mcpResult);
|
|
69
113
|
if (merged.length === 0)
|
|
70
114
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-installation.helpers.js","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAKnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAA;AAE5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAUjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAY5D,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,gBAAkC;IAChF,MAAM,IAAI,GAAG;QACX,SAAS,GAAG,SAAS,GAAG,2BAA2B;QACnD,yDAAyD,GAAG,SAAS,GAAG,eAAe;QACvF,6CAA6C;KAC9C,CAAA;IAED,IAAI,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,iDAAiD,CAAC,CAAA;QAChE,IAAI,gBAAgB,CAAC,qBAAqB,IAAI,gBAAgB,CAAC,qBAAqB,GAAG,CAAC,EAAE,CAAC;YACzF,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,qBAAqB,GAAG,mBAAmB,CAAC,CAAA;QAC5F,CAAC;QACD,IAAI,gBAAgB,CAAC,SAAS,IAAI,gBAAgB,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,GAAG,qBAAqB,CAAC,CAAA;QAC/E,CAAC;QACD,IAAI,gBAAgB,CAAC,iBAAiB,IAAI,gBAAgB,CAAC,YAAY,EAAE,CAAC;YACxE,IAAI,CAAC,IAAI,CAAC,oCAAoC,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;QACjF,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,4CAA4C,CAAC,CAAA;IAC3D,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,cAAsB;IACpD,MAAM,SAAS,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"skill-installation.helpers.js","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-installation.helpers.test.d.ts","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for the SMI-5676 `.mcp.json` cross-check additions to
|
|
3
|
+
* skill-installation.helpers.ts (`getRegisteredMcpServers`, and the
|
|
4
|
+
* resolution-aware warning filtering in `extractDepIntel`).
|
|
5
|
+
* @module @skillsmith/core/services/skill-installation.helpers.test
|
|
6
|
+
* @see SMI-5676: Wave 1 Step 3b — harden extractMcpReferences
|
|
7
|
+
*/
|
|
8
|
+
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as os from 'os';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { extractDepIntel, getRegisteredMcpServers } from './skill-installation.helpers.js';
|
|
13
|
+
describe('getRegisteredMcpServers (SMI-5676)', () => {
|
|
14
|
+
let tmpDir;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'skillsmith-mcp-json-'));
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
20
|
+
});
|
|
21
|
+
it('returns undefined when .mcp.json does not exist (fail open)', () => {
|
|
22
|
+
expect(getRegisteredMcpServers(tmpDir)).toBeUndefined();
|
|
23
|
+
});
|
|
24
|
+
it('returns the registered server names when .mcp.json is valid', () => {
|
|
25
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: { ruflo: {}, skillsmith: {} } }));
|
|
26
|
+
expect(getRegisteredMcpServers(tmpDir)).toEqual(['ruflo', 'skillsmith']);
|
|
27
|
+
});
|
|
28
|
+
it('returns an empty array when mcpServers is present but empty (checked, found nothing)', () => {
|
|
29
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: {} }));
|
|
30
|
+
expect(getRegisteredMcpServers(tmpDir)).toEqual([]);
|
|
31
|
+
});
|
|
32
|
+
it('fails open (returns undefined) on unparseable JSON', () => {
|
|
33
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), '{ not valid json');
|
|
34
|
+
expect(getRegisteredMcpServers(tmpDir)).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
it('fails open (returns undefined) when the mcpServers key is missing', () => {
|
|
37
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ foo: 'bar' }));
|
|
38
|
+
expect(getRegisteredMcpServers(tmpDir)).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
it('fails open (returns undefined) when mcpServers is not an object', () => {
|
|
41
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: 'nope' }));
|
|
42
|
+
expect(getRegisteredMcpServers(tmpDir)).toBeUndefined();
|
|
43
|
+
});
|
|
44
|
+
it('fails open (returns undefined) when mcpServers is an array', () => {
|
|
45
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: ['ruflo'] }));
|
|
46
|
+
expect(getRegisteredMcpServers(tmpDir)).toBeUndefined();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('extractDepIntel resolution-aware warnings (SMI-5676)', () => {
|
|
50
|
+
let tmpDir;
|
|
51
|
+
let originalCwd;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
originalCwd = process.cwd();
|
|
54
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'skillsmith-dep-intel-'));
|
|
55
|
+
});
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
process.chdir(originalCwd);
|
|
58
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
it('does not warn about a server confirmed registered in .mcp.json', () => {
|
|
61
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: { linear: {} } }));
|
|
62
|
+
process.chdir(tmpDir);
|
|
63
|
+
const result = extractDepIntel('Use mcp__linear__save_issue to create issues.');
|
|
64
|
+
expect(result.dep_inferred_servers).toContain('linear');
|
|
65
|
+
expect(result.dep_warnings.some((w) => w.includes('linear'))).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
it('warns about a server absent from .mcp.json (e.g. the claude-flow -> ruflo rename)', () => {
|
|
68
|
+
fs.writeFileSync(path.join(tmpDir, '.mcp.json'), JSON.stringify({ mcpServers: { ruflo: {} } }));
|
|
69
|
+
process.chdir(tmpDir);
|
|
70
|
+
const result = extractDepIntel('Use mcp__claude-flow__agent_spawn to spawn agents.');
|
|
71
|
+
expect(result.dep_inferred_servers).toContain('claude-flow');
|
|
72
|
+
expect(result.dep_warnings.some((w) => w.includes('claude-flow'))).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('still warns when .mcp.json is missing (fail open -> unknown, not silently trusted)', () => {
|
|
75
|
+
process.chdir(tmpDir); // no .mcp.json written
|
|
76
|
+
const result = extractDepIntel('Use mcp__linear__save_issue to create issues.');
|
|
77
|
+
expect(result.dep_warnings.some((w) => w.includes('linear'))).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=skill-installation.helpers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-installation.helpers.test.js","sourceRoot":"","sources":["../../../src/services/skill-installation.helpers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,9 +9,18 @@
|
|
|
9
9
|
* Design parity with the CLI scanner at
|
|
10
10
|
* `packages/cli/src/utils/skills-directory.ts`:
|
|
11
11
|
* - Uses the SAME {@link SkillParser} to resolve `skill_id` / `version`.
|
|
12
|
-
* - Realpath-
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* - Realpath-memoizes the expensive SKILL.md read/parse/hash ACROSS harnesses
|
|
13
|
+
* (a symlinked alias is parsed only once), but does NOT drop the emitted
|
|
14
|
+
* entry for it — one row is still emitted per harness, since the same skill
|
|
15
|
+
* independently installed (or symlink-aliased) under two harnesses must
|
|
16
|
+
* remain two distinct rows (the `device_skills` PK is `(harness, skill_id)`).
|
|
17
|
+
* A shared `Set<realpath>` here used to also skip the push whenever the
|
|
18
|
+
* SAME realpath recurred under a DIFFERENT harness, collapsing legitimate
|
|
19
|
+
* cross-harness membership (GH #1912 / SMI-5717). The fix keys the
|
|
20
|
+
* memoization cache by realpath alone (safe — it's for parse-cost reuse
|
|
21
|
+
* only) but keys emitted-row tracking by `(harness, realpath)` (so a
|
|
22
|
+
* within-harness alias still collapses to one row, while a cross-harness
|
|
23
|
+
* one does not).
|
|
15
24
|
*
|
|
16
25
|
* @module @skillsmith/core/sync/inventory-collector
|
|
17
26
|
*/
|
|
@@ -28,7 +37,9 @@ import type { InventorySkillEntry } from './inventory-types.js';
|
|
|
28
37
|
* a `too_many_skills` 400) — silently dropping skills here would corrupt the
|
|
29
38
|
* server-side reconcile by making present skills look absent.
|
|
30
39
|
*
|
|
31
|
-
* @returns One entry per (harness, skill)
|
|
40
|
+
* @returns One entry per (harness, skill). `readSkillFields()` is memoized by
|
|
41
|
+
* realpath across harnesses to avoid redundant parsing, but every harness
|
|
42
|
+
* that observes the skill still gets its own row (GH #1912 / SMI-5717).
|
|
32
43
|
* @see SMI-5392
|
|
33
44
|
*/
|
|
34
45
|
export declare function collectDeviceSkills(): Promise<InventorySkillEntry[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory-collector.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"inventory-collector.d.ts","sourceRoot":"","sources":["../../../src/sync/inventory-collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAQH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AA0L/D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAQ1E"}
|