Issue Description
Static property functions are restricted to the allowlist in Microsoft.Build.Internal.AvailableStaticMethods (src/Build/Resources/Constants.cs). However, when an allowlisted static returns an object, any public instance method can then be chained onto the result.
Expander.Function.IsInstanceMethodAvailable (src/Build/Evaluation/Expander.Function.cs:1154) only rejects GetType unless FeatureSwitches.RestrictPropertyFunctionReceivers is on:
if (string.Equals("GetType", methodName, StringComparison.OrdinalIgnoreCase)) { return false; }
if (FeatureSwitches.RestrictPropertyFunctionReceivers) { return PropertyFunctionReceiver.IsAllowed(receiverType, methodName); }
return true;
That switch is effectively never on for a normal MSBuild: FeatureSwitches.cs:97 reads it via AppContext.TryGetSwitch (false when unset), and Microsoft.Build.Framework.csproj:47 emits the RuntimeHostConfigurationOption with Trim="true", so it only applies to trimmed apps. Microsoft.Build.dll in the SDK and in VS is untrimmed, so PropertyFunctionReceiver.IsAllowed — which deliberately excludes mutating members like Delete/MoveTo/CopyTo — never runs.
Practical consequence: Directory::GetParent is allowlisted and returns a live DirectoryInfo, so a project file can call mutating file-system methods during plain evaluation (no targets run, no packages involved).
Steps to Reproduce
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Result>$([System.IO.Directory]::GetParent('some_dir/x').Delete(true))</Result>
</PropertyGroup>
</Project>
mkdir some_dir && echo hi > some_dir/important.txt
dotnet build Repro.csproj -getProperty:Result
ls some_dir # gone
Expected Behavior
Chained instance calls should be limited to the curated PropertyFunctionReceiver allowlist; DirectoryInfo.Delete should fail to bind.
Actual Behavior
some_dir and its contents are deleted during evaluation. -getProperty shows it happens with evaluation alone (i.e. also on IDE background evaluation), with no output at all.
Versions & Configurations
Reproduced on .NET SDK 10.0.301; the same code path exists in the 8.0/9.0 SDKs. Default configuration, no environment variables or command-line switches.
Issue Description
Static property functions are restricted to the allowlist in
Microsoft.Build.Internal.AvailableStaticMethods(src/Build/Resources/Constants.cs). However, when an allowlisted static returns an object, any public instance method can then be chained onto the result.Expander.Function.IsInstanceMethodAvailable(src/Build/Evaluation/Expander.Function.cs:1154) only rejectsGetTypeunlessFeatureSwitches.RestrictPropertyFunctionReceiversis on:That switch is effectively never on for a normal MSBuild:
FeatureSwitches.cs:97reads it viaAppContext.TryGetSwitch(false when unset), andMicrosoft.Build.Framework.csproj:47emits theRuntimeHostConfigurationOptionwithTrim="true", so it only applies to trimmed apps.Microsoft.Build.dllin the SDK and in VS is untrimmed, soPropertyFunctionReceiver.IsAllowed— which deliberately excludes mutating members likeDelete/MoveTo/CopyTo— never runs.Practical consequence:
Directory::GetParentis allowlisted and returns a liveDirectoryInfo, so a project file can call mutating file-system methods during plain evaluation (no targets run, no packages involved).Steps to Reproduce
Expected Behavior
Chained instance calls should be limited to the curated
PropertyFunctionReceiverallowlist;DirectoryInfo.Deleteshould fail to bind.Actual Behavior
some_dirand its contents are deleted during evaluation.-getPropertyshows it happens with evaluation alone (i.e. also on IDE background evaluation), with no output at all.Versions & Configurations
Reproduced on .NET SDK 10.0.301; the same code path exists in the 8.0/9.0 SDKs. Default configuration, no environment variables or command-line switches.