# Migrating a .NET project to Chainguard Libraries

URL: https://chainguard-docs-preview-git-uv-frozen-installs.chainguard.app/chainguard/libraries/dotnet/migration.md
Last Modified: October 16, 2026
Tags: Chainguard Libraries, .NET

How to migrate an existing .NET project to pull dependencies from Chainguard Libraries


Chainguard Libraries for .NET provides a registry of NuGet packages that have been scanned for malware and are subject to configurable policies. Switching an existing project requires only a registry configuration change – no changes to your application code or dependency versions.

This guide walks through migrating an existing .NET project to Chainguard Libraries, covering the two most common setups:

- **Direct access**: Your build tool connects directly to libraries.cgr.dev. This option is faster for initial evaluation and smaller-scale setups.
- **Repository manager**: Your build tool connects to a repository manager, which proxies requests to Chainguard Libraries. This option is recommended for teams and organizations.

## Prerequisites

Before getting started, you need:

- A .NET project with a .csproj file
- The .NET SDK
    - If you are using macOS, install the .NET SDK with Homebrew: `brew install --cask dotnet-sdk`
- `chainctl` installed and authenticated
- An [entitlement to Chainguard Libraries for .NET](#entitlement)
- A [pull token for Chainguard Libraries for .NET](#create-a-pull-token)

### Entitlement

To use Chainguard Libraries for .NET, your organization must be entitled to the .NET ecosystem. To add an entitlement, contact your Chainguard account team.

You do not need to manually enable upstream fallback for .NET; the entitlement for .NET automatically includes Chainguard protections for upstream artifacts.

You can configure a cooldown policy once your organization is entitled to .NET. For example, to create and enforce a policy for a 14-day cooldown:

```bash
chainctl libraries policy create --name=dotnet-cooldown-14d --cooldown-days=14
chainctl libraries policy enable dotnet-cooldown-14d --ecosystem=DOTNET --mode=ENFORCE
```

It can take up to 30 minutes for configured policies to take effect. Learn more about cooldown and other policies in the [Libraries policies documentation](/chainguard/chainguard-repository/library-policies/).

### Create a pull token

Create a pull token for the .NET repository:

```bash
chainctl auth pull-token --repository=dotnet --ttl=8670h
```

The command returns a username and password. Use these values to authenticate NuGet to Chainguard Libraries.

> **Note**: Do not commit the credentials to source control. Keep `nuget.config` out of the repository when it contains literal credentials, or generate it at build time from secrets stored in your CI/CD system. For shared environments, use a dedicated machine identity or service account instead of a personal token when available.

## Step 1: Configure authentication and registry

Choose the setup that matches your organization. With direct access, your build tool connects to libraries.cgr.dev. With a repository manager, your build tool connects to a proxy that you configure to fetch from Chainguard Libraries.



**Direct access**

<p>NuGet reads package sources from <code>nuget.config</code> files at the project, solution, user, and machine levels. Before changing the configuration, list the sources currently in use:</p>
<pre class="highlight" data-language="bash"><code class="language-bash" data-lang="bash">dotnet nuget list source</code></pre><p>Edit or create a file named <code>nuget.config</code> in the project directory, alongside the <code>.csproj</code> file. Replace its contents with the following configuration, substituting the username and password with the values of your pull token:</p>
<pre class="highlight" data-language="xml"><code class="language-xml" data-lang="xml">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;
&lt;configuration&gt;
  &lt;packageSources&gt;
    &lt;clear /&gt;
    &lt;add key=&#34;chainguard&#34; value=&#34;https://libraries.cgr.dev/dotnet/v3/index.json&#34; /&gt;
  &lt;/packageSources&gt;
  &lt;packageSourceCredentials&gt;
    &lt;chainguard&gt;
      &lt;add key=&#34;Username&#34; value=&#34;REPLACE WITH USERNAME FROM pull-token&#34; /&gt;
      &lt;add key=&#34;ClearTextPassword&#34; value=&#34;REPLACE WITH PASSWORD FROM pull-token&#34; /&gt;
    &lt;/chainguard&gt;
  &lt;/packageSourceCredentials&gt;
&lt;/configuration&gt;</code></pre><p>The <code>&lt;clear /&gt;</code> element removes previously configured package sources, including <code>nuget.org</code>. This prevents NuGet from silently falling back to <code>nuget.org</code>.</p>
<p>Confirm the active sources:</p>
<pre class="highlight" data-language="bash"><code class="language-bash" data-lang="bash">dotnet nuget list source</code></pre><p>The expected output shows Chainguard as enabled:</p>
<pre class="highlight" data-language="output"><code class="language-output" data-lang="output">Registered Sources:
  1.  chainguard [Enabled]
      https://libraries.cgr.dev/dotnet/v3/index.json</code></pre>


**Repository manager**

<p>Before you configure your project, set up your repository manager to proxy Chainguard Libraries for .NET. Follow the <a href="/chainguard/libraries/dotnet/global-configuration/">global configuration guide</a> to add Chainguard Libraries as an upstream source. Once the repository manager is configured, point your project at its URL instead of libraries.cgr.dev.</p>
<p>From the project directory, create a NuGet configuration file:</p>
<pre class="highlight" data-language="bash"><code class="language-bash" data-lang="bash">dotnet new nugetconfig</code></pre><p>Replace its contents with the following configuration, substituting your repository manager URL and credentials:</p>
<pre class="highlight" data-language="xml"><code class="language-xml" data-lang="xml">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;
&lt;configuration&gt;
  &lt;packageSources&gt;
    &lt;clear /&gt;
    &lt;add key=&#34;organization&#34; value=&#34;https://repo.example.com/nuget/dotnet&#34; /&gt;
  &lt;/packageSources&gt;
  &lt;packageSourceCredentials&gt;
    &lt;organization&gt;
      &lt;add key=&#34;Username&#34; value=&#34;REPLACE WITH REPOSITORY MANAGER USERNAME&#34; /&gt;
      &lt;add key=&#34;ClearTextPassword&#34; value=&#34;REPLACE WITH REPOSITORY MANAGER PASSWORD&#34; /&gt;
    &lt;/organization&gt;
  &lt;/packageSourceCredentials&gt;
&lt;/configuration&gt;</code></pre><p>Authenticate with your repository manager credentials, not your Chainguard pull token. The pull token authenticates the repository manager to Chainguard; it does not authenticate individual build tools to the repository manager.</p>
<p>The <code>&lt;clear /&gt;</code> element removes previously configured package sources, including <code>nuget.org</code>. This prevents NuGet from silently falling back to <code>nuget.org</code>.</p>
<p>Confirm the active sources:</p>
<pre class="highlight" data-language="bash"><code class="language-bash" data-lang="bash">dotnet nuget list source</code></pre><p>The expected output shows your repository manager as enabled:</p>
<pre class="highlight" data-language="output"><code class="language-output" data-lang="output">Registered Sources:
  1.  organization [Enabled]
      https://repo.example.com/nuget/dotnet</code></pre>





## Step 2: Clear caches, restore, and build

Because packages have previously been served from upstream, you must clear the NuGet HTTP cache and restore:

```bash
dotnet nuget locals http-cache --clear
dotnet restore --force --no-cache --verbosity normal
```

The output should include requests to the Chainguard endpoint. If you configured access through a repository manager, the output shows your repository manager URL instead. If the URL or credentials are incorrect, `restore` fails instead of using a cached package. Common errors include `NU1301`, `NU1101`, and `HTTP 401` responses.

After restoring, build your project:

```bash
dotnet build
```

## Step 3: Verify your libraries

Inspect the project assets file to confirm that your project is using Chainguard Libraries:

```bash
dotnet nuget list source
```

The expected output includes the Chainguard endpoint:

```output
      "sources": {
        "https://libraries.cgr.dev/dotnet/v3/index.json": {}
```

If you configured access through a repository manager, the `sources` entry shows your repository manager URL instead of `libraries.cgr.dev`, and must not contain `nuget.org`.

