a79d8282dc
- 15 Controller-Klassen ersetzen Minimal APIs in Program.cs - Repository Pattern mit Interfaces + Implementierungen (Project, Task, Activity, User) - AuthService verwendet jetzt IUserRepository statt direktem DbContext-Zugriff - SecurityHeadersMiddleware als eigenständige Middleware-Klasse - PathSecurityHelper als gemeinsamer Helper für Pfadvalidierung - DTOs in eigenem Namespace Nexus.Api.DTOs - EF-Entities in Nexus.Api.Data (vorher Nexus.Api.Domain) - Program.cs auf DI-Registrierung + Middleware reduziert - Alle 43 Endpoints unverändert erhalten - Build + 3/3 Tests erfolgreich
36 lines
1.3 KiB
C#
36 lines
1.3 KiB
C#
namespace Nexus.Api.Helpers;
|
|
|
|
public static class PathSecurityHelper
|
|
{
|
|
/// <summary>Validates a path against directory traversal and resolves a safe absolute path.</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>Validates config filename against path-traversal; must be alphanumeric .md.</summary>
|
|
public static bool IsValidConfigFileName(string fileName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(fileName)) return false;
|
|
return System.Text.RegularExpressions.Regex.IsMatch(fileName, @"^[a-zA-Z0-9._-]+\.md$");
|
|
}
|
|
}
|