🛡️ Sentinel: [HIGH] Fix path traversal in CustomEmployeeManager#185
🛡️ Sentinel: [HIGH] Fix path traversal in CustomEmployeeManager#185mleem97 wants to merge 1 commit into
Conversation
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull Request Overview
The PR addresses a high-severity path traversal vulnerability in SetPortrait, but several critical issues must be resolved before merging. A logic error in the Fire method dispatches a 'Hired' event instead of 'Fired', which will cause significant state management issues in the application. Additionally, the sanitization logic is missing from the Register entry point, leaving the system vulnerable to save file corruption and UI breakage.
While Codacy reports the PR is 'up to standards', the manual review has identified two distinct memory leaks: one involving unmanaged Unity assets (Textures/Sprites) and another involving an ever-growing static list of delegates. Finally, although the PR description claims the fix was verified via unit tests, no such tests are present in the provided file list. These tests are required to ensure the security fix works as intended.
About this PR
- Acceptance criteria gap: While the traversal risk is mitigated in
SetPortrait, theRegistermethod still accepts un-sanitized identifiers. This can lead to save file corruption (via newlines) or UI logic errors if not addressed at the source. - The PR description states that the fix was 'Tested via unit tests', but no test files are included in this PR. Please include the test suite used to verify the path traversal fix.
Test suggestions
- Call
SetPortraitwith anemployeeIdcontaining directory traversal sequences (e.g., '../../etc/passwd') and verify it is blocked. - Call
SetPortraitwith anemployeeIdcontaining platform-specific invalid filename characters and verify it is blocked. - Call
SetPortraitwith a validemployeeIdand verify the portrait image is successfully loaded from theModAssetsdirectory. - Verify that
FireCustomEmployeeFiredis dispatched correctly when callingFire(Logic check). - Verify that repeatedly calling
SetPortraitdoes not result in an unbound increase in memory usage (Leak check).
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Call `SetPortrait` with an `employeeId` containing directory traversal sequences (e.g., '../../etc/passwd') and verify it is blocked.
2. Call `SetPortrait` with an `employeeId` containing platform-specific invalid filename characters and verify it is blocked.
3. Call `SetPortrait` with a valid `employeeId` and verify the portrait image is successfully loaded from the `ModAssets` directory.
4. Verify that `FireCustomEmployeeFired` is dispatched correctly when calling `Fire` (Logic check).
5. Verify that repeatedly calling `SetPortrait` does not result in an unbound increase in memory usage (Leak check).
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| public static IReadOnlyList<CustomEmployeeEntry> Employees => _employees; | ||
| public static bool HasPendingAction => _pendingEmployeeId != null; | ||
|
|
||
| public static int Register(string id, string name, string description, float salary, float reputation, bool requiresConfirmation = false) |
There was a problem hiding this comment.
🔴 HIGH RISK
The id parameter should be validated at the entry point to prevent save file corruption (via newlines), UI breakage (via directory separators in Transform.Find), and path traversal.
Update the Register method to validate that the id string does not contain any characters from Path.GetInvalidFileNameChars(), directory separators, or newline characters. Return 0 if validation fails.
| CrashLog.Log($"CustomEmployee.Fire: step 3 - dispatching CustomEmployeeFired event for '{id}'"); | ||
| try | ||
| { | ||
| EventDispatcher.FireCustomEmployeeHired(id); |
There was a problem hiding this comment.
🔴 HIGH RISK
Critical logic error: The Fire method dispatches the FireCustomEmployeeHired event instead of a firing-specific event. This is likely a copy-paste error from the Hire method.
| EventDispatcher.FireCustomEmployeeHired(id); | |
| EventDispatcher.FireCustomEmployeeFired(id); |
| try | ||
| { | ||
| byte[] imageData = File.ReadAllBytes(imagePath); | ||
| var tex = new Texture2D(2, 2, TextureFormat.RGBA32, false); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: Loading textures and creating sprites in this way causes a native memory leak. Consider caching these assets in a dictionary keyed by employeeId to reuse them across menu refreshes.
Implement a static Dictionary<string, Sprite> to cache loaded portraits. In SetPortrait, check the cache before loading from disk, and ensure any existing textures/sprites are properly managed to avoid leaks.
| { | ||
| private static readonly List<CustomEmployeeEntry> _employees = new(); | ||
| private static readonly Dictionary<string, int> _employeeIndex = new(); | ||
| private static readonly List<UnityAction> _liveCallbacks = new(); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Nitpick: The _liveCallbacks list is used to store static references to UnityAction delegates but is never cleared. New actions are added every time SetupButtons is called, leading to an ever-growing memory footprint. Refactor this to clear references when the UI is closed or when cards are destroyed.
🚨 Severity: HIGH
💡 Vulnerability: The
SetPortraitmethod inCustomEmployeeManageruses theemployeeIdparameter directly to construct file paths for reading image files. If anemployeeIdcontains traversal sequences like../../, this can lead to reading arbitrary.jpgor.pngfiles from the filesystem.🎯 Impact: An attacker could potentially extract sensitive files from the server or user's filesystem by crafting malicious mod data with directory traversal in the
employeeId.🔧 Fix: Added a validation check to
SetPortraitusingIndexOfAny(Path.GetInvalidFileNameChars())andContains("..")to ensureemployeeIdcannot contain path separators or traversal characters.✅ Verification: Tested via unit tests and verified via source code review.
PR created automatically by Jules for task 14766504909649096741 started by @mleem97