# Migrating a .NET project to Chainguard Libraries

URL: https://chainguard-docs-preview-git-bot-docs-bundle-refresh.chainguard.app/chainguard/libraries/dotnet/migration.md
Last Modified: September 29, 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](#create-an-entitlement)
- A [pull token for Chainguard Libraries for .NET](#create-a-pull-token)

### Create an entitlement

To create an entitlement to Chainguard Libraries for .NET, run:

```bash
chainctl libraries entitlements create --ecosystems=DOTNET
```

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

You can also configure a cooldown policy after you create the entitlement. 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`.

