Skip to content

Harden PathHelpers.SafePathCombine to match TemplateDotNetTool reference implementation#59

Merged
Malcolmnixon merged 2 commits intomainfrom
copilot/improve-path-helper-security
Mar 1, 2026
Merged

Harden PathHelpers.SafePathCombine to match TemplateDotNetTool reference implementation#59
Malcolmnixon merged 2 commits intomainfrom
copilot/improve-path-helper-security

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 1, 2026

PathHelpers.SafePathCombine lacked null guards and a defense-in-depth path escape check present in the canonical TemplateDotNetTool implementation.

Changes

  • PathHelpers.cs — now exactly matches the TemplateDotNetTool reference (namespace adjusted):

    • Add ArgumentNullException.ThrowIfNull guards for both parameters before any path logic
    • Add post-combine validation: resolve both paths via Path.GetFullPath, then use Path.GetRelativePath to confirm the result stays within basePath — guards against symlinks and other platform edge cases that could bypass the initial ../rooted checks
  • PathHelpersTests.cs — two new tests:

    • NullBasePath_ThrowsArgumentNullException — asserts correct ParamName
    • NullRelativePath_ThrowsArgumentNullException — asserts correct ParamName
internal static string SafePathCombine(string basePath, string relativePath)
{
    // Validate inputs
    ArgumentNullException.ThrowIfNull(basePath);
    ArgumentNullException.ThrowIfNull(relativePath);

    if (relativePath.Contains("..") || Path.IsPathRooted(relativePath))
        throw new ArgumentException($"Invalid path component: {relativePath}", nameof(relativePath));

    var combinedPath = Path.Combine(basePath, relativePath);

    // Defense-in-depth: verify resolved path stays within basePath
    var relativeCheck = Path.GetRelativePath(Path.GetFullPath(basePath), Path.GetFullPath(combinedPath));
    if (relativeCheck.StartsWith("..") || Path.IsPathRooted(relativeCheck))
        throw new ArgumentException($"Invalid path component: {relativePath}", nameof(relativePath));

    return combinedPath;
}

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code quality improvement

Related Issues

Pre-Submission Checklist

Before submitting this pull request, ensure you have completed the following:

Build and Test

  • Code builds successfully: dotnet build --configuration Release
  • All tests pass: dotnet test --configuration Release
  • Code produces zero warnings

Code Quality

  • Code formatting is correct: dotnet format --verify-no-changes
  • New code has appropriate XML documentation comments
  • Static analyzer warnings have been addressed

Quality Checks

Please run the following checks before submitting:

  • Spell checker passes: cspell "**/*.{md,cs}"
  • Markdown linter passes: markdownlint "**/*.md"
  • YAML linter passes: yamllint '**/*.{yml,yaml}'
  • Self-validation passes:
    dotnet run --project src/DemaConsulting.SarifMark --configuration Release --framework net10.0 --no-build -- --validate

Testing

  • Added unit tests for new functionality
  • Updated existing tests if behavior changed
  • All tests follow the AAA (Arrange, Act, Assert) pattern
  • Test coverage is maintained or improved

Documentation

  • Updated README.md (if applicable)
  • Updated ARCHITECTURE.md (if applicable)
  • Added code examples for new features (if applicable)
  • Updated requirements.yaml (if applicable)

Additional Notes

CodeQL static analysis reports 0 alerts.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
Copilot AI changed the title [WIP] Update path helpers for more secure implementation Harden PathHelpers.SafePathCombine to match TemplateDotNetTool reference implementation Mar 1, 2026
@Malcolmnixon Malcolmnixon marked this pull request as ready for review March 1, 2026 01:18
@Malcolmnixon Malcolmnixon merged commit 40e1513 into main Mar 1, 2026
11 checks passed
@Malcolmnixon Malcolmnixon deleted the copilot/improve-path-helper-security branch March 1, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants