Web › Module 3 › Lesson 1
Dependencies as Attack Surface
A03:2025 — inventory deps YOU own.
Visual · deps_attack_surface
Software Supply Chain Failures (A03:2025): Inventory packages you own — do not hydra the LAN.
Opening
You did not write the vulnerability — you installed it. That is still your risk.
OWASP Top 10:2025 elevates Software Supply Chain Failures as A03: compromised packages, poisoned pipelines, unsigned updates, and blind trust in registries. Attackers aim at maintainers, typosquat names, or CI secrets so victims pull malicious code through normal install. Your goal as a defender: know what you depend on, pin what you trust, verify what you can. This is ORIGINAL Cyberlium teaching — attack literacy first.
1. A03 in one sentence: trust in someone else’s code or build was misplaced
Supply chain failure means the integrity or authenticity of software you consume (libraries, containers, plugins, CI actions) was broken — or never established. Attacker goals: run code in your build or runtime, steal secrets from CI, persist via updates. Victims often “just npm installed” or “just docker pulled.” Finding language: “Unpinned deps; no SBOM; CI can publish with overbroad token.” Fix language: “Inventory; pin; verify checksums/signatures when available; least privilege in CI; review diffs on upgrades.”
Command guide
A03 Supply chain — A03 in one sentence
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl
macOS: Built-in
Windows: Built-in (PowerShell: Invoke-WebRequest)
═══ COMMANDS ═══
Command — copy this
SAFE="http://127.0.0.1:8770"
Command — copy this
curl -sS -m 3 -I "$SAFE/" | head -n 12
2. Direct vs transitive: the graph you did not read
Direct dependencies are what you declared. Transitive ones arrive because those packages depend on others. Attackers love deep graphs: one compromised leaf reaches thousands of apps. Literacy: generate a lockfile/tree for a project YOU own (pip freeze, npm ls --depth=0) and notice how wide it is. Do not “prove A03” by uploading malware to a public registry.
Command guide
A03 Supply chain — Direct vs transitive
═══ COMMANDS ═══
Command — copy this
ls -1 package-lock.json yarn.lock pnpm-lock.yaml requirements.txt poetry.lock go.sum Cargo.lock ls -1 "$HOME/cyberlium-lab"/*lock* find "$HOME/cyberlium-lab" . -maxdepth 3 \( -name "package-lock.json" -o -name "requirements.txt" -o -name "go.sum" -o -name "poetry.lock" \) | head -n 20
3. Typosquats and abandoned packages — named risks, not a how-to
Lookalike names and unmaintained packages are common failure stories. Defender habits: spell package names carefully; prefer maintained projects; watch sudden maintainer changes; read release notes on bumps. This course does not teach how to publish malicious lookalikes. Naming the risk is enough.
Command guide
A03 Supply chain — Typosquats and abandoned packages - named risks, not a how-to
═══ COMMANDS ═══
Command — copy this
printf "typosquat_named: lookalike names abandoned_named: unmaintained with old CVEs refuse: poisoning registries " >> "$HOME/cyberlium-lab/a03-deps-mid-h3.txt"
4. What you ship before SBOM lesson
Start an inventory habit: lockfiles committed; dependency review in PRs; no blind latest tags in production. Secrets out of install scripts. CI tokens scoped. Identify DEMO first so writeups use http://192.168.0.1/ as the demo asset (or note SAFE if that IP is a router). Record the habit in notes even if your toy project is tiny.
5. What you record
Date (UTC). A03 = Software Supply Chain Failures (OWASP Top 10:2025). Identify banner of http://192.168.0.1/ or STOP if router. Direct vs transitive one line. pip freeze / npm ls snippet (redacted). Ethics: NEVER publish malware packages; NEVER hydra/nmap the LAN. Path: $HOME/cyberlium-lab/a03-deps-notes.txt, chmod 600. Legal: original Cyberlium — not official OWASP certification.
6. Wrong vs right: poisoning registries vs inventory you own
Worked failure — same word “supply chain,” opposite action. Right never needs a malicious publish.
Wrong
Typosquat a popular name. Hydra 192.168.0.1. Steal CI tokens as “research.” Install random unknown packages to “see what happens.”
Right
Identify DEMO with curl -I; list deps on a project you own; lock a03-deps-notes.txt chmod 600. Next: SBOM Pinning and Trust Boundaries.
If you have a local package.json/requirements.txt/pubspec.yaml you own, copy a redacted name list into notes. Otherwise create a tiny toy manifest under cyberlium-lab. Identify DEMO first.
Command guide
a03_deps_inventory.sh — DEMO curl -I + list YOUR toy deps
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install curl sudo apt install nmap sudo apt install python3
macOS:
Command — copy this
brew install nmap brew install python3
Windows: Built-in (PowerShell: Invoke-WebRequest)
Command — copy this
choco install nmap # or download https://nmap.org/download.html
Download https://python.org/downloads/
═══ COMMANDS ═══
Command — copy this
cd "$HOME/cyberlium-lab/a03-toy"
Command — copy this
cat > requirements-toy.txt << 'REQ' demo-left-pad==1.0.0 demo-http-client==2.3.1 REQ
Command — copy this
cat > list_deps.py << 'PY'
from pathlib import Path
text = Path("requirements-toy.txt").read_text(encoding="utf-8")
lines = [l.strip() for l in text.splitlines() if l.strip() and not l.startswith("#")]
print("direct_deps_count", len(lines))
for l in lines:
print("dep:", l)
print("a03: dependencies are attack surface you chose to trust")
print("ethics: NEVER publish typosquats / malware packages; NEVER hydra/nmap the LAN")
print("legal: original Cyberlium — not official OWASP certification")
PYCommand — copy this
python3 list_deps.py || python list_deps.py
Command — copy this
(pip freeze || pip3 freeze || true) | head -n 15
Command — copy this
cat > a03_optional_echo.py << 'PY'
"""Optional identify echo. Bind loopback only."""
from http.server import BaseHTTPRequestHandler, HTTPServer
HOST = "127.0.0.1"
PORT = 8770
if HOST != "127.0.0.1":
raise SystemExit("refusing non-loopback bind")
class H(BaseHTTPRequestHandler):
def do_GET(self):
body = b"Cyberlium A03 inventory lab. DEMO writeup: http://192.168.0.1/
"
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
print("optional bind", HOST, PORT)
HTTPServer((HOST, PORT), H).serve_forever()
PYCommand — copy this
cat > a03_deps_practical.sh << 'SH' SH
Command — copy this
{Mission: a03-deps-notes.txt in cyberlium-lab (mode 600)
1) curl -sS -I http://192.168.0.1/ —2) Inventory a toy or owned project dependency list (pip freeze / npm ls / toy manifest). 3) Fill $HOME/cyberlium-lab/a03-deps-notes.txt, chmod 600. No malicious publishes.
Stuck? Ask Cyberlium AI Mentor
If “supply chain only counts if I compromise a package” still feels true, ask for a hint — not a typosquat guide. Try: "Hint only: why deps are attack surface, which curl -I identifies MY lab vs a router, and where locked a03-deps-notes.txt lives?"
You now treat dependencies as A03 attack surface — identify the demo, inventory first, no malicious publishes — with locked notes. Original Cyberlium — not official OWASP certification. Next — SBOM Pinning and Trust Boundaries.
Knowledge Check
APPLY: Your app has 8 direct deps and 140 transitive. What A03 literacy follows?
Multiple choice
Knowledge Check
APPLY: True or False: “npm install latest” on every build is fine because registries are always safe.
True or False
Knowledge Check
APPLY: curl http://192.168.0.1/ shows a Netgear Router Admin page. What do you do?
Multiple choice