fix: resolve static analysis issues#24
Conversation
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| BestPractice | 2 medium |
| ErrorProne | 1 high |
| Security | 3 critical |
🟢 Metrics 70 complexity · 0 duplication
Metric Results Complexity 70 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
This PR is currently not up to standards due to several critical issues that must be addressed before merging. Most significantly, the malicious code scanner contains a malformed regular expression that will cause it to crash at runtime, and its failure to return a non-zero exit code on exceptions creates a security loophole in the CI pipeline.
While the PR successfully resolves 56 existing static analysis findings, it introduces 6 new issues. There are also significant risks associated with the refactoring of core services: the replacement of optional parameters with overloads constitutes a breaking API change, and high-complexity files like ModCollectionService.cs have been refactored without any accompanying unit tests or local verification.
Finally, repository consistency is compromised by a broken documentation link to a non-existent EXTERNAL_DEPENDENCIES.md file, which should be resolved to ensure maintainability.
About this PR
- No new tests were provided for the significant refactoring of core service logic. This increases the risk of regressions in critical paths like mod synchronization and package handling.
- The changes to process launching and scanning logic have not been verified in a local environment. Given the security implications, local validation is highly recommended.
- Replacing optional parameters with method overloads in core services (Dialog, Collection, Download, Telemetry) is a breaking change for the public API. Ensure all internal and known external consumers are updated.
Test suggestions
- Verify SafeProcess.OpenUrlAsync only permits HTTP/HTTPS schemes.
- Verify malicious_scan.py argument validation rejects null bytes, newlines, and carriage returns.
- Verify DialogService overloads provide expected default button text ('OK', 'Cancel').
- Verify SafeProcess.LaunchApp correctly uses ArgumentList to pass parameters without shell interpretation.
- Verify ModCollectionService.SyncCollectionAsync correctly identifies and downloads dependencies during the sync loop.
- Add unit tests for ModCollectionService.ProcessCollectionQueueAsync and dependency resolution (uncovered complex file).
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify SafeProcess.OpenUrlAsync only permits HTTP/HTTPS schemes.
2. Verify malicious_scan.py argument validation rejects null bytes, newlines, and carriage returns.
3. Verify DialogService overloads provide expected default button text ('OK', 'Cancel').
4. Verify SafeProcess.LaunchApp correctly uses ArgumentList to pass parameters without shell interpretation.
5. Verify ModCollectionService.SyncCollectionAsync correctly identifies and downloads dependencies during the sync loop.
6. Add unit tests for ModCollectionService.ProcessCollectionQueueAsync and dependency resolution (uncovered complex file).
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| @@ -0,0 +1,33 @@ | |||
| # TOOLS.md — Build, CI, and Operations | |||
There was a problem hiding this comment.
🔴 HIGH RISK
Referenced file EXTERNAL_DEPENDENCIES.md was not found. Please add the file or update the documentation references in TOOLS.md and AGENTS.md.
| Path(args.output).write_text(json.dumps(make_error_sarif(message), indent=2), encoding="utf-8") | ||
| Path(args.summary).write_text(f"Scanner failed: {ex}\n", encoding="utf-8") | ||
| print(f"Scanner failed: {ex}") | ||
| return 0 |
There was a problem hiding this comment.
🔴 HIGH RISK
The script returns an exit code of 0 even when an exception occurs. In a security context, failures should return a non-zero code to ensure CI pipelines stop if the scan cannot be completed.
| secret=re.compile(r"(secret|token|password|apikey|api[_-]?key|private[_-]?key)", re.IGNORECASE), | ||
| secret_assignment=re.compile(r"(secret|token|password|apikey|api[_-]?key|private[_-]?key)\s*[:=]\s*['\"][^'\"]{8,}", re.IGNORECASE), | ||
| network=re.compile(r"(curl\s|wget\s|http[s]?://|requests\.|fetch\(|http\.get|HttpClient|Invoke-RestMethod)", re.IGNORECASE), | ||
| system=re.compile(r"(Process\.Start|cmd\.exe|powershell\.exe|/bin/sh|subprocess\.|Runtime\.getRuntime\(\)\.exec)", re.IGNORECASE), |
There was a problem hiding this comment.
🔴 HIGH RISK
The regular expression is malformed due to an unmatched opening parenthesis at the start of the pattern: ([REDACTED:HIGH_ENTROPY](\)\.exec). This will cause a re.error and crash the scanner during pattern compilation.
| info.ArgumentList.Add(argument); | ||
| } | ||
|
|
||
| Process.Start(info); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
The code correctly uses ArgumentList to prevent shell injection, but static analysis requires an explicit suppression. Add [SuppressMessage("Security", "S2076")] to the StartProcess helper.
| return SyncCollectionAsync(collectionId, downloader, sync, gameRoot, log, CancellationToken.None); | ||
| } | ||
|
|
||
| public async Task<bool> SyncCollectionAsync( |
There was a problem hiding this comment.
🟡 MEDIUM RISK
This service has been significantly refactored with complex async queue logic but currently has no test coverage. Add unit tests for ProcessCollectionQueueAsync to prevent synchronization regressions.
| return CreateBundleAsync(CancellationToken.None); | ||
| } | ||
|
|
||
| public Task<string> CreateBundleAsync(CancellationToken cancellationToken) |
There was a problem hiding this comment.
🟡 MEDIUM RISK
This method performs heavy synchronous file I/O but returns a completed Task. This will block the caller. Wrap the implementation logic in Task.Run to satisfy the asynchronous contract.
| var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); | ||
|
|
||
| return JsonSerializer.Deserialize(json, AppJsonContext.Default.ListPluginPackageInfo); | ||
| }).GetAwaiter().GetResult(); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: The use of Task.Run(...).GetAwaiter().GetResult() blocks the calling thread, risking UI freezes and deadlocks. Refactor ListPlugins to be fully asynchronous.
|
|
||
| --- | ||
| - Keep PowerShell build scripts and GitHub Actions workflows aligned unless a PR intentionally stages a migration and explains the temporary divergence. | ||
| - Preserve publish-size settings unless a measured, reviewed change requires otherwise. |
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: Replace vague qualifiers like 'measured, reviewed change' with specific thresholds (e.g., < 50MB) to ensure consistent enforcement of size targets.
Summary
ArgumentListusage.gitexecutable and split large scan functions into smaller helpers.AGENTS.mdinto shorter companion files and keep rule wording escape-hatch aware..globalconfigfor known large UI/parser files where structural splitting should be handled separately from the security cleanup.Verification
github.com, so normal clone/build/test commands were unavailable.fix/static-analysis-issues.Notes