Back to Cheat Sheets

📦 Insecure Third-Party Dependencies

OWASP Serverless Top 10 - SAS-6

CRITICAL RISK

📋 What Is It?

Insecure Third-Party Dependencies occur when a serverless function pulls in external code-npm, PyPI, Maven, or Gradle packages plus their transitive dependencies-that is vulnerable, malicious, unmaintained, or simply unaccounted for. A function is glue code: it parses an event, calls a managed service, and returns. To do that it drags in a tree of libraries the author never wrote and often never read. The serverless twist is where the dependency runs and what it inherits: a compromised library runs with the function's IAM execution role, its environment variables (often holding secrets), and its network egress-so one bad transitive package can read secrets and pivot across the account.

SAS-6 OWASP Rank
80%+ Code Is 3rd-Party
Transitive Danger Zone

⚠️ Common Exploits

  • Known CVE in a Bundled Dep: Crafted input triggers a public advisory in a parser/deserializer for RCE
  • Typosquatting: crossenv vs cross-env, reqeusts vs requests
  • Dependency Confusion: Attacker publishes your internal package name on the public registry at a higher version
  • Maintainer/Account Hijack: Malicious release hidden in a fresh transitive dependency
  • Install-Time Script: postinstall runs attacker code on the CI/CD host
  • Runtime Credential Theft: An imported module reads env vars + the container credential endpoint
  • Stale Shared Layer: One vulnerable library exploits an entire fleet of functions

🔴 Attack Flow

1. Get code into the function
(known CVE, typosquat, hijack, or confusion)
↓
2. Execute in the function's context
(at import, via install script, or vuln path)
↓
3. Harvest ambient credentials
(env vars + container credential endpoint)
↓
4. Pivot with the over-privileged role
(S3, DynamoDB, AssumeRole)
↓
5. IMPACT: One bad dep becomes an account breach!

❌ Vulnerable Code

# package.json - floating ranges + a build-time script that runs anything { "name": "order-fn", "dependencies": { "left-pad": "*", // whatever resolves - no ceiling "some-parser": "^1.0.0", // silently accepts a hijacked 1.9.9 "aws-sdk": "latest" // non-deterministic across builds }, "scripts": { "postinstall": "node ./setup.js" // arbitrary code on every install } } # requirements.txt - unpinned, no hashes requests pyyaml>=3 some-utils # name never verified; a typo installs an impostor # serverless.yml - the function role is a skeleton key provider: iam: role: statements: - Effect: Allow Action: "*" ← a bad dep can do ANYTHING Resource: "*" environment: DB_PASSWORD: ${env:DB_PASSWORD} ← plaintext env any module can read runtime: python3.7 ← deprecated / unpatched runtime

✅ Secure Code

# package.json - exact versions, no floating "latest", scripts controlled in CI { "name": "order-fn", "dependencies": { "some-parser": "1.4.2", // exact version, chosen deliberately "@aws-sdk/client-dynamodb": "3.658.1" } // no lifecycle scripts; CI installs with --ignore-scripts } # requirements.txt - pinned AND hash-verified (install fails if a hash mismatches) requests==2.32.3 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 # CI: deterministic install, no lifecycle scripts, scan gates the deploy - run: npm ci --ignore-scripts # from committed lockfile, hashed - run: npm audit --audit-level=high # fail build on known CVEs - run: npx snyk test --severity-threshold=high - run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json - run: grype sbom:sbom.json --fail-on high - run: npx serverless deploy # only if every gate passed # serverless.yml - least privilege bounds the blast radius provider: iam: role: statements: - Effect: Allow Action: ["dynamodb:GetItem"] # only what it needs Resource: "arn:aws:dynamodb:us-east-1:123456789012:table/Orders" runtime: python3.12 # current, patched runtime

✓ Prevention Checklist

  • Generate an SBOM per function & layer, every build
  • Gate CI on SCA (npm audit / pip-audit / Snyk / Grype)
  • Re-scan deployed artifacts on a schedule
  • Commit lockfiles with integrity hashes
  • Install with npm ci / pip --require-hashes
  • Minimize the tree; prefer stdlib over micro-packages
  • Pull from a trusted, scoped registry (stop confusion)
  • Disable install scripts (--ignore-scripts)
  • Scan Lambda layers & container images, not just manifests
  • Keep functions on a supported, patched runtime
  • Automate update PRs (Dependabot / Renovate)
  • Least-privilege role + monitored egress

🔍 Detection & Tools

SCA & Scanning:

npm audit pip-audit Snyk OWASP Dependency-Check Grype Trivy

Inventory & Updates:

CycloneDX Syft (SBOM) Dependabot Renovate npm ls / pipdeptree

How to Test:

  • Run SCA against the manifest AND the built artifact/layer
  • Diff SBOMs between releases for new transitive deps
  • Check for floating ranges (*, latest, ^) in manifests
  • Confirm a lockfile is committed and CI uses npm ci
  • Look for lifecycle scripts (postinstall) and native builds
  • Verify the runtime version is still supported

🌍 Real-World

Described as incident classes-repeatedly observed patterns-because the durable lesson is the pattern, not any single advisory:

  • Malicious npm Package in the Tree (event-stream class): A low-attention package changes maintainership; malicious code is buried in a fresh transitive dep and pulled automatically by floating ranges with no lockfile.
  • Typosquatting & Dependency-Confusion Waves: Lookalike or internal-name packages on the public registry ship credential-stealing payloads via install scripts-on build hosts and in the artifact.
  • Unpatched Known-Vulnerable Library in a Shared Layer: A stale, unscanned layer bundles a parsing library with a public advisory; every function attached inherits the vulnerable version.
  • Trojanized Update to a Low-Attention Transitive Dep: A tiny utility three levels down-that nobody named or watches-is hijacked.

📌 Quick Tips

  • DO NOT use floating ranges (*, latest) in prod
  • DO NOT run install scripts unreviewed in CI
  • DO NOT ship a wildcard IAM role with your deps
  • DO pin + hash-verify from a committed lockfile
  • DO gate every build on SCA and an SBOM scan
  • DO scan layers and keep runtimes current
  • DO minimize the tree and monitor egress

📜 Compliance

Related Standards:

  • OWASP Top 10 - Vulnerable & Outdated Components
  • NIST SSDF / SBOM (EO 14028)
  • PCI-DSS Requirement 6.3 - Known Vulnerabilities
  • SOC 2 CC7.1
  • CycloneDX / SPDX SBOM Standards