MCPcopy Index your code
hub / github.com/codeaashu/claude-code / validateMarketplaceManifest

Function validateMarketplaceManifest

src/utils/plugins/validatePlugin.ts:310–507  ·  view source on GitHub ↗
(
  filePath: string,
)

Source from the content-addressed store, hash-verified

308 * Validate a marketplace manifest file (marketplace.json)
309 */
310export async function validateMarketplaceManifest(
311 filePath: string,
312): Promise<ValidationResult> {
313 const errors: ValidationError[] = []
314 const warnings: ValidationWarning[] = []
315 const absolutePath = path.resolve(filePath)
316
317 // Read file content — handle ENOENT / EISDIR / permission errors directly
318 let content: string
319 try {
320 content = await readFile(absolutePath, { encoding: 'utf-8' })
321 } catch (error: unknown) {
322 const code = getErrnoCode(error)
323 let message: string
324 if (code === 'ENOENT') {
325 message = `File not found: ${absolutePath}`
326 } else if (code === 'EISDIR') {
327 message = `Path is not a file: ${absolutePath}`
328 } else {
329 message = `Failed to read file: ${errorMessage(error)}`
330 }
331 return {
332 success: false,
333 errors: [{ path: 'file', message, code }],
334 warnings: [],
335 filePath: absolutePath,
336 fileType: 'marketplace',
337 }
338 }
339
340 let parsed: unknown
341 try {
342 parsed = jsonParse(content)
343 } catch (error) {
344 return {
345 success: false,
346 errors: [
347 {
348 path: 'json',
349 message: `Invalid JSON syntax: ${errorMessage(error)}`,
350 },
351 ],
352 warnings: [],
353 filePath: absolutePath,
354 fileType: 'marketplace',
355 }
356 }
357
358 // Check for path traversal in plugin sources before schema validation
359 // This ensures we catch security issues even if schema validation fails
360 if (parsed && typeof parsed === 'object') {
361 const obj = parsed as Record<string, unknown>
362
363 if (Array.isArray(obj.plugins)) {
364 obj.plugins.forEach((plugin: unknown, i: number) => {
365 if (plugin && typeof plugin === 'object' && 'source' in plugin) {
366 const source = (plugin as { source: unknown }).source
367 // Check string sources (relative paths)

Callers 1

validateManifestFunction · 0.85

Calls 11

readFileFunction · 0.85
getErrnoCodeFunction · 0.85
jsonParseFunction · 0.85
checkPathTraversalFunction · 0.85
marketplaceSourceHintFunction · 0.85
formatZodErrorsFunction · 0.85
forEachMethod · 0.80
entriesMethod · 0.80
errorMessageFunction · 0.50
resolveMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected