Test that the HTML post-processor refuses to merge through a symlink - #10731
Conversation
HtmlArtifactPostProcessor is the only one of the four artifact post-processors whose reparse-point refusal has no test, so removing the guard at the call site makes nothing in the repository fail. Add the symlink case and the dangling symlink case to HtmlArtifactPostProcessorTests, matching the tests the Trx, JUnit and Ctrf files already have. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Note
🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.
Review Summary
Two new unit tests covering the reparse-point guard in HtmlArtifactPostProcessor.ProcessAsync — one for a live symlink and one for a dangling symlink. Both verify the processor returns null and does not write through the link.
| # | Dimension | Verdict |
|---|---|---|
| 1 | Algorithmic Correctness | ✅ Clean |
| 2 | Behavioral Compatibility | N/A — test-only |
| 3 | Public API Surface | N/A — no API changes |
| 4 | Thread Safety / Concurrency | N/A |
| 5 | Resource Management | ✅ try/finally cleanup matches existing pattern |
| 6 | Error Handling | ✅ Assert.Inconclusive for privilege-gated symlink creation |
| 7 | Performance | N/A — test code |
| 8 | Cross-TFM Correctness | ✅ Correctly gated behind #if NETCOREAPP (Directory.CreateSymbolicLink is .NET 6+) |
| 9 | Localization | N/A |
| 10 | Security | ✅ Tests validate the security guard |
| 11 | Naming & Conventions | ✅ |
| 12 | Test Quality | ✅ Good assertions: IsNull on output, IsEmpty/IsFalse on side-effect directories |
| 13 | Documentation | N/A |
| 14 | Build & Packaging | N/A |
| 15 | Diagnostics / Logging | N/A |
| 16 | IPC / Wire Compat | N/A |
| 17 | Configuration | N/A |
| 18 | Analyzers | N/A |
| 19 | Cancellation | N/A |
| 20 | Serialization | N/A |
| 21 | Code Duplication | |
| 22 | Scope Discipline | ✅ Focused on one concern |
Overall: Clean. No blocking issues found. The tests are well-structured, correctly guard against privilege limitations with Assert.Inconclusive, and follow existing patterns in the file.
🧪 Expert test review — PR #10731
Both tests target the This advisory comment was generated automatically. Grades are heuristic
|
There was a problem hiding this comment.
Pull request overview
Adds HTML report post-processor coverage ensuring merges cannot write through symlinks outside the output directory.
Changes:
- Tests valid and dangling
mergeddirectory symlinks. - Verifies processing returns no artifact and performs no redirected writes.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
🧵 Parallel-safety audit — PR #10731Parallelization
This PR only touches Findings: A (global-state) Top actions (by expected value): none — the change is parallel-safe as written. Both new tests call the existing No process-global state (env vars, CWD, culture, console, One minor readiness note, Info only, not a finding: Advisory only — heuristic, non-blocking. Re-run with
|
Amaury Levé (Evangelink)
left a comment
There was a problem hiding this comment.
Reviewed against RFC 018 and the existing artifact post-processing design. The added tests close the HTML call-site coverage gap and correctly verify fail-closed behavior for both live and dangling directory links without introducing production or API changes.
HtmlArtifactPostProcessor calls
ArtifactPostProcessingHelper.IsReparsePointbefore it merges, so a symlink or junction planted at the fixedmergedname cannot redirect the merged report outside the output directory the orchestrator gave it. Trx, JUnit and Ctrf all have a test at the call site proving they act on that check, the HTML one did not, so deleting the guard fromHtmlArtifactPostProcessor.csmade nothing in the repository fail.Adds the symlink case and the dangling symlink case to
HtmlArtifactPostProcessorTests, copying the shape of the existing ones.Verified by removing the guard and rerunning: the symlink test fails on
Assert.IsNull(output)because the merge writes through the link, and the dangling one fails by throwing. Both pass again with the guard restored. FullMicrosoft.Testing.Extensions.UnitTestsrun on net9.0 is 1202 tests, 0 failed, and the project still builds for net462, net472, net8.0 and net9.0.The dangling variant is not added to the Trx and Ctrf files. Those two call
Directory.CreateDirectory(mergedDirectory)without the try/catch that the HTML and JUnit processors have, and on Linux that call throwsIOExceptionon a dangling directory symlink instead of returning, so the test would pass on Windows and fail on Linux CI. It looks like those two do not hold the never-fail-the-run invariant that the comment inTrxArtifactPostProcessor.csdescribes, but that is a behavior change rather than a test, so I left it out of this PR.Related: #10710
🤖