{"record":{"id":"ed5b3b016f87ef4a","repo":"can1357/oh-my-pi","slug":"invalid-version-for-cache-version","errorCode":null,"errorMessage":"Invalid version for cache: \"${version}\"","messagePattern":"Invalid version for cache: \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/plugins/marketplace/cache.ts","lineNumber":39,"sourceCode":"// 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}`);\n}\n\n/**","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/plugins/marketplace/cache.ts#L21-L57","documentation":"Cache versions are validated by isValidVersionForCache: non-empty, ≤128 chars, matching /^[a-zA-Z0-9._+-]+$/, and containing no \"..\" (path-traversal guard). A version like \"main..dev\", \"v1.0.0/\", or a git ref with slashes throws this error.","triggerScenarios":"getCachedPluginPath called with versions containing slashes, spaces, colons, or \"..\"; passing a branch name like \"feature/x\" or a full git SHA prefix with illegal characters; empty version string.","commonSituations":"Using git branch/refs with slashes as the version; raw URLs or ranges (\">=1.0.0\") as version; string interpolation injecting whitespace.","solutions":["Use a sanitized version string (semver like \"1.2.3\" or a plain commit SHA).","Replace slashes in branch names with a safe separator (e.g. \"feature-x\").","Ensure the version is non-empty and ≤128 characters.","Sanitize upstream-supplied versions before calling the cache API."],"exampleFix":"// before\ngetCachedPluginPath(dir, \"acme\", \"my-plugin\", \"feature/big-refactor\");\n// after\ngetCachedPluginPath(dir, \"acme\", \"my-plugin\", \"a1b2c3d\"); // commit SHA","handlingStrategy":"validation","validationCode":"if (!/^[a-zA-Z0-9._+-]+$/.test(version) || version.includes(\"..\") || version.length === 0 || version.length > 128) {\n  throw new Error(`Unsafe cache version: ${version}`);\n}","typeGuard":"function isCacheSafeVersion(v: string): boolean {\n  return v.length > 0 && v.length <= 128 && /^[a-zA-Z0-9._+-]+$/.test(v) && !v.includes(\"..\");\n}","tryCatchPattern":"try {\n  const p = getCachedPluginPath(dir, marketplace, pluginName, version);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"Invalid version\")) {\n    console.error(`Use a semver tag or commit SHA, not \"${version}\"`);\n  } else throw err;\n}","preventionTips":["Prefer semver tags or commit SHAs over raw branch names as versions","Replace \"/\" in branch-derived identifiers before caching","Reject versions containing \"..\" early in your own pipeline","Cap version strings at 128 characters"],"tags":["plugins","marketplace","validation","path-traversal","cache","version"],"backgroundTag":"invalid-path-component","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}