{"record":{"id":"653fa0e0e411027f","repo":"can1357/oh-my-pi","slug":"invalid-plugin-name-for-cache-pluginname","errorCode":null,"errorMessage":"Invalid plugin name for cache: \"${pluginName}\"","messagePattern":"Invalid plugin name for cache: \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/marketplace/cache.ts","lineNumber":36,"sourceCode":"\nimport { isValidNameSegment } from \"./types\";\n\n// Reject anything that could be used for path traversal or shell injection in\n// version strings. Only printable, unambiguous characters are allowed.\nconst VERSION_RE = /^[a-zA-Z0-9._+-]+$/;\n\n/** Return true when `version` is safe for use as a cache path component. */\nexport function isValidVersionForCache(version: string): boolean {\n\t// prevent path-traversal sequences like \"..\" or \"1..2\"\n\treturn version.length > 0 && version.length <= 128 && VERSION_RE.test(version) && !version.includes(\"..\");\n}\n\nfunction validateCacheComponents(marketplace: string, pluginName: string, version: string): void {\n\tif (!isValidNameSegment(marketplace)) {\n\t\tthrow new Error(`Invalid marketplace name for cache: \"${marketplace}\"`);\n\t}\n\tif (!isValidNameSegment(pluginName)) {\n\t\tthrow new Error(`Invalid plugin name for cache: \"${pluginName}\"`);\n\t}\n\tif (!isValidVersionForCache(version)) {\n\t\tthrow new Error(`Invalid version for cache: \"${version}\"`);\n\t}\n}\n\n/**\n * Return the absolute path for a cached plugin directory.\n * Throws if any component fails validation.\n */\nexport function getCachedPluginPath(\n\tcacheDir: string,\n\tmarketplace: string,\n\tpluginName: string,\n\tversion: string,\n): string {\n\tvalidateCacheComponents(marketplace, pluginName, version);\n\treturn path.join(cacheDir, `${marketplace}___${pluginName}___${version}`);","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/marketplace/cache.ts#L18-L54","documentation":"Same cache-path validation: the plugin name must satisfy isValidNameSegment (lowercase alnum + hyphens, ≤64) because it becomes a directory-name component. Anything else (dots, underscores, slashes, uppercase, empty, too long) is rejected to block path traversal.","triggerScenarios":"getCachedPluginPath called with a plugin name like \"my_plugin\", \"My.Plugin\", \"scope/pkg\", \"\", or a >64-char name.","commonSituations":"Scoped npm names (@scope/pkg) passed unmodified; names taken verbatim from package.json where underscores are allowed; version-derived or URL-derived strings used as names.","solutions":["Convert the plugin name to a cache-safe segment: lowercase, replace illegal chars with hyphens.","Resolve scoped names before calling the cache (use the package's unscoped/base name as the catalog defines it).","Verify against the marketplace catalog's declared plugin id rather than package.json name.","Ensure length ≤ 64 and non-empty."],"exampleFix":"// before\ngetCachedPluginPath(dir, \"acme\", \"@acme/my_plugin\", \"1.0.0\");\n// after\ngetCachedPluginPath(dir, \"acme\", \"acme-my-plugin\", \"1.0.0\");","handlingStrategy":"validation","validationCode":"import { isValidNameSegment } from \".../marketplace/types\";\nif (!isValidNameSegment(pluginName)) {\n  pluginName = pluginName.toLowerCase().replace(/[^a-z0-9-]/g, \"-\").slice(0, 64);\n}","typeGuard":"function isCacheSafeName(s: string): boolean {\n  return s.length > 0 && s.length <= 64 && /^[a-z0-9-]+$/.test(s);\n}","tryCatchPattern":"try {\n  const p = getCachedPluginPath(dir, marketplace, pluginName, version);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"Invalid plugin name\")) {\n    console.error(`Plugin name \"${pluginName}\" must be lowercase alnum/hyphens (≤64)`);\n  } else throw err;\n}","preventionTips":["Use the catalog's declared plugin id, not the npm package name, for cache keys","Sanitize scoped/underscored npm names before caching","Keep plugin names within the marketplace validator's charset when authoring","Never interpolate slashes or dots into cache name components"],"tags":["plugins","marketplace","validation","path-traversal","cache"],"backgroundTag":"invalid-path-component","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}