5.2 Feed Scoping, Upstream Sources & Pipeline Authentication
Key Takeaways
- Project-scoped feeds are the modern default and inherit project permissions; organisation-scoped feeds are shared across every project and are harder to govern.
- An upstream source caches every package pulled from a public registry into the feed, so the build keeps working during a public registry outage or package unpublish.
- Dependency confusion occurs when a public registry serves a higher version of an internal package name; the defence is a single feed with upstreams plus reserved or scoped names.
- Azure Pipelines authenticates to Azure Artifacts with the built-in NuGetAuthenticate and npmAuthenticate tasks using $(System.AccessToken) - no personal access token is required.
- An HTTP 401 on npm install from a Microsoft-hosted agent almost always means the .npmrc registry entry is missing or the build service identity lacks the Feed Reader role.
5.2 Feed Scoping, Upstream Sources & Pipeline Authentication
Choosing the platform is the easy half. The operational half is deciding who can consume a feed, what happens when the public registry is unavailable or hostile, and how a build agent authenticates without a stored credential.
Feed Architecture in Azure Artifacts: Project-Scoped vs. Organization-Scoped
When creating a feed in Azure Artifacts, administrators must choose between two scoping models: Project-scoped feeds and Organization-scoped feeds. This structural decision dictates security boundaries, access inheritance, and URL endpoints.
Azure Artifacts Feed Scoping Hierarchy:
[Azure DevOps Organization: contoso-devops]
│
├── Organization-Scoped Feed: [Enterprise-Common-Libraries]
│ └── URL: https://pkgs.dev.azure.com/contoso-devops/_packaging/Enterprise-Common-Libraries/...
│ └── Visibility: All projects and teams across contoso-devops
│
├── Project: [Retail-Banking]
│ └── Project-Scoped Feed: [Retail-Banking-Components]
│ └── URL: https://pkgs.dev.azure.com/contoso-devops/Retail-Banking/_packaging/...
│ └── Visibility: Restricted to members of Retail-Banking
│
└── Project: [Commercial-Loans]
└── Project-Scoped Feed: [Commercial-Loans-Components]
└── Visibility: Restricted to members of Commercial-Loans
1. Project-Scoped Feeds (Modern Default)
In modern Azure DevOps, newly created feeds default to Project-scoped. The project name is explicitly embedded into the feed's package manager endpoint URL:
https://pkgs.dev.azure.com/{organization}/{project}/_packaging/{feedName}/nuget/v3/index.json
- Security & Access Boundary: Project-scoped feeds inherit permissions directly from the hosting Azure DevOps project. Users, groups, and build service accounts must have permissions within the project to access the feed.
- Project Isolation: Feeds are completely isolated from other projects in the same organization. If the project is deleted, the feed and all its packages are deleted.
- Recommended Use Cases:
- Microservices or modular applications where package dependencies are strictly internal to that specific product or project team.
- Regulated systems requiring strict zero-trust segregation between distinct business units or client-specific deliverables.
2. Organization-Scoped Feeds
Organization-scoped feeds are created at the root level of the Azure DevOps organization without being bound to a specific project. The project segment is omitted from the URL:
https://pkgs.dev.azure.com/{organization}/_packaging/{feedName}/nuget/v3/index.json
- Security & Access Boundary: Permissions are managed at the organization level. Any project within the organization can reference and consume packages from the feed, provided project build service accounts are granted
Readerpermissions. - Recommended Use Cases:
- Core enterprise shared libraries (e.g., organizational logging frameworks, standardized authentication wrappers, common corporate UI components).
- Monolithic enterprise architectures where hundreds of repositories across dozens of projects depend on a unified set of internally vetted packages.
| Criteria | Project-Scoped Feed | Organization-Scoped Feed |
|---|---|---|
| URL Structure | Contains /{organization}/{project}/_packaging/ | Contains /{organization}/_packaging/ |
| Default Permissions | Inherits from Azure DevOps Project ACLs | Managed via Organization Collection ACLs |
| Cross-Project Access | Requires explicit cross-project build service permissions | Readily accessible to all projects across tenant |
| Lifecycle Dependency | Tied to project existence | Independent of individual projects |
| AZ-400 Recommended Role | Team-specific components & microservices | Enterprise-wide shared utility frameworks |
Upstream Sources, Outage Resilience & Dependency Confusion Defense
Modern applications rely heavily on external open-source packages from public registries such as nuget.org, npmjs.com, PyPI, and Maven Central. Connecting an Azure Artifacts feed to Upstream Sources provides caching, governance, and supply chain security.
Upstream Caching and Resilience
When an Azure Artifacts feed is configured with an upstream source (such as nuget.org):
- A developer or CI build agent requests package
Newtonsoft.Json 13.0.3from the internal Azure Artifacts feed. - Azure Artifacts checks if
Newtonsoft.Json 13.0.3exists in its internal storage:- Cache Miss: Azure Artifacts proxies the request to
nuget.org, downloads the package, validates its checksum, saves a cached copy into the feed, and returns it to the requester. - Cache Hit: If another developer or pipeline requests
Newtonsoft.Json 13.0.3in the future, Azure Artifacts serves the cached copy directly from internal storage.
- Cache Miss: Azure Artifacts proxies the request to
Upstream Ingestion and Caching Flow:
[Developer / CI Agent]
│
▼ (1. Request: Newtonsoft.Json 13.0.3)
[Azure Artifacts Feed]
│
├── (2. Check Local Cache: MISS)
│
▼ (3. Fetch from Upstream)
[Upstream Source: nuget.org]
│
▼ (4. Stream Package Binary)
[Azure Artifacts Feed] ──► [Saves Immutable Cached Copy to @local]
│
▼ (5. Return Package Binary to Client)
[Developer / CI Agent]
Why Upstream Caching is Critical for CI/CD
- Resilience Against Public Registry Outages: If
npmjs.comornuget.orgsuffers an outage, builds do not fail because all previously restored dependencies are served directly from the Azure Artifacts internal cache. - Protection Against Upstream Deletions: If an author unpublishes or deletes an open-source library from a public registry, the cached copy remains permanently in the internal Azure Artifacts feed, ensuring future builds succeed.
- Bandwidth & Latency Optimization: Builds running on Azure Pipelines agents in the same Azure region retrieve cached dependencies over internal Azure datacenter backbones rather than transiting the public internet.
Dependency Confusion (Namespace Collision) Attacks
A Dependency Confusion attack (discovered by security researcher Alex Birsan) targets software delivery pipelines that combine private internal packages with public open-source packages.
Dependency Confusion Vulnerability Mechanism:
1. Enterprise develops internal proprietary package: 'contoso-telemetry-auth' (v1.2.0)
2. Attacker discovers internal package name from leaked configs or build logs
3. Attacker publishes malicious package named 'contoso-telemetry-auth' to public npmjs.org (v99.0.0)
4. Package manager (npm/yarn/pip) queries feed with upstreams enabled:
Internal Feed offers: contoso-telemetry-auth v1.2.0
Public Upstream offers: contoso-telemetry-auth v99.0.0 (HIGHER VERSION)
5. Default package manager logic resolves v99.0.0 from public registry!
6. Malicious code executes inside enterprise CI/CD pipeline or developer machine!
Defenses in Azure Artifacts & Package Managers
To prevent dependency confusion in Azure Artifacts and client package managers, implement three complementary controls:
- Package Source Mapping (NuGet): In
nuget.config, declare explicitpackageSourceMappingpatterns. This forces the package manager to query only the internal feed for internal namespaces and only public upstreams for open-source namespaces:
<!-- nuget.config with Package Source Mapping -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="ContosoInternalFeed" value="https://pkgs.dev.azure.com/contoso/Finance/_packaging/CoreFeed/nuget/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceMapping>
<!-- Internal proprietary libraries are strictly routed to the internal feed -->
<packageSource key="ContosoInternalFeed">
<package pattern="Contoso.*" />
<package pattern="CompanyCore.*" />
</packageSource>
<!-- All third-party open-source libraries are routed to nuget.org -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>
- Scoped Namespaces (npm): For JavaScript/TypeScript, always prefix proprietary packages with an organizational scope (e.g.,
@contoso/telemetry-auth). In.npmrc, route that scope exclusively to the private Azure Artifacts feed while leaving default packages routed to public npmjs:
# .npmrc configuration enforcing scoped routing
@contoso:registry=https://pkgs.dev.azure.com/contoso/Finance/_packaging/CoreFeed/npm/registry/
always-auth=true
- Upstream Source Internal Package Priority: In Azure Artifacts feed settings, administrators can explicitly configure package source behavior to block external resolution for specific package identifiers once an internal package is published.
Authentication & Credential Provisioning
Private package feeds require secure, authenticated access. In Exam AZ-400, understanding how to configure authentication for both developer workstations and automated CI/CD pipelines is heavily tested.
Feed Authentication Matrix:
[Developer Workstation] ──► Azure Artifacts Credential Provider ──► Entra ID Device Flow / PAT
[CI/CD Build Pipeline] ──► Packaging Authenticate Tasks ───────► $(System.AccessToken)
[External System / CLI] ──► az artifacts login / Scoped PAT ────► Basic Auth / Bearer Token
1. Developer Workstation Authentication
- Personal Access Tokens (PATs): Developers can generate a PAT in Azure DevOps user settings. For packaging operations, the PAT must be assigned the Packaging scope:
Packaging (Read): Allows querying and downloading packages.Packaging (Read & write): Allows publishing new packages and unlisting.Packaging (Read, write, & manage): Full permissions including feed settings and view management.
- Azure Artifacts Credential Provider: The recommended modern approach for .NET developers. The credential provider automatically detects when
dotnet restoreornuget.exeencounters an authenticated Azure Artifacts feed and launches an interactive Microsoft Entra ID browser prompt or device code login, acquiring short-lived bearer tokens without requiring manual PAT generation in configuration files. - Azure CLI
az artifacts login: Automatically injects authentication tokens into client configuration files for npm, pip, and twine:
# Authenticate Azure CLI with packaging credentials for npm
az artifacts login --organization https://dev.azure.com/contoso --name CoreFeed --tool npm
2. Azure Pipelines CI/CD Authentication
In automated pipelines, developers must never hardcode personal access tokens or credentials into nuget.config or .npmrc files stored in source repositories. Instead, Azure Pipelines provides dedicated authentication tasks that dynamically inject the pipeline's runtime identity token ($(System.AccessToken)):
NuGetAuthenticate@1: Configures authentication for NuGet package restore and push commands.npmAuthenticate@0: Injects credentials into.npmrcfiles located in the pipeline workspace.TwineAuthenticate@1: Injects authentication variables for Pythontwineuploads to PyPI feeds.MavenAuthenticate@0: Updates Mavensettings.xmlwith repository credentials.
YAML Pipeline Example: Authenticating and Publishing NuGet and npm Packages
# azure-pipelines.yml: Authenticating feeds and publishing packages
trigger:
branches:
include:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
feedName: 'Retail-Banking/CoreComponentsFeed'
steps:
# 1. Checkout source code
- checkout: self
# 2. Authenticate NuGet feed using runtime pipeline token
- task: NuGetAuthenticate@1
displayName: 'Authenticate with Azure Artifacts NuGet Feed'
inputs:
forceReinstallCredentialProvider: false
# 3. Restore and build .NET library
- task: DotNetCoreCLI@2
displayName: 'Restore NuGet Packages'
inputs:
command: 'restore'
projects: '**/*.csproj'
feedsToUse: 'select'
feedRestore: '$(feedName)'
- task: DotNetCoreCLI@2
displayName: 'Pack NuGet Package'
inputs:
command: 'pack'
packagesToPack: '**/*.csproj'
versioningScheme: 'off'
outputDir: '$(Build.ArtifactStagingDirectory)/nuget'
# 4. Push NuGet package to Azure Artifacts
- task: DotNetCoreCLI@2
displayName: 'Push NuGet Package to Feed'
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/nuget/*.nupkg'
publishVstsFeed: '$(feedName)'
# 5. Authenticate npm session using .npmrc
- task: npmAuthenticate@0
displayName: 'Authenticate npm using .npmrc'
inputs:
workingFile: '$(System.DefaultWorkingDirectory)/client-app/.npmrc'
# 6. Install and publish npm package
- script: |
cd client-app
npm install
npm publish
displayName: 'Publish npm Package to Azure Artifacts'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
Practical AZ-400 Exam Scenarios & Anti-Patterns
Scenario 1: Preventing Dependency Confusion in Multi-Source Environments
- Scenario: A corporate security audit reveals that developer machines and CI build agents frequently download packages from public
npmjs.orgrather than the company's internal private Azure Artifacts feed whenever identical package names exist. - AZ-400 Solution: Enforce organizational scoping (
@contoso/packagename) for all internal npm packages. In the workspace.npmrc, bind@contoso:registryexclusively to the private feed URL. For .NET projects, commit a repository-levelnuget.configwithpackageSourceMappingexplicitly routingContoso.*patterns to the internal feed and*patterns tonuget.org.
Scenario 2: Storing Multi-Gigabyte Deployment Payloads
- Scenario: An engineering team deploying automated test rigs requires downloading a 35 GB pre-compiled simulation engine and operating system image during pipeline runs. They attempt to publish it as a NuGet package to Azure Artifacts, but the upload is rejected.
- AZ-400 Solution: NuGet packages in Azure Artifacts are capped at 500 MiB. The team must publish the 35 GB binary payload as a Universal Package using the Azure CLI (
az artifacts universal publish). Universal Packages support arbitrary file collections up to 4 TiB in size.
An enterprise develops an internal proprietary library named 'contoso-financial-core'. During an automated CI build, the build agent pulls an unexpected version 99.1.0 published on public npmjs.org containing malicious code, rather than the expected internal version 1.4.0 from their Azure Artifacts feed. What security vulnerability occurred, and what is the primary recommended defense to prevent this in Azure Artifacts?
A developer configures an Azure Pipelines YAML build to restore private npm packages from a project-scoped Azure Artifacts feed. The build fails on a Microsoft-hosted agent with an HTTP 401 Unauthorized error during the 'npm install' step. The repository includes a valid .npmrc file referencing the feed registry URL. What step must be added to the pipeline immediately prior to 'npm install' to resolve the authentication failure without exposing secrets?