{"record":{"id":"1b5585c0f7b98148","repo":"agalwood/Motrix","slug":"plugin-fs-invalid-basename","errorCode":"plugin.fs.invalid_basename","errorMessage":"not a valid basename: ${name}","messagePattern":"not a valid basename: (.+?)","errorType":"validation","errorClass":"FsSandboxError","httpStatus":null,"severity":"error","filePath":"src/core/plugin/capabilities/fs-sandbox.ts","lineNumber":145,"sourceCode":"  ) {\n    throw new FsSandboxError(\n      'plugin.fs.path_outside_sandbox',\n      'plugin.fs.path_outside_sandbox: resolved path outside sandbox root'\n    )\n  }\n  return normalizedAbs\n}\n\nexport function assertBasename(name: string): void {\n  if (\n    name === '' ||\n    name === '.' ||\n    name === '..' ||\n    name.includes('/') ||\n    name.includes('\\\\') ||\n    name.startsWith('.')\n  ) {\n    throw new FsSandboxError(\n      'plugin.fs.invalid_basename',\n      `not a valid basename: ${name}`\n    )\n  }\n}\n","sourceCodeStart":127,"sourceCodeEnd":151,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/plugin/capabilities/fs-sandbox.ts#L127-L151","documentation":"Thrown by `assertBasename(name)` when the proposed filename is empty, `.`, `..`, contains a `/` or `\\`, or starts with a `.`. The function enforces a safe single-segment name (no traversal, no hidden files). Code is `plugin.fs.invalid_basename`. Used by rename() and any path expecting a bare filename.","triggerScenarios":"Passing a path-like string (with separators), a dotfile (`.env`), the special entries `.`/`..`, or an empty string to a function that requires a plain basename. Most commonly hit via `FsTask.rename(newFilename)`.","commonSituations":"Plugin derives a filename from user input without sanitizing; allowing dotfiles by mistake; passing a full relative path instead of just a name; cross-platform code where a `\\` slips in from Windows input.","solutions":["Sanitize the input: take `path.basename()`, strip a leading dot, and reject empty results.","Validate against an explicit allow pattern (e.g. `/^[A-Za-z0-9._-]+$/` and disallow leading dot).","Refuse separators and the literal `.`/`..` tokens before calling rename().","If dotfiles are legitimately needed, file a feature request rather than working around the guard."],"exampleFix":"// before\nawait task.rename('logs/2024.txt') // contains '/', rejected\n\n// after — pass a bare basename\nawait task.rename('2024.txt')","handlingStrategy":"validation","validationCode":"function assertSafeBasename(name: string): void {\n  if (\n    name === '' || name === '.' || name === '..' ||\n    name.includes('/') || name.includes('\\\\') || name.startsWith('.')\n  ) {\n    throw new Error(`unsafe basename: ${name}`)\n}\n}","typeGuard":"function isInvalidBasename(e: unknown): boolean {\n  return e instanceof Error && (e as FsSandboxError).code === 'plugin.fs.invalid_basename'\n}","tryCatchPattern":"try {\n  await task.rename(newFilename)\n} catch (e) {\n  if (isInvalidBasename(e)) { /* sanitize and retry */ }\n  else throw e\n}","preventionTips":["Always pass path.basename() output, then strip a leading dot.","Validate against an allow-list regex like /^[A-Za-z0-9._-]+$/.","Never pass user input straight through to rename()."],"tags":["fs","sandbox","filename-validation","security"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}