{"record":{"id":"fc1a80e42226e387","repo":"nexu-io/open-design","slug":"invalid-brand-id-input-brandid","errorCode":null,"errorMessage":"invalid brand id: ${input.brandId}","messagePattern":"invalid brand id: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/brands/index.ts","lineNumber":2107,"sourceCode":"    return;\n  }\n  const source = path.join(projectDir, dirName);\n  if (!isDirectory(source)) return;\n  const target = resolveBrandFile(brandsRoot, brandId, [dirName]);\n  if (!target) return;\n  copyDirectorySync(source, target);\n}\n\nasync function syncBrandFilesToProject(input: {\n  brandsRoot: string;\n  projectsRoot: string;\n  brandId: string;\n  projectId: string;\n  brand: Brand;\n  metadata: ProjectMetadata;\n}): Promise<void> {\n  const brandRoot = resolveBrandFile(input.brandsRoot, input.brandId, []);\n  if (!brandRoot) throw new Error(`invalid brand id: ${input.brandId}`);\n  const write = async (name: string, body: string | Buffer) => {\n    await writeProjectFile(input.projectsRoot, input.projectId, name, body, { overwrite: true }, input.metadata);\n  };\n  await write('brand.json', JSON.stringify(input.brand, null, 2));\n  await write('DESIGN.md', brandToDesignMd(input.brand));\n  await writeOptionalFileToProject(input.projectsRoot, input.projectId, input.metadata, brandRoot, 'guide.md');\n  await copyDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, brandSystemDir(input.brandsRoot, input.brandId), 'system');\n  await copyOptionalDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, path.join(brandRoot, 'logos'), 'logos');\n  await copyOptionalDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, path.join(brandRoot, 'fonts'), 'fonts');\n  await copyOptionalDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, path.join(brandRoot, 'imagery'), 'imagery');\n  await copyOptionalDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, path.join(brandRoot, 'prefetch'), 'prefetch');\n  await copyOptionalDirectoryToProject(input.projectsRoot, input.projectId, input.metadata, path.join(brandRoot, 'context'), 'context');\n}\n\nasync function writeOptionalFileToProject(\n  projectsRoot: string,\n  projectId: string,\n  metadata: ProjectMetadata,","sourceCodeStart":2089,"sourceCodeEnd":2125,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/brands/index.ts#L2089-L2125","documentation":"Thrown by syncBrandFilesToProject when resolveBrandFile(brandsRoot, input.brandId, []) returns null. This is a path-safety/slug guard, NOT a not-found check: the brand id failed validation (contains '..', slashes, or characters outside the allowed set) and was refused before directory lookup. Security-relevant: it blocks path traversal.","triggerScenarios":"Passing a brandId containing path separators ('../x', 'a/b'), parent traversal ('..'), or characters the resolver rejects; constructing an id from untrusted URL path input without sanitization.","commonSituations":"User-supplied or URL-derived brand id reaching the sync path unsanitized; programmatic callers concatenating path segments into the id; testing with literal traversal strings.","solutions":["Use only safe slug brand ids produced by the brand-creation flow.","Reject any id containing '/', '\\', or '..' before calling syncBrandFilesToProject.","If accepting user input, slugify and validate against a strict character set upstream."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isSafeBrandId(id: string): boolean {\n  // Mirror resolveBrandFile's contract: no path separators, no parent traversal.\n  return typeof id === 'string' && id.length > 0 && !/[\\\\/]/.test(id) && !/(^|\\/|\\\\)\\.\\.?(\\/|\\\\|$)/.test(id);\n}\nif (!isSafeBrandId(input.brandId)) {\n  throw new Error(`Refusing to sync: brand id '${input.brandId}' is not a safe slug.`);\n}","typeGuard":"function isSafeBrandId(id: unknown): id is string {\n  return typeof id === 'string'\n    && id.length > 0\n    && !/[\\\\/]/.test(id)\n    && id !== '..'\n    && !id.includes('../');\n}","tryCatchPattern":"try {\n  await syncBrandFilesToProject(input);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('invalid brand id:')) {\n    return badRequest('Brand id must be a safe slug with no path characters.');\n  }\n  throw err;\n}","preventionTips":["Never build brand ids from raw URL path segments — slugify and validate first.","Reject any id containing '/', '\\\\', or '..' at the trust boundary.","Treat this error as a security signal: path-traversal attempts should be logged, not just returned."],"tags":["brands","validation","path-traversal","security"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}