- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.5k
 
[PM-27575] Add support for loading Mailer templates from disk #6520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| 
           Claude finished @Hinton's task —— View job Code Review Complete
 Summary of Changes Since Last ReviewThis PR adds the capability to load mail templates from disk for self-hosted instances, allowing template customization without recompilation. The latest commits addressed path traversal vulnerabilities with case-insensitive security checks and comprehensive testing. Recent changes: 
 Critical Issues1. Potential symlink bypass in path traversal protection (src/Core/Platform/Mailer/HandlebarMailRenderer.cs:97-106)Severity: High (Security) The current implementation resolves paths with  // Current code
var diskPath = Path.GetFullPath(Path.Combine(_globalSettings.MailTemplateDirectory, template));
var baseDirectory = Path.GetFullPath(_globalSettings.MailTemplateDirectory);
if (!diskPath.StartsWith(baseDirectory + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) &&
    !diskPath.Equals(baseDirectory, StringComparison.OrdinalIgnoreCase))
{
    _logger.LogWarning("Template path traversal attempt detected: {Template}", template);
    return null;
}Attack scenario: 
 Recommendation: Use  var diskPath = Path.GetFullPath(Path.Combine(_globalSettings.MailTemplateDirectory, template));
var baseDirectory = Path.GetFullPath(_globalSettings.MailTemplateDirectory);
// Ensure the resolved path is within the configured directory
if (!diskPath.StartsWith(baseDirectory + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) &&
    !diskPath.Equals(baseDirectory, StringComparison.OrdinalIgnoreCase))
{
    _logger.LogWarning("Template path traversal attempt detected: {Template}", template);
    return null;
}
// Check for symlinks
var fileInfo = new FileInfo(diskPath);
if (fileInfo.Exists && fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
    _logger.LogWarning("Template is a symlink, which is not allowed: {Template}", template);
    return null;
}2. Missing null check for 
 | 
    
| return handlebars.Compile(source); | ||
| } | ||
| 
               | 
          ||
| private static async Task<string> ReadSourceAsync(Assembly assembly, string template) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We had to remove static from most functions because reading from disk relies on non static data.
| 
           
 Great job! No new security vulnerabilities introduced in this pull request | 
    
          Codecov Report❌ Patch coverage is  
 Additional details and impacted files@@            Coverage Diff             @@
##             main    #6520      +/-   ##
==========================================
+ Coverage   51.86%   51.88%   +0.01%     
==========================================
  Files        1902     1902              
  Lines       84058    84090      +32     
  Branches     7501     7504       +3     
==========================================
+ Hits        43598    43629      +31     
- Misses      38766    38768       +2     
+ Partials     1694     1693       -1     ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
  | 
    

🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-27575
📔 Objective
Adds support for overloading mail templates from disk.
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:) or similar for great changes:memo:) or ℹ️ (:information_source:) for notes or general info:question:) for questions:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:) for suggestions / improvements:x:) or:warning:) for more significant problems or concerns needing attention:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt:pick:) for minor or nitpick changes