{"record":{"id":"735da3cdaa904012","repo":"stablyai/orca","slug":"invalid-renderer-output-path-string-outputpath","errorCode":null,"errorMessage":"Invalid renderer output path: ${String(outputPath)}","messagePattern":"Invalid renderer output path: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/project-renderer-web-client.mjs","lineNumber":61,"sourceCode":"        if (entryKeys.has(dependency) && dependency !== sourceEntry) {\n          throw new Error(`Renderer entry ${sourceEntry} executes entry ${dependency}`)\n        }\n        pending.push(dependency)\n      }\n    }\n  }\n}\n\nfunction addOutputPath(outputPath) {\n  if (\n    typeof outputPath !== 'string' ||\n    outputPath.length === 0 ||\n    outputPath.startsWith('/') ||\n    /^[A-Za-z]:/.test(outputPath) ||\n    outputPath.includes('\\\\') ||\n    outputPath.split('/').includes('..')\n  ) {\n    throw new Error(`Invalid renderer output path: ${String(outputPath)}`)\n  }\n  selectedFiles.add(outputPath)\n}\n\nfunction visitManifestEntry(key) {\n  if (visitedEntries.has(key)) {\n    return\n  }\n  visitedEntries.add(key)\n\n  const entry = manifest[key]\n  if (!entry || typeof entry !== 'object') {\n    throw new Error(`Renderer manifest is missing entry: ${key}`)\n  }\n\n  addOutputPath(entry.file)\n  for (const outputPath of [...(entry.css ?? []), ...(entry.assets ?? [])]) {\n    addOutputPath(outputPath)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/project-renderer-web-client.mjs#L43-L79","documentation":"addOutputPath validates every file path the script stages into the web-client projection. It rejects: non-strings, empty strings, absolute paths (leading '/'), Windows drive letters, backslashes, and any '..' path segment. This is a path-traversal guard — manifest paths must be relative, forward-slashed, and stay under the renderer output root.","triggerScenarios":"A manifest entry's file, css, or assets field is absolute, contains '\\', matches /^[A-Za-z]:/, or contains a '..' segment. Typical with a manifest produced on Windows and consumed on Linux, or a Vite misconfiguration emitting absolute publicDir paths.","commonSituations":"Cross-OS build/projection (build on Windows, project on Linux); a rollup asset plugin emitting absolute paths; a publicDir set to an absolute external path; manual manifest tampering.","solutions":["Rebuild the renderer on the same OS that runs the projection, or normalize paths in the build","Check Vite config for base/publicDir/assetFileNames that could yield absolute or backslash paths","If a legitimate asset legitimately lives outside the renderer root, copy it in first rather than referencing an absolute path","Grep the manifest for the offending path shape: paths starting with '/' or containing '\\'"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isSafeOutputPath(p) {\n  return typeof p === 'string' && p.length > 0 && !p.startsWith('/') && !/^[A-Za-z]:/.test(p) && !p.includes('\\\\') && !p.split('/').includes('..')\n}","typeGuard":"function isSafeOutputPath(p) {\n  return typeof p === 'string' && p.length > 0 && !p.startsWith('/') && !/^[A-Za-z]:/.test(p) && !p.includes('\\\\') && !p.split('/').includes('..')\n}","tryCatchPattern":null,"preventionTips":["Build and project on the same OS to avoid backslash/drive-letter paths","Audit Vite base/publicDir/assetFileNames for absolute-path emission","Grep the manifest for paths starting with '/' or containing '\\\\' before projecting"],"tags":["security","path-traversal","build","validation","cross-platform"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}