Containers have become a standard deployment mechanism for modern .NET applications.

A typical application may move through several stages before reaching production:

Source Code
    |
    v
Build
    |
    v
Container Image
    |
    v
Container Registry
    |
    v
CI/CD Pipeline
    |
    v
Production

At every stage, there is an important question:

How can you prove that the container running in production is the same trusted artifact that was built by the expected publisher?

A container image digest can prove that a particular artifact has not changed since the digest was calculated. A digital signature adds another important property: it can associate that artifact with a trusted signing identity.

.NET 11 Preview 3 introduced signed official .NET container images. Microsoft announced that .NET container images are now signed, providing an additional supply-chain security signal for consumers of the official images.

This does not eliminate the need for dependency scanning, SBOMs, provenance, access controls, or runtime security. Instead, signing provides another layer in a broader software supply-chain security model.

What Does a Signed Container Image Mean?

A container image consists of metadata and filesystem layers identified by cryptographic digests.

A simplified representation is:

Container Image
    |
    +-- Manifest
    |
    +-- Configuration
    |
    +-- Layer 1
    |
    +-- Layer 2
    |
    +-- Layer 3

A signature binds the publisher's identity to the artifact descriptor, including its digest.

Conceptually:

Image Digest
     |
     v
Cryptographic Signature
     |
     v
Trusted Publisher Identity

When a consumer verifies the image, the verification process can establish:

  1. The signature is cryptographically valid.

  2. The signature corresponds to the artifact being consumed.

  3. The signing identity is trusted according to the configured policy.

  4. The artifact has not been modified since it was signed.

Microsoft's OCI artifact guidance describes signing as a way to establish both integrity and authenticity.

Why Container Signing Matters

Consider a normal container deployment:

Registry
   |
   v
Pull Image
   |
   v
Run Container

The registry may contain multiple tags:

myapp:latest
myapp:1.2
myapp:production

Tags are convenient, but they are mutable references.

A digest is more precise:

myapp@sha256:<digest>

Signing adds publisher identity to that immutable artifact reference.

The resulting trust model becomes:

Expected Publisher
        |
        v
Signed Artifact
        |
        v
Verified Digest
        |
        v
Deployment

This is significantly stronger than simply trusting a tag.

.NET 11 Official Container Images

Microsoft announced signed .NET container images as part of .NET 11 Preview 3.

Official .NET container images are available in different variants for runtime, ASP.NET Core, SDK, operating system, architecture, and other characteristics. Microsoft documents a tagging scheme based on the target framework, operating system, architecture, image type, and image variant.

A typical .NET application might use:

FROM mcr.microsoft.com/dotnet/aspnet:11.0 AS base

WORKDIR /app

EXPOSE 8080

and then:

FROM mcr.microsoft.com/dotnet/sdk:11.0 AS build

WORKDIR /src

COPY . .

RUN dotnet restore

RUN dotnet publish \
    -c Release \
    -o /app/publish \
    --no-restore

The final stage can copy the published application into the runtime image:

FROM base AS final

WORKDIR /app

COPY --from=build /app/publish .

ENTRYPOINT ["dotnet", "MyApplication.dll"]

The signing of Microsoft's official image is useful when that image is used as a trusted base layer, but your resulting application image still needs its own supply-chain controls.

Signing the Base Image Is Not Enough

This distinction is important.

Suppose your Dockerfile contains:

FROM mcr.microsoft.com/dotnet/aspnet:11.0

The official base image may be signed.

Your application image is then built on top of it:

Microsoft Signed Base Image
          |
          v
Your Application Files
          |
          v
Your Container Image

The resulting application image is a different artifact.

Therefore, organizations should consider signing their own final images as part of their CI/CD pipeline.

The trust chain should look more like:

Trusted Base Image
        |
        v
Controlled Build
        |
        v
Application Image
        |
        v
Organization Signature
        |
        v
Registry
        |
        v
Deployment Verification

OCI Signatures and Notation

The Notary Project provides tooling for signing and verifying OCI artifacts.

Notation is the command-line tool used to perform these operations.

Microsoft's current Azure Container Registry documentation describes Notation as a tool for signing and verifying OCI artifacts, including container images.

The workflow is conceptually:

Build Image
    |
    v
Push Image
    |
    v
Sign Image
    |
    v
Push Signature
    |
    v
Verify Before Deployment

This separates image creation from artifact trust.

Sign an Image With Notation

Suppose an image has already been pushed to a registry:

myregistry.example.com/orders-api:1.0

Notation can sign the image:

notation sign \
  myregistry.example.com/orders-api:1.0

The exact command depends on the configured signing key provider.

In a real organization, the signing key should not simply be stored as a plaintext file on a developer workstation.

Microsoft documents integrations with signing services such as Azure Key Vault and Azure Artifact Signing.

Why Key Management Matters

The security of a signed image depends heavily on the protection of the signing identity.

Consider:

Private Signing Key
        |
        v
Image Signature
        |
        v
Trusted Deployment

If an attacker obtains the signing credential, they may be able to produce artifacts that appear to originate from a trusted publisher.

Therefore:

Azure Artifact Signing provides an alternative to managing certificate lifecycle directly through Azure Key Vault and uses short-lived certificates with a managed signing experience.

Verify a Signed Image

Signing is useful only if consumers actually verify the signature.

Notation supports verification:

notation verify \
  myregistry.example.com/orders-api@sha256:<digest>

Microsoft's documentation demonstrates verification using a trust policy and trust store.

The verification process can be represented as:

Image
  |
  v
Find Signature
  |
  v
Validate Signature
  |
  v
Validate Certificate / Identity
  |
  v
Evaluate Trust Policy
  |
  +---- Trusted ----> Continue
  |
  +---- Untrusted --> Block

This is where signing becomes an enforceable security control rather than simply metadata attached to an image.

Trust Policies Are Critical

A signature can be mathematically valid while still coming from an identity your organization does not trust.

For example:

Image
 |
 +-- Valid signature
 |
 +-- Signer = UnknownDeveloper

Cryptographically valid does not automatically mean authorized.

A trust policy defines which identities are trusted for specific registry scopes.

A simplified policy concept looks like:

{
  "version": "1.0",
  "trustPolicies": [
    {
      "name": "production-images",
      "registryScopes": [
        "myregistry.example.com/orders"
      ],
      "signatureVerification": {
        "level": "strict"
      },
      "trustedIdentities": [
        "expected-publisher"
      ]
    }
  ]
}

The exact trust-store and identity configuration depends on the signing system.

Microsoft's Notation examples use trust policies to associate registry scopes with trust stores and trusted identities.

Verify by Digest, Not Just by Tag

Consider:

orders-api:production

A tag can move from one image digest to another.

For stronger deployment controls, use a digest:

orders-api@sha256:abc123...

Then verify the signature against that exact artifact.

A useful deployment pipeline is:

Build
  |
  v
Push
  |
  v
Resolve Digest
  |
  v
Sign Digest
  |
  v
Verify Digest
  |
  v
Deploy Digest

This prevents the deployment stage from accidentally resolving a mutable tag to a different image.

Integrating Signing Into CI/CD

A practical pipeline can be structured as follows:

Source
  |
  v
Build
  |
  v
Unit Tests
  |
  v
Security Scans
  |
  v
Container Build
  |
  v
Push
  |
  v
Sign
  |
  v
Verify
  |
  v
Deploy

The signing operation should occur after the final image has been built and pushed.

The deployment stage should verify the signature rather than assuming that the previous pipeline step was successful.

This creates a second security boundary:

Build Pipeline
      |
      v
Signed Artifact
      |
      v
Deployment Policy
      |
      v
Production

Example Azure DevOps Workflow

Microsoft provides an Azure DevOps Notation task that can sign and verify OCI artifacts in an Azure Pipeline.

A conceptual pipeline might contain:

steps:
- script: |
    docker build \
      -t $(REGISTRY)/orders-api:$(Build.BuildId) \
      .
  displayName: Build container

- script: |
    docker push \
      $(REGISTRY)/orders-api:$(Build.BuildId)
  displayName: Push container

- task: Notation@0
  inputs:
    command: 'sign'
    artifactRefs: '$(IMAGE)'
  displayName: Sign container

- task: Notation@0
  inputs:
    command: 'verify'
    artifactRefs: '$(IMAGE)'
    trustPolicy: '.pipeline/trustpolicy.json'
    trustStore: '.pipeline/truststore/'
  displayName: Verify container

The exact task configuration depends on the selected signing provider and pipeline environment.

Microsoft's documented Azure DevOps workflow builds and pushes the image, signs it, and then supports verification through a configured trust policy and trust store.

GitHub Actions

The same concept can be implemented in GitHub Actions.

Microsoft documents a workflow using Notation and Artifact Signing that builds an image, pushes it to Azure Container Registry, signs it, and stores the resulting signature in the registry.

A conceptual workflow is:

name: Build and Sign

on:
  push:

jobs:
  container:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: |
          docker build \
            -t ${{ env.IMAGE }}:${{ github.sha }} \
            .

      - name: Push image
        run: |
          docker push \
            ${{ env.IMAGE }}:${{ github.sha }}

      - name: Sign image
        run: |
          notation sign ${{ env.IMAGE }}@${{ env.DIGEST }}

The authentication and signing-provider configuration should be implemented using the identity and secret-management mechanisms supported by the chosen platform.

Do not place private signing keys directly in the workflow source.

Verify at Deployment Time

One of the strongest patterns is to make signature verification a deployment requirement.

Consider Kubernetes:

Registry
   |
   v
Image Request
   |
   v
Signature Verification
   |
   +---- Valid ----> Deployment
   |
   +---- Invalid --> Rejected

Microsoft documents using Ratify with Azure Policy to verify container image signatures in Azure Kubernetes Service.

This moves verification from an advisory CI/CD step to an enforcement point closer to production.

The exact enforcement architecture depends on the Kubernetes environment and policy stack.

Build a Chain of Trust

A mature container supply chain should verify more than one property.

For example:

                    Source
                      |
                      v
                Controlled Build
                      |
          +-----------+-----------+
          |                       |
          v                       v
        SBOM                 Provenance
          |                       |
          +-----------+-----------+
                      |
                      v
                Container Image
                      |
                      v
                  Signature
                      |
                      v
                 Registry
                      |
                      v
              Deployment Policy

Container signing provides authenticity and integrity for the artifact.

SBOMs provide visibility into components.

Build provenance can provide information about how an artifact was produced.

Vulnerability scanning identifies known security issues.

None of these mechanisms replaces the others.

Signing vs Hashing vs Scanning

ControlPrimary PurposeAnswers
DigestArtifact integrity referenceDid this artifact change?
SignatureIntegrity + publisher identityWho signed this artifact?
Vulnerability scanKnown vulnerability detectionDoes it contain known issues?
SBOMComponent visibilityWhat is inside it?
ProvenanceBuild traceabilityHow was it produced?
Runtime policyDeployment enforcementIs this artifact allowed to run?

A secure supply chain generally combines several of these controls.

Common Mistakes

Signing Only the Base Image

A signed Microsoft base image does not automatically make your application image trusted.

Sign your final application artifact as well.

Signing Mutable Tags Without Tracking Digests

Always know which digest was actually signed.

Storing Signing Keys in Source Control

Private signing credentials should never be committed to a Git repository.

Verifying Signatures Only in CI

If deployment can bypass the verification stage, the security control may be bypassed.

Where practical, enforce verification at the deployment boundary.

Trusting Any Valid Signature

A valid signature from an untrusted identity should not automatically authorize deployment.

Trust policy matters.

Treating Signing as Vulnerability Scanning

A perfectly signed image can still contain a vulnerable dependency.

Signing establishes provenance-related trust properties; it does not prove that the software is vulnerability-free.

Troubleshooting Signature Verification

Verification Fails With an Unknown Signer

Check the configured trust store and trust policy.

The certificate may be valid but not trusted by the verifier.

The Image Was Rebuilt and Verification Fails

That can be expected.

A rebuilt image normally has a different digest and therefore needs its own signature.

The Tag Works but the Digest Does Not

Check whether the tag points to the same digest that was signed.

Avoid using mutable tags as the security identity of an artifact.

The Image Is Signed but Deployment Still Succeeds After Verification Is Removed

That is expected if verification is only a CI step.

Signing does not automatically enforce deployment policy.

Add an admission or deployment-time verification mechanism where appropriate.

Testing a Supply Chain

A useful security test suite should include both successful and failed scenarios.

Valid image
   |
   +-- Valid signature
   +-- Trusted identity
   +-- Expected registry
   |
   +----> Deploy


Tampered image
   |
   +-- Invalid signature
   |
   +----> Reject


Untrusted signer
   |
   +-- Valid cryptographic signature
   +-- Wrong identity
   |
   +----> Reject


Unsigned image
   |
   +----> Reject


Wrong digest
   |
   +----> Reject

These tests demonstrate that the policy actually enforces the intended trust model.

Best Practices

Sign Immutable Artifacts

Prefer digest-based references for security-sensitive deployment.

Keep Signing Separate From Building

The identity that builds an artifact does not necessarily need unrestricted signing privileges.

Protect Signing Identities

Use a managed key or signing service where appropriate.

Verify Before Production

Do not rely solely on the registry to tell you that an artifact is trusted.

Enforce Verification

Make deployment fail when required signatures are missing or invalid.

Maintain a Trust Policy

Define exactly which publishers are trusted for which repositories.

Combine Controls

Use signing together with:

Frequently Asked Questions

Are all .NET container images signed?

Microsoft announced signed .NET container images beginning with .NET 11 Preview 3. The exact image and version should still be verified against the official image and release documentation being consumed.

Does a signed image guarantee that it is secure?

No.

A signature provides authenticity and integrity information. It does not prove that the image contains no vulnerabilities or malicious application logic.

Can I sign my own .NET container image?

Yes.

OCI-compatible tooling such as Notation can sign container images, and Microsoft documents integrations with signing systems including Azure Key Vault and Artifact Signing.

Should I verify the image in CI/CD?

Yes.

CI/CD verification is useful, but production environments should also consider enforcing signature policies at deployment time.

Why use a digest if the image is signed?

The digest identifies the exact artifact.

A tag such as latest can point to different artifacts over time. A digest provides a stable reference to the specific image being verified.

Conclusion

Signed container images provide an important building block for modern software supply-chain security.

For .NET developers, the introduction of signatures for official .NET container images provides stronger trust information when consuming Microsoft-provided base images.

But a secure supply chain requires more than trusting the base image.

A stronger architecture is:

Official Trusted Base
        |
        v
Controlled Build
        |
        v
Application Image
        |
        v
SBOM + Security Checks
        |
        v
Organization Signature
        |
        v
Registry
        |
        v
Digest Verification
        |
        v
Deployment Policy
        |
        v
Production

The key principle is:

Build trust into the artifact lifecycle, then enforce that trust at deployment time.

Container signing answers an important question—whether an artifact is associated with a trusted publisher and has remained intact—but it should operate alongside vulnerability scanning, SBOMs, provenance, identity controls, and runtime policies.

For teams building .NET applications in containers, that combination turns a simple image-push workflow into a more verifiable software supply chain.