Summary
MSBuildTask0005 ("transitively calls unsafe API") is reported on the task's Execute method rather than at the call site of the unsafe API. That makes it impossible to suppress narrowly: a #pragma warning disable MSBuildTask0005 around the actual offending call has no effect, so the only way to silence a single reviewed call is to disable the rule across the task's entire Execute call graph — which also blinds every other transitive violation in that task.
Repro
In dotnet/dotnet, Microsoft.DotNet.UnifiedBuild.Tasks has a shared ProcessService helper that runs a child process with a timeout:
catch (OperationCanceledException)
{
#pragma warning disable MSBuildTask0005 // <-- has no effect
try { process.Kill(entireProcessTree: true); } catch { }
#pragma warning restore MSBuildTask0005
throw new TimeoutException($"Process timed out after {Timeout.TotalMilliseconds} ms");
}
The diagnostic is still emitted, at a completely different file/line:
CreateSourceArtifact.cs(70,26): warning MSBuildTask0005: 'CreateSourceArtifact.Execute' transitively
calls unsafe API 'Process.Kill(bool)' via: CreateSourceArtifact.Execute → CreateSourceArtifact.ExecuteAsync
→ ProcessService.RunProcessAsync → Process.Kill(bool)
To get a clean build we had to suppress on Execute itself:
#pragma warning disable MSBuildTask0005
public override bool Execute() => ExecuteAsync().GetAwaiter().GetResult();
#pragma warning restore MSBuildTask0005
which now hides all transitive violations for that task, including future regressions — the opposite of what the rule is for.
Why this particular call is safe
Process.Kill(entireProcessTree: true) here targets a process the task itself started. entireProcessTree walks descendants, so it cannot reach the MSBuild host, which is the parent. Removing the kill is strictly worse: a timed-out child would be leaked, holding file handles and potentially stalling the build.
So this is a case where the call is legitimately safe and needs a targeted, reviewed suppression.
Requests
- Honor
#pragma warning disable at the unsafe call site for MSBuildTask0005, in addition to (or instead of) the reporting location. This is the main ask.
- Alternatively/additionally, support an opt-out attribute on the helper method, e.g.
[MSBuildTaskSafeApiUsage("Process.Kill", Justification = "...")], so the review is recorded next to the code being reviewed.
- Consider also reporting a second, lower-severity diagnostic at the unsafe call site, so the location is discoverable without reading the call chain in the message.
Impact
Any task that funnels process or file work through a shared helper hits this. The workaround (suppressing on Execute) actively removes analyzer coverage, which undermines using MSBuildTask0005 as a regression guard.
Found while migrating the dotnet/dotnet VMR's Microsoft.DotNet.UnifiedBuild.Tasks to the multithreaded task model.
Summary
MSBuildTask0005("transitively calls unsafe API") is reported on the task'sExecutemethod rather than at the call site of the unsafe API. That makes it impossible to suppress narrowly: a#pragma warning disable MSBuildTask0005around the actual offending call has no effect, so the only way to silence a single reviewed call is to disable the rule across the task's entireExecutecall graph — which also blinds every other transitive violation in that task.Repro
In
dotnet/dotnet,Microsoft.DotNet.UnifiedBuild.Taskshas a sharedProcessServicehelper that runs a child process with a timeout:The diagnostic is still emitted, at a completely different file/line:
To get a clean build we had to suppress on
Executeitself:which now hides all transitive violations for that task, including future regressions — the opposite of what the rule is for.
Why this particular call is safe
Process.Kill(entireProcessTree: true)here targets a process the task itself started.entireProcessTreewalks descendants, so it cannot reach the MSBuild host, which is the parent. Removing the kill is strictly worse: a timed-out child would be leaked, holding file handles and potentially stalling the build.So this is a case where the call is legitimately safe and needs a targeted, reviewed suppression.
Requests
#pragma warning disableat the unsafe call site forMSBuildTask0005, in addition to (or instead of) the reporting location. This is the main ask.[MSBuildTaskSafeApiUsage("Process.Kill", Justification = "...")], so the review is recorded next to the code being reviewed.Impact
Any task that funnels process or file work through a shared helper hits this. The workaround (suppressing on
Execute) actively removes analyzer coverage, which undermines usingMSBuildTask0005as a regression guard.Found while migrating the
dotnet/dotnetVMR'sMicrosoft.DotNet.UnifiedBuild.Tasksto the multithreaded task model.