dotnet/runtime: an MSBuild tree checked as XML
dotnet/runtime keeps most of its structure in XML, in 5,856 .csproj files and 607 .props and .targets files, and pins versions in global. This config reads them with XML and JSON path rules instead of regexes, next to the bundled dotnet ruleset. This config was written to test alint; dotnet/runtime doesn't use alint.
What alint found
The bundled GitHub Actions rules (alint 0.16.1, on the workflows as of 7 May 2026) flag 15 action references not pinned to a commit, 4 workflows that grant contents: write at the workflow level, such as backport, and 2 that declare no permissions.
The config
Projects inherit settings from 361 Directory.Build files, eng/ maps each build subset to its projects, and global and eng/ pin the SDK and tools. The config checks the SDK each project names and its nullable setting as XML, the pins in global, a Directory in each area under src/ and the MIT header on C# sources. It extends the bundled dotnet, oss-baseline, ci/ and hygiene/ rulesets.
- id: dotnet-runtime-csproj-uses-known-sdk
kind: xml_path_matches
paths:
include:
- "src/coreclr/**/*.csproj"
- "src/libraries/**/*.csproj"
- "src/mono/**/*.csproj"
- "src/tasks/**/*.csproj"
- "src/tools/**/*.csproj"
exclude:
- "**/bin/**"
- "**/obj/**"
- "**/artifacts/**"
- "**/external/**"
- "**/ref/**"
path: "$.Project['@Sdk']"
matches: '^(Microsoft\.NET\.Sdk(\.\w+)?|Microsoft\.Build\.(NoTargets|Traversal))$'
if_present: true
level: warningxml_ reads the Sdk attribute on each project's root element, so a commented-out or nested element can't satisfy it.
- id: dotnet-runtime-global-json-sdk-and-tools-coherent
kind: cross_file_value_equals
source:
file: global.json
extract: { json: "$.sdk.version" }
targets:
- file: global.json
extract: { json: "$.tools.dotnet" }
normalize: trim
level: errorglobal names the .NET SDK twice, for the SDK and for the tools; the two have to agree. Three more rules pin the SDK, Arcade and Helix versions.
- id: dotnet-runtime-areas-have-directory-build-props
kind: for_each_dir
select: "src/{coreclr,libraries,mono,installer,tasks,tools}"
require:
- kind: file_exists
paths: "{path}/Directory.Build.props"
level: errorEach area under src/ sets its shared MSBuild properties in a Directory.
What stays outside alint
What MSBuild computes and what runs on Helix stay there:
- the Azure Pipelines matrix, Helix test runs and the internal pipeline templates;
- what MSBuild computes from the props files: packaging, analyzer and trimming targets;
- the API compatibility checks, which compare binaries with a previous release, and their
CompatibilitySuppressionsbaselines;.xml - C# style, which
dotnet formatchecks.