{"record":{"id":"bbc87401adbe7b55","repo":"hcengineering/platform","slug":"key-contains-invalid-path-sequences","errorCode":null,"errorMessage":"Key contains invalid path sequences","messagePattern":"Key contains invalid path sequences","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pods/preview/src/cache.ts","lineNumber":172,"sourceCode":"    }\n\n    const entry = { ...value, filePath, size }\n    this.cache.set(key, entry)\n\n    return entry\n  }\n\n  async delete (key: string): Promise<void> {\n    this.cache.delete(key)\n  }\n\n  private getFilePath (key: string): string {\n    if (key.length === 0) {\n      throw new Error('Key cannot be empty')\n    }\n\n    if (key.includes('..') || key.includes('./') || key.includes('/.')) {\n      throw new Error('Key contains invalid path sequences')\n    }\n\n    key = key.replace(/[^a-zA-Z0-9-_/]/g, '_')\n    const path = join(this.cachePath, key)\n\n    if (!this.isPathWithinCache(path)) {\n      throw new Error('Cache path is outside of cache directory')\n    }\n\n    return path\n  }\n\n  private isPathWithinCache (filePath: string): boolean {\n    const normalizedPath = resolve(normalize(filePath))\n    const relativePath = relative(this.cachePath, normalizedPath)\n\n    // If the relative path starts with '..', it's outside the cache directory\n    return !relativePath.startsWith('..') && !isAbsolute(relativePath)","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/pods/preview/src/cache.ts#L154-L190","documentation":"Error thrown by getFilePath when the key contains path-traversal-like sequences ('..', './', or '/.'). The cache derives a real file path from the key, so keys that could escape or probe directories are rejected to prevent path traversal.","triggerScenarios":"Passing a raw URL, file path, or user-controlled string as a cache key instead of a sanitized hash — anything containing dots with slashes, e.g. '../../etc/passwd' or './x'.","commonSituations":"Using the unhashed URL as the key, concatenating user input into keys, or a migration where keys were previously raw paths; also triggered by keys containing '..' inside normal text (e.g. 'foo../bar').","solutions":["Hash the key (sha256 hex digest) before storing so it only contains safe characters","Sanitize/replace forbidden sequences before calling cache methods","Validate keys at your API boundary: reject keys containing '.' adjacent to '/'","Audit where user input flows into cache keys"],"exampleFix":"// before\nawait cache.put(url, previewFile) // url contains './'\n// after\nconst key = createHash('sha256').update(url).digest('hex')\nawait cache.put(key, previewFile)","handlingStrategy":"validation","validationCode":"function safeKey(raw: string): string {\n  return createHash('sha256').update(raw).digest('hex')\n}","typeGuard":"function isSafeCacheKey(key: string): boolean {\n  return key.length > 0 && !key.includes('..') && !key.includes('./') && !key.includes('/.')\n}","tryCatchPattern":"try {\n  await cache.put(key, value)\n} catch (e) {\n  if (e.message === 'Key contains invalid path sequences') {\n    return cache.put(createHash('sha256').update(key).digest('hex'), value)\n  }\n  throw e\n}","preventionTips":["Always hash raw URLs/user input before using as cache keys","Reject or sanitize keys containing '.' adjacent to '/'","Audit all data flow into cache keys for user control","Add a shared key-normalization helper used by all callers"],"tags":["security","path-traversal","cache"],"backgroundTag":"path-traversal","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}