What this integration does
The .NET CLI, nuget.exe and Visual Studio restore through mShield instead of talking to
nuget.org directly. Each .nupkg download is evaluated against your policies before it
reaches the machine. Package listings and the service index behave normally; a package that fails
policy stops with an HTTP 403 naming the check that refused it.
The integration is one package source in a NuGet.config. Nothing is installed on the
developer's machine, and in egress-interception mode there is no client change at all.
For SaaS and on-prem. This guide uses client configuration. DNS mode is an alternative available only on-prem; see deployment models.
Point NuGet at your mShield source
Your deployment provides the hostname and the credentials to use. Replace
nuget.example.mshield.dev below with your own.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="mshield" value="https://nuget.example.mshield.dev/v3/index.json" protocolVersion="3" />
</packageSources>
<packageSourceCredentials>
<mshield>
<add key="Username" value="token" />
<add key="ClearTextPassword" value="<your-token>" />
</mshield>
</packageSourceCredentials>
</configuration>
The <clear /> line matters. Without it the machine-wide nuget.org source stays in
the list, and a restore can succeed without ever touching mShield.
Scopes
- Project or solution — recommended for a pilot. Save the file as
NuGet.confignext to the solution. NuGet picks it up for any command run beneath that directory. - User.
~/.nuget/NuGet/NuGet.Config(Windows:%AppData%\NuGet\NuGet.Config) covers every solution for that account. - Machine. A machine-wide config needs administrator rights; typical for a build image or shared runner.
Merging into an existing NuGet.config. Keep your other sections. Only the
packageSources list needs to end up pointing at mShield. If you use package source
mapping, map your patterns to the mshield source key.
Do not leave a second source such as nuget.org enabled alongside mShield unless you deliberately want a fallback past it. A second source is an ungated path to the same packages.
On tokens. ClearTextPassword is readable by anyone who can read the
file. Keep it out of version control and rotate the token if it is shared or committed.
Verify it took effect
dotnet nuget list source
dotnet restore --force --no-cache
dotnet nuget list source should show only your mShield source as enabled. Run it from
outside the project directory: the line should be gone — that is the proof a project-scoped change
is confined to this project. Use --force --no-cache so the restore does not satisfy itself
from the local package cache.
CI runners
- Write
NuGet.configin the job from a secret before the restore step. It is discarded with the workspace. - Bake it into the build image at machine scope so every job is covered without editing pipelines.
Cached package folders hide the proxy: on a runner that keeps ~/.nuget/packages
between jobs, a package already in the cache is never fetched again and so is never evaluated.
What a blocked restore looks like
error NU1301: Response status code does not indicate success: 403
Package "Newtonsoft.Json" 9.0.1 was refused by policy "Production dependencies"
| More details: https://mshield.example.com/...
The restore fails the way it fails any rejected download, and the refusal names the package and the rule behind it.
The refusal also carries a link to a page that explains the block in full — what was refused, why, the version that would satisfy the policy, and a way to request an exclusion. It needs no login, and it is scoped to that single refusal. See what the developer opens.
If the block is wrong for a case your team has accepted, the developer requests an exclusion from that page; an operator grants or refuses it, and a granted exclusion is package-scoped, time-boxed, and recorded like any other decision.
Rolling back
Remove the mshield source (or delete the NuGet.config you added) and
restore your previous packageSources. Decisions already recorded stay in the dashboard.