{"record":{"id":"94f67c81ca60db37","repo":"hcengineering/platform","slug":"invalid-cache-path","errorCode":null,"errorMessage":"Invalid cache path","messagePattern":"Invalid cache path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pods/preview/src/cache.ts","lineNumber":216,"sourceCode":"\n  try {\n    const chunks: Buffer[] = []\n    for await (const chunk of data) {\n      chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n    }\n    return Buffer.concat(chunks)\n  } finally {\n    data.destroy()\n  }\n}\n\nexport function createCache (ctx: MeasureContext, options: CacheConfig): Cache {\n  if (options.enabled && options.cachePath !== undefined) {\n    try {\n      const cachePath = resolve(normalize(options.cachePath))\n\n      if (cachePath.includes('..') || !isAbsolute(cachePath)) {\n        throw new Error('Invalid cache path')\n      }\n\n      ctx.info('using disk cache', { cachePath })\n      return new DiskCache(ctx, { ...options, cachePath })\n    } catch (err: any) {\n      ctx.error('Failed to create cache', { path: options.cachePath, error: err })\n    }\n  }\n\n  ctx.info('using no cache')\n  return new NoopCache()\n}\n\nexport async function withCache (\n  ctx: MeasureContext,\n  cache: Cache,\n  key: string,\n  fn: () => Promise<PreviewFile>","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/pods/preview/src/cache.ts#L198-L234","documentation":"createCache validates the configured cachePath before constructing a DiskCache. If the resolved path is not absolute or contains '..' (path traversal), it throws 'Invalid cache path'. This guards against writing cache files to unintended directories.","triggerScenarios":"createCache(ctx, { enabled: true, cachePath: <path> }) where the normalized absolute path either is relative after resolution or contains a '..' segment.","commonSituations":"Config file or env var holding a relative path like './cache' or 'var/cache'; misconfigured defaults on Windows where the path lacks a drive root; path interpolation injecting '..' segments.","solutions":["Set cachePath to an absolute path (e.g. /var/lib/app/cache) in your CacheConfig","Remove any '..' segments from the configured path","If a relative path is desired, resolve it to an absolute path before passing it (path.resolve(process.cwd(), rel))","Or set enabled: false to skip the disk cache entirely"],"exampleFix":"// before\ncreateCache(ctx, { enabled: true, cachePath: './data/cache' })\n// after\ncreateCache(ctx, { enabled: true, cachePath: '/var/lib/myapp/cache' })","handlingStrategy":"validation","validationCode":"import { resolve, normalize, isAbsolute } from 'path'\nfunction assertValidCachePath (p?: string): void {\n  if (p === undefined) return\n  const abs = resolve(normalize(p))\n  if (abs.includes('..') || !isAbsolute(abs)) {\n    throw new Error(`cachePath must be absolute without '..': ${p}`)\n  }\n}\nassertValidCachePath(options.cachePath)","typeGuard":"function isValidCachePath (p: unknown): p is string {\n  return typeof p === 'string' && p.length > 0 && isAbsolute(resolve(normalize(p))) && !resolve(normalize(p)).includes('..')\n}","tryCatchPattern":"try {\n  const cache = createCache(ctx, options)\n} catch (err) {\n  ctx.error('cache init failed, continuing without disk cache', { path: options.cachePath, error: err })\n  // fall back to in-memory/no cache\n}","preventionTips":["Always configure absolute paths via path.resolve(__dirname, ...) or a known root","Never build cache paths from untrusted user input","Add a startup config validation step that checks cachePath before createCache","Keep '..' out of path templates; join segments instead of concatenating strings"],"tags":["cache","configuration","path-validation"],"backgroundTag":"invalid-path-configuration","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}