mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +08:00
fix: block inconclusive skillhub installs
This commit is contained in:
parent
c744213aae
commit
3b1f190938
@ -184,9 +184,40 @@ describe('skill market source normalization', () => {
|
||||
slug: 'skill-vetter',
|
||||
trustState: 'benign',
|
||||
trustSummary: '安全,无风险',
|
||||
installEligibility: { status: 'installable' },
|
||||
})
|
||||
})
|
||||
|
||||
it('blocks SkillHub details when security reports are missing', () => {
|
||||
const detail = normalizeSkillHubDetail({
|
||||
skill: {
|
||||
slug: 'unreviewed-skill',
|
||||
displayName: 'Unreviewed Skill',
|
||||
},
|
||||
})
|
||||
|
||||
expect(detail.trustState).toBe('unknown')
|
||||
expect(detail.installEligibility.status).toBe('blocked')
|
||||
expect(detail.installEligibility.reason).toMatch(/security report is missing or inconclusive/i)
|
||||
})
|
||||
|
||||
it('blocks SkillHub details when security reports are mixed or inconclusive', () => {
|
||||
const detail = normalizeSkillHubDetail({
|
||||
securityReports: {
|
||||
community: { status: 'benign', statusText: 'safe' },
|
||||
staticAnalysis: { status: 'pending-review', statusText: 'Scanner still reviewing.' },
|
||||
},
|
||||
skill: {
|
||||
slug: 'mixed-report-skill',
|
||||
displayName: 'Mixed Report Skill',
|
||||
},
|
||||
})
|
||||
|
||||
expect(detail.trustState).toBe('unknown')
|
||||
expect(detail.installEligibility.status).toBe('blocked')
|
||||
expect(detail.installEligibility.reason).toMatch(/security report is missing or inconclusive/i)
|
||||
})
|
||||
|
||||
it('uses malicious SkillHub report summaries for blocked details', () => {
|
||||
const detail = normalizeSkillHubDetail({
|
||||
securityReports: {
|
||||
|
||||
@ -45,6 +45,13 @@ const ALLOWED_EXTERNAL_URL_HOSTS = new Set([
|
||||
'raw.githubusercontent.com',
|
||||
])
|
||||
|
||||
const SKILLHUB_DETAIL_INSTALLABLE_TRUST_STATES = new Set<SkillMarketTrustState>([
|
||||
'clean',
|
||||
'benign',
|
||||
'signed',
|
||||
'official',
|
||||
])
|
||||
|
||||
function requiresApiKey(labels?: { requires_api_key?: string }) {
|
||||
return labels?.requires_api_key === 'true'
|
||||
}
|
||||
@ -93,6 +100,19 @@ function trustFromReports(reports?: Record<string, { status?: string; statusText
|
||||
return { trustState: 'unknown', trustSummary: values.find((report) => report.statusText)?.statusText }
|
||||
}
|
||||
|
||||
function installEligibilityFromTrustState(trustState: SkillMarketTrustState): SkillMarketDetail['installEligibility'] {
|
||||
if (SKILLHUB_DETAIL_INSTALLABLE_TRUST_STATES.has(trustState)) {
|
||||
return { status: 'installable' }
|
||||
}
|
||||
if (trustState === 'blocked') {
|
||||
return { status: 'blocked', reason: 'SkillHub security report blocked this skill.' }
|
||||
}
|
||||
if (trustState === 'warning') {
|
||||
return { status: 'blocked', reason: 'SkillHub security report returned warnings.' }
|
||||
}
|
||||
return { status: 'blocked', reason: 'SkillHub security report is missing or inconclusive.' }
|
||||
}
|
||||
|
||||
export function normalizeSkillHubList(payload: SkillHubListResponse): SkillMarketListResult {
|
||||
const items = (payload.data?.skills ?? [])
|
||||
.filter((item) => item.slug && item.name)
|
||||
@ -155,8 +175,6 @@ export function normalizeSkillHubDetail(payload: SkillHubDetailResponse): SkillM
|
||||
installed: false,
|
||||
files: [],
|
||||
riskLabels: requiresApiKey(skill.labels) ? ['requires-api-key'] : [],
|
||||
installEligibility: trust.trustState === 'blocked'
|
||||
? { status: 'blocked', reason: 'SkillHub security report blocked this skill.' }
|
||||
: { status: 'installable' },
|
||||
installEligibility: installEligibilityFromTrustState(trust.trustState),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user