ASP.NET 10 official runtime baseline¶
Baseline date: 2026-08-13
Platform: linux/amd64
Discovery tag: mcr.microsoft.com/dotnet/aspnet:10.0
Immutable manifest: mcr.microsoft.com/dotnet/aspnet@sha256:282c2e90dd35c6a720b744f4848d3dce9de4bfb404011270cc8ee63f07e56c36
Version observed: .NET Runtime 10.0.11 / ASP.NET Core Runtime 10.0.11
Status: registry and filesystem inspection complete; live container commands remain to be repeated when the local Docker engine is healthy
Why establish a baseline?¶
A hardened-image claim only has meaning relative to a measured starting point. An OCI tag such as 10.0 is movable: Microsoft can repoint it after a patch rebuild. A digest identifies one exact manifest and is therefore the correct identity for evidence, SBOMs, scans, and later comparisons.
The 10.0 tag is a multi-platform image index. Its index digest was sha256:207cc51496778557731c81ff670333d8ade4a4fec22768fd1be8e78474a84ecf; the digest above is the Linux amd64 child manifest selected from that index. Evidence must state both platform and digest.
Result summary¶
| Property | Observed result | How established |
|---|---|---|
| Base operating system | Ubuntu 24.04 LTS (Noble) | OCI label and Microsoft's runtime-deps Dockerfile |
| Architecture | amd64 |
OCI manifest/config |
| Created | 2026-08-10T17:01:15.238169197Z |
OCI config |
| Unpacked image size | 236,417,516 bytes (about 225.5 MiB) | Syft image source metadata |
| Registry transfer size | 98,271,223 bytes (about 93.7 MiB), excluding manifest/config | Sum of six compressed OCI layer sizes |
| Filesystem layers | 6 | OCI manifest |
| Default user | unset, therefore root (UID 0) | OCI config User = null |
| Created non-root account | app, UID/GID 1654 |
official runtime-deps Dockerfile and layer history |
| Distribution packages | 97 records with Status: install ok installed |
final dpkg status database extracted from the dependency layer |
| Syft component findings | 106: 100 deb, 4 binary, 2 .NET |
Syft 1.50.0 native catalog; three deb findings are binary-inferred rather than direct dpkg records |
| Interactive shell | present (bash 5.2.21) |
package database, Syft file catalog, and configured command /bin/bash |
| Package manager | present (apt 2.8.3 and dpkg 1.22.6) |
package database and /usr/bin/apt-get in Syft file catalog |
| Unnecessary network clients checked | curl, wget, ssh, and nc not found in the Syft catalog |
Syft file catalog; repeat live with command -v |
| Build tools checked | gcc, make, and python executables not found |
Syft file catalog; the ASP.NET image contains runtime, not SDK, content |
| Exposed ports metadata | none | OCI config ExposedPorts = null |
| Intended HTTP port | 8080 | ASPNETCORE_HTTP_PORTS=8080; this is application configuration, not host publication |
| Entrypoint | none | OCI config Entrypoint = null |
| Default command | /bin/bash |
OCI config |
| Working directory | unset | OCI config |
| SPDX SBOM | generated, SPDX 2.3, 107 SPDX package entries | Syft 1.50.0 |
| Vulnerability scan | 132 matches; interpretation required | Grype 0.116.1, database built 2026-08-13 06:39:30 UTC |
Microsoft's official .NET 10 image listing identifies Ubuntu 24.04 as the default 10.0 Linux variant. The authoritative ASP.NET Dockerfile copies the ASP.NET shared framework onto the .NET runtime. The runtime-deps Dockerfile shows the selected OS dependencies and UID 1654 account creation.
Step 1: resolve and pull the artifact¶
docker pull mcr.microsoft.com/dotnet/aspnet:10.0
docker image inspect mcr.microsoft.com/dotnet/aspnet:10.0 `
--format '{{index .RepoDigests 0}}'
pull downloads the image index, selects the host platform, and obtains its content-addressed layers. RepoDigests reports the registry digest. Expected on linux/amd64 for this baseline:
mcr.microsoft.com/dotnet/aspnet@sha256:282c2e90dd35c6a720b744f4848d3dce9de4bfb404011270cc8ee63f07e56c36
If a different digest appears, do not overwrite these results. Start a newly dated baseline because the artifact changed.
In this session Docker Desktop 4.23.0 started its WSL support services but never launched dockerd; the Windows API proxy remained unresponsive. The manifest was therefore resolved independently through MCR's read-only OCI Distribution API. That is valid for image metadata, but it does not substitute for the live tests below.
Step 2: inspect configuration and layers¶
$image = 'mcr.microsoft.com/dotnet/aspnet@sha256:282c2e90dd35c6a720b744f4848d3dce9de4bfb404011270cc8ee63f07e56c36'
docker image inspect $image
docker image history --no-trunc $image
An image has two related structures:
- Filesystem layers are content-addressed changes such as the Ubuntu root filesystem or copied .NET runtime files.
- The image configuration is metadata such as environment, user, command, entrypoint, and uncompressed layer identifiers.
--no-trunc preserves full build-history entries. History is useful context but is not provenance: it does not prove who ran a build or which source revision was used.
The six compressed layer sizes were:
The layers correspond broadly to Ubuntu, runtime dependencies, account creation, .NET runtime, the dotnet link, and ASP.NET runtime content.
Step 3: inspect the running filesystem¶
Run each check manually; the point is to see what exists, not merely pass a gate.
$image = 'mcr.microsoft.com/dotnet/aspnet@sha256:282c2e90dd35c6a720b744f4848d3dce9de4bfb404011270cc8ee63f07e56c36'
docker run --rm $image cat /etc/os-release
docker run --rm $image sh -c 'id; command -v bash; command -v apt-get'
docker run --rm $image sh -c 'dpkg-query -W -f="${Package}\t${Version}\n" | sort'
docker run --rm $image sh -c 'dpkg-query -W -f="${db:Status-Abbrev}\n" | grep -c "^ii"'
docker run --rm $image sh -c 'for x in curl wget ssh nc gcc make python3; do command -v "$x" || true; done'
The equivalent command from a Linux host shell is:
Expected concepts and results:
- An unset image user means the runtime starts as root even though an
appaccount exists. bash,sh,apt-get, anddpkgare present in the ordinary Ubuntu image.- Runtime library packages are expected; compiler/SDK packages are not.
EXPOSEdoes not publish a port, and this image has noEXPOSEmetadata anyway.ASPNETCORE_HTTP_PORTS=8080tells compatible ASP.NET applications where to listen.- The base runtime has no application entrypoint; its inherited Ubuntu command opens Bash. A child application image normally supplies
ENTRYPOINT ["dotnet", "App.dll"]or equivalent entrypoint plus command.
The direct dpkg inventory contains 97 installed packages. Important attack-surface observations include apt, dpkg, bash, coreutils, perl-base, procps, openssl, and general-purpose filesystem utilities. Their presence is not automatically a vulnerability, but each tool expands what an attacker can use after code execution.
Step 4: generate the SBOM¶
An SBOM inventories discovered components in this final artifact. Scanning the final image matters because a build-stage SBOM would include SDK/compiler packages that are not shipped and might miss files introduced later.
$image = 'registry:mcr.microsoft.com/dotnet/aspnet@sha256:282c2e90dd35c6a720b744f4848d3dce9de4bfb404011270cc8ee63f07e56c36'
syft scan $image --platform linux/amd64 `
-o spdx-json=evidence/baseline/aspnet-10.0.11-linux-amd64.spdx.json `
-o syft-json=evidence/baseline/aspnet-10.0.11-linux-amd64.syft.json
registry:bypasses the Docker daemon and reads OCI content from MCR.--platformprevents an ambiguous multi-platform selection.- SPDX is the exchange deliverable. Native Syft JSON preserves catalog details and is accepted directly by Grype.
- Package URLs (purls) give packages ecosystem-aware identifiers; they are identifiers, not proof of vulnerability.
Syft 1.50.0 found 106 artifacts: 100 Debian/Ubuntu package findings, four binary findings, and two .NET framework findings. SPDX contains 107 package records because it also represents the image source as a package.
Step 5: scan vulnerabilities¶
grype sbom:evidence/baseline/aspnet-10.0.11-linux-amd64.syft.json `
--by-cve `
--output json `
--file evidence/baseline/aspnet-10.0.11-linux-amd64.grype.json
--by-cve normalizes related advisory identifiers toward CVE identifiers. The scan produced:
| Severity | Count |
|---|---|
| Critical | 4 |
| High | 17 |
| Medium | 90 |
| Low | 19 |
| Negligible | 2 |
This table is not a release decision. Of 132 matches, 94 came from Ubuntu's distribution namespace and 38 from generic NVD CPE matching. The Ubuntu-specific matches included zero Critical and zero High. All 4 Critical and all 17 High matches were generic binary/CPE matches, primarily against an OpenSSL binary version. Distribution packages often backport patches without changing the upstream-looking binary version, so those findings require advisory and applicability review. They must not be silently suppressed, but they also must not be advertised as 21 confirmed exploitable flaws.
This Grype JSON format did not emit a per-match KEV flag, so the 79 unique scanned CVE identifiers were independently intersected with CISA's official KEV JSON catalog version 2026.08.11 (released 2026-08-11T18:59:43.6861Z, 1,665 entries, downloaded SHA-256 64BB30C14AB0AA40F0032325A2303F8EB3A348348A27D6533B9E4DDF4424D5D8). The intersection contained zero identifiers. This is a point-in-time catalog comparison, not a statement about future KEV additions or vulnerability applicability.
Full evidence:
evidence/baseline/aspnet-10.0.11-linux-amd64.spdx.jsonevidence/baseline/aspnet-10.0.11-linux-amd64.syft.jsonevidence/baseline/aspnet-10.0.11-linux-amd64.grype.jsonevidence/baseline/vulnerability-summary.json
Stage 1 conclusion¶
The official ordinary ASP.NET image is a production runtime rather than an SDK image, but it is not a least-tooling artifact: it defaults to root and retains a shell, package manager, and broad Ubuntu userland. Those facts justify evaluating the official Noble Chiseled variant as the starting material for IHL-CTR-0001. Chiseled is not automatically “secure”; it is a smaller and more constrained composition on which runtime controls, SBOM, scanning, signing, provenance, and evidence still need to be applied.
Do not mark Stage 1 fully runtime-validated until the five live Docker command groups above have been repeated on a healthy engine and their outputs reconciled with this document.