Node.js

Lesson 10

Input validation and path safety

Validate user input before using it in filesystem paths or other sensitive operations.

Good Code

src/files.ts
import path from "node:path";

const uploadRoot = path.resolve("uploads");

export function resolveUploadPath(fileName: string) {
  if (!/^[a-z0-9._-]+$/i.test(fileName)) {
    throw new Error("Invalid file name.");
  }

  const targetPath = path.resolve(uploadRoot, fileName);

  if (!targetPath.startsWith(uploadRoot + path.sep)) {
    throw new Error("Path escapes upload directory.");
  }

  return targetPath;
}

Bad Code

src/files.ts
import path from "node:path";

export function resolveUploadPath(fileName: string) {
  return path.join("uploads", fileName);
}

Review Notes

What to review

Good Code

The good version validates the filename, resolves it against a known root, and rejects paths that escape the upload directory.

Bad Code

The bad version joins user input directly into a filesystem path, allowing traversal input to point outside the intended folder.

Takeaways

  • Resolve user-controlled paths against an allowed root and reject traversal attempts.