isPathSafe function

bool isPathSafe(
  1. String path,
  2. String root
)

Returns true if path does not contain '..' segments that escape root. Audited: 2026-06-12 11:26 EDT

Implementation

bool isPathSafe(String path, String root) {
  final String pathNorm = path.replaceAll(RegExp(r'[/\\]+'), '/').replaceFirst(RegExp(r'^/'), '');
  final String rootNorm = root.replaceAll(RegExp(r'[/\\]+'), '/').replaceFirst(RegExp(r'^/'), '');
  final List<String> rootParts = rootNorm
      .split('/')
      .where((String s) => s.isNotEmpty && s != '.')
      .toList();
  final List<String> parts = pathNorm
      .split('/')
      .where((String s) => s.isNotEmpty && s != '.')
      .toList();
  // Track nesting depth relative to the ROOT directory: start at the root's own
  // depth and require we never climb above it. The previous check (`depth < 0`)
  // measured against the FILESYSTEM root, so a path could ascend rootParts.length
  // levels above the supplied root undetected — e.g. isPathSafe('../secret',
  // 'home/user') resolved to 'home/secret' (a sibling of the root) yet returned
  // true. Escaping the root the instant depth drops below rootDepth is correct.
  final int rootDepth = rootParts.length;
  int depth = rootDepth;
  for (final String p in parts) {
    if (p == '..') {
      depth--;
      if (depth < rootDepth) return false;
    } else {
      depth++;
    }
  }
  return true;
}