{"record":{"id":"5dc8adc1f6b8016a","repo":"quasarframework/quasar","slug":"refusing-to-remove-the-user-home-directory-as-buil","errorCode":null,"errorMessage":"Refusing to remove the user home directory as build output","messagePattern":"Refusing to remove the user home directory as build output","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"app-vite/lib/utils/remove-build-artifacts.js","lineNumber":76,"sourceCode":"    throw new Error('Build output directory must be a non-empty path')\n  }\n\n  if (typeof projectDir !== 'string' || projectDir.trim() === '') {\n    throw new Error('Project directory must be a non-empty path')\n  }\n\n  const project = resolve(projectDir)\n  const effectiveProject = fse.realpathSync(project)\n  const home = fse.realpathSync(resolve(homedir()))\n  const target = resolve(projectDir, targetDir)\n  const effectiveTarget = getEffectivePath(target)\n\n  if (isFilesystemRoot(target) || isFilesystemRoot(effectiveTarget)) {\n    throw new Error('Refusing to remove a filesystem root as build output')\n  }\n\n  if (target === home || effectiveTarget === home) {\n    throw new Error(\n      'Refusing to remove the user home directory as build output'\n    )\n  }\n\n  if (target === project || effectiveTarget === effectiveProject) {\n    throw new Error('Refusing to remove the project root as build output')\n  }\n\n  if (\n    allowOutsideProject !== true &&\n    isContainedPath(effectiveProject, effectiveTarget) === false\n  ) {\n    throw new Error(\n      'Build output directory must remain inside the project. Set build.allowOutsideProjectDistDir to true to explicitly allow an external directory.'\n    )\n  }\n\n  return { target, effectiveTarget }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/quasarframework/quasar/blob/4841521b5f635a971eb9e2710e5542efd194691b/app-vite/lib/utils/remove-build-artifacts.js#L58-L94","documentation":"A safety guard in getBuildArtifactsCleanTarget that refuses to delete the user's home directory as build output. Both the resolved target and its symlink-resolved effective target are compared against the realpath of os.homedir(), so even a symlink or alias pointing home is caught.","triggerScenarios":"Configuring the build output directory as '~', $HOME, /home/user, or any path whose realpath equals the home directory (including a symlink inside the project that points home).","commonSituations":"distDir: '~' without expansion semantics resolving unexpectedly; DIST_DIR=/ home env leakage; a symlink named dist -> ~ created by tooling; running with HOME=/ in containers making a relative-ish path resolve to home.","solutions":["Set distDir to a project-relative subdirectory such as 'dist'","Inspect the configured path and any symlinks with 'readlink -f' to confirm it does not resolve to $HOME","Avoid passing raw HOME-based env vars as the output directory; validate against path.resolve(os.homedir()) first"],"exampleFix":"// before\ndistDir: process.env.HOME\n// after\ndistDir: 'dist'","handlingStrategy":"validation","validationCode":"const os = require('node:os')\nconst path = require('node:path')\nconst fs = require('node:fs')\nconst home = fs.realpathSync(os.homedir())\nconst target = path.resolve(projectDir, distDir)\nif (target === home || (fs.existsSync(target) && fs.realpathSync(target) === home)) {\n  throw new Error('dist dir resolves to the home directory')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await removeBuildArtifacts(opts)\n} catch (err) {\n  if (err.message === 'Refusing to remove the user home directory as build output') {\n    // correct the distDir config before any deletion\n  } else throw err\n}","preventionTips":["Never assign $HOME or '~' as the build output directory","Validate configured paths against path.resolve(os.homedir()) early in config loading","Resolve symlinks before using user-supplied distDir values"],"tags":["safety","filesystem","path-traversal"],"backgroundTag":"unsafe-delete-path","analyzedSha":"4841521b5f635a971eb9e2710e5542efd194691b","analyzedAt":"2026-08-30T01:13:14.944Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}