namespace Nexus.Api.Helpers;
public static class PathSecurityHelper
{
/// Validates a path against directory traversal and resolves a safe absolute path.
public static bool TryResolveSafePath(string basePath, string userInput, out string? safePath)
{
safePath = null;
// URL-decode to catch encoded attacks like %2F, %2e%2e, %00
var decoded = Uri.UnescapeDataString(userInput);
// Reject null bytes
if (decoded.Contains('\0')) return false;
// Combine with base and resolve to canonical form
var combined = Path.Combine(basePath, decoded);
var full = Path.GetFullPath(combined);
var canonicalBase = Path.GetFullPath(basePath);
// Must stay within the allowed base directory
if (!full.StartsWith(canonicalBase + Path.DirectorySeparatorChar) && full != canonicalBase)
return false;
safePath = full;
return true;
}
/// Validates config filename against path-traversal; must be alphanumeric .md.
public static bool IsValidConfigFileName(string fileName)
{
if (string.IsNullOrWhiteSpace(fileName)) return false;
return System.Text.RegularExpressions.Regex.IsMatch(fileName, @"^[a-zA-Z0-9._-]+\.md$");
}
}