Supply-chain reality check: package-squatting + CI/OIDC abuse are the fastest routes into your cloud

By Ash K
Supply-chain reality check: package-squatting + CI/OIDC abuse are the fastest routes into your cloud

Two converging attack paths

  1. Package squatting / dependency confusion: Adversaries publish near-name or higher-version packages to public registries (npm/PyPI). CI/dev machines resolve to the malicious package, executing install scripts that exfiltrate tokens or modify build output.
  2. CI OIDC abuse: With repo takeover (stolen token, maintainer account, or dependency hijack), attackers request cloud creds via OIDC federation (e.g., GitHub → AWS/GCP/Azure). Misconfigured trust policies (broad aud/subject claims) let arbitrary workflows assume powerful roles.

Red flags in telemetry

  • Build time anomalies: unexplained preinstall/postinstall scripts; outbound connections during npm i / pip install.
  • Registry resolution: packages sourced from public registry when an internal mirror is expected.
  • OIDC claims: Cloud STS logs showing issuers like https://token.actions.githubusercontent.com with overly broad sub patterns (e.g., repo wildcard) or missing aud pinning.

Hunting starters

# Cloud audit (AWS example)
CloudTrail
| filter eventName = "AssumeRoleWithWebIdentity"
| fields eventTime, requestParameters.roleArn, requestParameters.audience, requestParameters.subjectFromWebIdentityToken, sourceIPAddress
# GitHub Actions
"Workflow job run attempted to access OIDC token" events with unexpected repository, environment, or branch.
# Egress during package install (EDR/Proxy)
NetworkEvents
| where InitiatingProcessCommandLine has_any ("npm install","pip install","python -m pip")
| where RemoteUrl not in AllowListedRepos

Hardening that actually works

  1. Private registries & pinning: Route builds through an internal artifact proxy; require namespace/owner allow-lists; pin by digest (SRI/lockfiles).
  2. Provenance & signing: Enforce Sigstore/cosign for release artifacts; verify provenance in CI (SLSA level targets).
  3. Deny default OIDC: Cloud roles must restrict iss to GitHub’s issuer, aud to a custom value, and sub to the exact repo:org/name:ref:branch:environment.
  4. Least-privilege CI roles: Separate read-only build roles from deploy roles; use short-lived credentials and environment-level approvals.
  5. Dependency policy: Ban install scripts by default; require security review to enable. Alert on new maintainers/owners for critical packages.
  6. SBOM everywhere: Generate SBOMs for each build (SPDX/CycloneDX) and scan for unapproved packages before promotion.

30-day engineering plan

  • Days 1–7: Turn on private registry proxy; freeze lockfiles; block install scripts; audit top 50 packages for maintainer churn.
  • Days 8–15: Tighten OIDC trust policies; add aud pinning; restrict sub to exact repo+env; rotate CI secrets.
  • Days 16–23: Add provenance checks (cosign, SLSA provenance); enforce signature verification in pipelines.
  • Days 24–30: Split deploy roles; implement break-glass process; add detections for AssumeRoleWithWebIdentity spikes and unapproved registry egress.

Bottom line: Treat your build system as production. If a stranger can publish your dependencies or mint your cloud tokens, they can ship to your customers.

Ash K
Ash K
Ashton is a seasoned Cybersecurity Professional with over 25 years of experience in Cybersecurity Research, Cybersecurity Incident response, Products and Security Solutions architecture.