Hacktricks-skills dependency-confusion-audit

Audit and remediate dependency confusion vulnerabilities in package management configurations. Use this skill whenever the user mentions package managers (npm, pip, Maven, Gradle, NuGet, Go modules, Cargo, Bundler), CI/CD security, supply chain attacks, internal registries, or wants to secure their build dependencies. Also use when reviewing .npmrc, pip.conf, nuget.config, settings.xml, Gemfile, or any package configuration files. Make sure to use this skill when the user asks about securing dependencies, preventing supply chain attacks, or configuring private registries.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/dependency-confusion/SKILL.MD
source content

Dependency Confusion Audit & Remediation

This skill helps you identify and fix dependency confusion vulnerabilities in your project's package management setup.

What is Dependency Confusion?

Dependency confusion occurs when a package manager resolves a dependency from an unintended, less-trusted registry (usually public) instead of the intended private/internal one. Attackers exploit this by publishing malicious packages with the same names as your internal dependencies to public registries.

Common root causes:

  • Typosquatting: Importing
    reqests
    instead of
    requests
    (resolves from public registry)
  • Missing internal packages: Importing
    company-logging
    that doesn't exist internally, so the resolver falls back to public registries
  • Version preference: Internal
    company-requests@1.0.1
    vs public
    company-requests@1.0.2
    — resolver picks the newer public version

Quick Audit Checklist

Run through these checks to identify vulnerabilities:

  1. Registry Configuration: Are you mixing internal and public registries in the same resolution?
  2. Internal Namespaces: Do you have organization-specific package names (e.g.,
    @company/*
    ,
    company-*
    ,
    Company.*
    )?
  3. Fallback Behavior: Does your tooling fall back to public registries when internal packages aren't found?
  4. Version Pinning: Are versions pinned or locked, or do you allow wide ranges?
  5. Lockfile Integrity: Are lockfiles committed and enforced in CI?

Ecosystem-Specific Fixes

JavaScript/TypeScript (npm, Yarn, pnpm)

Problem: npm/yarn can resolve from multiple registries and pick the "best" version.

Fix: Bind internal scopes to private registry only.

.npmrc
(project-level):

# Bind internal scope to private registry; do not allow public fallback for @company/*
@company:registry=https://registry.corp.example/npm/
# Always authenticate to the private registry
//registry.corp.example/npm/:_authToken=${NPM_TOKEN}
strict-ssl=true

package.json
(for internal package):

{
  "name": "@company/api-client",
  "version": "1.2.3",
  "private": false,
  "publishConfig": {
    "registry": "https://registry.corp.example/npm/",
    "access": "restricted"
  }
}

Yarn Berry (

.yarnrc.yml
):

npmScopes:
  company:
    npmRegistryServer: "https://registry.corp.example/npm/"
    npmAlwaysAuth: true
# CI should fail if lockfile would change
enableImmutableInstalls: true

Operational tips:

  • Only publish internal packages within the
    @company
    scope
  • For third-party packages, allow public registry via your private proxy/mirror, not directly from clients
  • Use
    npm ci
    or
    yarn install --immutable
    in CI

Python (pip / Poetry)

Core rule: Don't use

--extra-index-url
to mix trust levels. Either expose a single internal index that proxies and caches approved PyPI packages, or use explicit index selection and hash pinning.

pip.conf
:

[global]
index-url = https://pypi.corp.example/simple
# Disallow source distributions when possible
only-binary = :all:
# Lock with hashes generated via pip-tools
require-hashes = true

Generate hashed requirements with pip-tools:

# From pyproject.toml or requirements.in
pip-compile --generate-hashes -o requirements.txt
pip install --require-hashes -r requirements.txt

If you must reach public PyPI, do it via your internal proxy and maintain an explicit allowlist there. Avoid

--extra-index-url
in CI.

.NET (NuGet)

Problem: Multiple package sources can be queried simultaneously.

Fix: Use Package Source Mapping to bind patterns to specific sources.

nuget.config
:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <add key="corp" value="https://nuget.corp.example/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
    <packageSource key="corp">
      <package pattern="Company.*" />
      <package pattern="Internal.Utilities" />
    </packageSource>
  </packageSourceMapping>
</configuration>

Java (Maven/Gradle)

Problem: POMs can declare arbitrary repositories.

Fix: Mirror all to internal, ban ad-hoc repos.

Maven

settings.xml
:

<settings>
  <mirrors>
    <mirror>
      <id>internal-mirror</id>
      <mirrorOf>*</mirrorOf>
      <url>https://maven.corp.example/repository/group</url>
    </mirror>
  </mirrors>
</settings>

Add Enforcer plugin to ban repositories in POMs:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>3.6.1</version>
  <executions>
    <execution>
      <id>enforce-no-repositories</id>
      <goals><goal>enforce</goal></goals>
      <configuration>
        <rules>
          <requireNoRepositories />
        </rules>
      </configuration>
    </execution>
  </executions>
</plugin>

Gradle: Centralize and lock dependencies.

settings.gradle.kts
:

dependencyResolutionManagement {
  repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
  repositories {
    maven { url = uri("https://maven.corp.example/repository/group") }
  }
}

Enable dependency verification and commit

gradle/verification-metadata.xml
.

Go Modules

Problem: Public proxy can resolve private module names.

Fix: Mark private paths to skip proxy.

# Use corporate proxy first, then public proxy as fallback
export GOPROXY=https://goproxy.corp.example,https://proxy.golang.org
# Mark private paths to skip proxy and checksum db
export GOPRIVATE=*.corp.example.com,github.com/your-org/*
export GONOSUMDB=*.corp.example.com,github.com/your-org/*

Rust (Cargo)

Problem: crates.io fallback for internal packages.

Fix: Replace crates-io with internal mirror.

.cargo/config.toml
:

[source.crates-io]
replace-with = "corp-mirror"

[source.corp-mirror]
registry = "https://crates-mirror.corp.example/index"

For publishing, be explicit with

--registry
and keep credentials scoped to the target registry.

Ruby (Bundler)

Problem: Multi-source Gemfiles can mix registries.

Fix: Use source blocks and disable multisource.

Gemfile
:

source "https://gems.corp.example"

source "https://rubygems.org" do
  gem "rails"
  gem "pg"
end

source "https://gems.corp.example" do
  gem "company-logging"
end

Enforce at config level:

bundle config set disable_multisource true

CI/CD Hardening

  • Single ingress: Use Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts as the only endpoint developers/CI can reach
  • Immutable lockfiles: Fail CI if lockfile would change
    • npm: commit
      package-lock.json
      , use
      npm ci
    • Yarn: commit
      yarn.lock
      , use
      yarn install --immutable
    • Python: commit hashed
      requirements.txt
      , enforce
      --require-hashes
    • Gradle: commit
      verification-metadata.xml
      and fail on unknown artifacts
  • Egress control: Block direct access from CI to public registries except via the approved proxy
  • Name reservation: Pre-register your internal names/namespaces in public registries where supported
  • Package provenance: When publishing public packages, enable provenance/attestations to make tampering more detectable

When to Use This Skill

Use this skill when:

  • Reviewing package configuration files (
    .npmrc
    ,
    pip.conf
    ,
    nuget.config
    ,
    settings.xml
    ,
    Gemfile
    , etc.)
  • Setting up a new project's dependency management
  • Auditing CI/CD pipelines for supply chain security
  • Investigating a potential dependency confusion incident
  • Wanting to harden your build environment against supply chain attacks
  • Configuring private registries or internal package management

References