diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8aa448d --- /dev/null +++ b/build.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +REM Restore dependencies +dotnet restore +if errorlevel 1 exit /b 1 + +REM Build the project +dotnet build --configuration Release +if errorlevel 1 exit /b 1 + +REM Run tests +dotnet test --configuration Release +if errorlevel 1 exit /b 1 + +echo Build completed successfully! diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5383df6 --- /dev/null +++ b/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +# Restore dependencies +dotnet restore + +# Build the project +dotnet build --configuration Release + +# Run tests +dotnet test --configuration Release diff --git a/lint.bat b/lint.bat new file mode 100644 index 0000000..d85f8c7 --- /dev/null +++ b/lint.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +REM Run markdown linter +call npx markdownlint-cli2 "**/*.md" +if errorlevel 1 exit /b 1 + +REM Run spell checker +call npx cspell "**/*.{md,cs}" +if errorlevel 1 exit /b 1 + +REM Run YAML linter +call yamllint . +if errorlevel 1 exit /b 1 + +echo Linting completed successfully! diff --git a/lint.sh b/lint.sh new file mode 100755 index 0000000..a562889 --- /dev/null +++ b/lint.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +# Run markdown linter +npx markdownlint-cli2 "**/*.md" + +# Run spell checker +npx cspell "**/*.{md,cs}" + +# Run YAML linter +yamllint . diff --git a/src/DemaConsulting.BuildMark/PathHelpers.cs b/src/DemaConsulting.BuildMark/PathHelpers.cs index d2f8be7..11252e7 100644 --- a/src/DemaConsulting.BuildMark/PathHelpers.cs +++ b/src/DemaConsulting.BuildMark/PathHelpers.cs @@ -44,6 +44,21 @@ internal static string SafePathCombine(string basePath, string relativePath) // 1. relativePath doesn't contain ".." (path traversal) // 2. relativePath is not an absolute path (IsPathRooted check) // This ensures the combined path will always be under basePath - return Path.Combine(basePath, relativePath); + var combinedPath = Path.Combine(basePath, relativePath); + + // Additional security validation: ensure the combined path is still under the base path. + // This defense-in-depth approach protects against edge cases that might bypass the + // initial validation, ensuring the final path stays within the intended directory. + var fullBasePath = Path.GetFullPath(basePath); + var fullCombinedPath = Path.GetFullPath(combinedPath); + + // Use GetRelativePath to verify the relationship between paths + var relativeCheck = Path.GetRelativePath(fullBasePath, fullCombinedPath); + if (relativeCheck.StartsWith("..") || Path.IsPathRooted(relativeCheck)) + { + throw new ArgumentException($"Invalid path component: {relativePath}", nameof(relativePath)); + } + + return combinedPath; } }