Join our Newsletter — 33% off our NHI Course
Home› Guides› OWASP CI/CD Top 10 CICD-SEC-3 Dependency Chain Abuse…
Guide Software & AI Supply Chain

OWASP CI/CD Top 10 CICD-SEC-3 Dependency Chain Abuse Guide: Stopping Dependency Confusion and Typosquatting

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 26 October 2026 14 min read
On this page

A build that resolves dependencies from the public internet will run whatever code a registry hands it, often before any scanner has looked at it. CICD-SEC-3, Dependency Chain Abuse, is the third risk in the OWASP Top 10 CI/CD Security Risks. It is about how developer workstations and build environments fetch packages, not about known vulnerabilities in those packages, and it covers dependency confusion, dependency hijacking, typosquatting and brandjacking. This guide sets out what OWASP requires, translates each principle into package manager settings for npm and pip, explains the identity controls that stop a poisoned package from stealing pipeline credentials, and maps the risk to NIST, CIS, ISO, OpenSSF S2C2F and ATT&CK. It is for platform, build and AppSec engineers who own dependency resolution.

Key takeaways

  • The fetch process is the attack surface. OWASP defines the risk as abuse of flaws in how workstations and build environments fetch code dependencies, resulting in a malicious package being fetched and executed when pulled.
  • Install equals execute. Pre-install and post-install scripts run package code immediately, so a malicious package usually acts before tests, scans or review.
  • Route everything through an internal proxy. OWASP's first principle is that no client should fetch directly from the internet; a curated internal repository gives a control point and an investigation trail.
  • Pin, hash and scope. Lockfiles, hash checking, organisation scopes and committed package manager configuration close dependency confusion and most typosquatting paths.
  • Keep secrets away from install steps. Recent npm worms harvested CI credentials at install time; running installs in a context without secrets limits the blast radius when prevention fails.

What it is and who it applies to

OWASP notes that packages are fetched by a dedicated client per language, usually from a mix of self-managed repositories such as JFrog Artifactory and public SaaS registries such as npm, PyPI and RubyGems. Many organisations scan dependencies for known vulnerabilities, but OWASP argues that an equally important set of controls governs how dependencies are pulled. A misconfigured client can lead an engineer, or worse the build system, to download a malicious package instead of the intended one. OWASP lists four attack vectors:

VectorOWASP definition (paraphrased)Primary controlExample
Dependency confusionPublishing a public package with the same name as an internal one so clients pick the public copySingle trusted index, organisation scopes, internal namespace reservationAlex Birsan's 2021 research reaching more than 35 organisations
Dependency hijackingTaking over a maintainer account to publish a malicious version of a popular packageLockfiles, version pinning, release age delay, maintainer MFA and trusted publishingua-parser-js, coa and rc npm hijacks cited by OWASP
TyposquattingPublishing packages with names similar to popular ones, relying on misspellingCurated allowlist, malware scanning at the proxy, review of new dependenciesNo specific case cited by OWASP
BrandjackingPublishing packages that imitate a brand's naming conventionAllowlist by publisher or scope, provenance checksNo specific case cited by OWASP

The risk applies to any organisation that builds software with third-party packages, which in practice means all of them. It applies with most force to CI runners, because they hold deployment credentials and execute installs unattended. OWASP's impact statement names credential theft and lateral movement from the host that pulled the package, and malicious code reaching production through the build, often while the package keeps its expected functionality so detection is less likely. See the Malicious Package and Dependency Confusion Guide for the threat background; this page concentrates on the OWASP control set.

Structure and key requirements

OWASP accepts that mitigations are specific to each language client and proxy, but says all of them share the same guiding principles. The table turns each into concrete settings.

OWASP principlenpm implementationpip implementationVerification
Pull through an internal proxy, not the internetregistry= in a project .npmrc pointing at the internal repository--index-url (or index-url in pip.conf) pointing at the internal repositoryEgress from runners to public registries blocked; proxy logs show all fetches
Disallow direct external pulls; enforce client configurationCommit .npmrc in every repository; CI fails if registry differsNever use --extra-index-url for private packagesPolicy check on config files in pull requests
Checksum and signature verificationnpm ci with package-lock.json integrity hashes; registry signatures and provenance where available--require-hashes with sha256 hashes for every requirementBuilds fail on hash mismatch
Avoid "latest"; pin pre-vetted versionsExact versions in the lockfile; npm ci never rewrites itPin with ==; hash mode requires pinningNo floating ranges in production manifests
Register and reference private packages under the organisation scope@org/ scope, with @org:registry= mapped to the internal registryReserve internal names on the public index or use a prefix the proxy routes internallyProxy rule blocks public packages matching internal names
Separate context for install scripts, without secretsignore-scripts=true or an allowlist; install in a job without deployment secretsPrefer wheels with --only-binary :all: so no build scripts runInstall jobs have no secret or OIDC permissions
Do not publish internal project namesStrip package.json contents from public bundles and source mapsKeep internal requirements files out of public repositoriesSecret and name scanning on published artefacts
Detection, monitoring and hardeningProxy logging, malware scanning, and system hardening as described in CICD-SEC-7 Insecure System ConfigurationAlerts on new packages, new maintainers and install-time network calls

Package manager documentation supports these settings directly. The npm documentation states that npm ci requires an existing package-lock.json, exits with an error if it does not match package.json, and never writes to either file, which makes installs effectively frozen. Each npm user or organisation has its own scope and only they can add packages to it. The ignore-scripts setting stops npm running scripts from package.json files, and the before setting restricts installs to versions available on or before a given date; current npm documentation also describes a min-release-age setting expressed in days. The pip documentation states that, by default, pip performs no checks against remote tampering and runs arbitrary code from distributions, and that hash-checking mode is all or nothing: hashes are needed for every requirement and every dependency, and requirements must be pinned. It recommends sha256 and notes that hashes supplied by the index in download URLs are not a guard against tampering.

Birsan's research explains why the index setting matters. pip's --extra-index-url checks both the internal and the public index and installs the higher version, so a public package with an inflated version number wins. He found internal package names in package.json files embedded in public JavaScript, in leaked paths and in public repositories, and recommended --index-url instead.

Identity and NHI requirements

Dependency chain abuse is usually described as a code problem, but its outcomes are identity outcomes. On both sides of the registry, machine credentials decide the damage.

  • Consumer side, runner credentials: a malicious package runs with whatever the install step can reach. In the ChainDrop npm Worm, a preinstall script launched a payload that targeted npm, GitHub, cloud, Kubernetes and Vault credentials and, on GitHub Actions runners, read secrets from runner process memory. Install jobs should therefore receive no deployment secrets and no id-token: write permission; give those only to later jobs that consume vetted artefacts. See the CI/CD Pipeline Identity Security Guide.
  • Producer side, publishing identities: dependency hijacking is account takeover of a maintainer or a publishing token. npm and PyPI both support trusted publishing over OIDC, which replaces long-lived tokens; PyPI states that the API token it issues expires 15 minutes after creation. npm recommends that once trusted publishing works, packages are set to "Require two-factor authentication and disallow tokens". See the npm Tokens Security Guide.
  • Provenance is not identity assurance: the ChainDrop malicious release carried valid provenance because the attacker controlled a legitimate maintainer's account. Provenance shows where a build ran; it does not prove the identity behind the change was safe.
  • Proxy and registry service accounts: the internal repository's own credentials to upstream registries, and the CI identities that publish into it, are high-value NHIs. Give them write access only to the namespaces they own and review them with other pipeline identities.
  • Bot-driven updates: automated update tools need registry credentials; GitHub documents OIDC authentication for Dependabot to private registries so those credentials need not be stored as secrets.

The Shai-Hulud npm Worm shows both sides at once: stolen publishing tokens let the worm republish victims' packages, and its install-time payload harvested further tokens from developer machines and CI runners. See also the OWASP NHI Top 10 NHI7 Long-Lived Secrets Guide.

Implementation steps

  1. Inventory clients and sources (weeks 1 to 3). List every package manager in use, every configured index or registry, every place --extra-index-url or multiple registries appear, and every internal package name. Generate SBOMs for main products. See the SBOM Guide.
  2. Stand up or harden the internal proxy (weeks 2 to 8). Configure one virtual repository per ecosystem that serves internal packages and proxies public ones, with rules that refuse public packages whose names match internal ones. Enable logging and malware or reputation checks at the proxy.
  3. Claim namespaces (weeks 2 to 6). Move private npm packages under the organisation scope and map the scope to the internal registry. For ecosystems without scopes, reserve internal names on the public index or adopt a prefix the proxy routes internally only.
  4. Commit configuration and pin (weeks 4 to 12). Commit .npmrc and pip.conf or equivalent to each repository. Switch CI from npm install to npm ci; generate hashed, pinned requirements for Python. Pin GitHub Actions to full-length commit SHAs, which GitHub's guidance recommends.
  5. Pilot in audit mode (weeks 6 to 12). On a pilot group of repositories, log fetches that would fail the new rules without blocking. Review the list, add legitimate packages to the curated feed, then switch to enforce. Rollback: point the pilot repositories back at the previous registry configuration, kept in version control.
  6. Block egress (weeks 10 to 16). Once every repository resolves through the proxy, block runner and build network egress to public registries. This is the control that makes the proxy mandatory rather than advisory.
  7. Separate install from secrets (weeks 8 to 16). Restructure pipelines so dependency installation runs without secrets or cloud federation permissions; disable install scripts by default with a reviewed allowlist.
  8. Add a release age delay and monitoring (ongoing). Delay adoption of newly published versions for a few days where tooling supports it, alert on new direct dependencies and maintainer changes, and rehearse the response. See the Supply Chain Compromise Response Playbook.

Decision guidance

  • Proxy everything or curate an allowlist: a transparent proxy is quick to deploy and gives logging and name-collision rules; a curated feed of pre-vetted packages, which OpenSSF S2C2F calls enforcing a curated OSS feed (ENF-2), gives stronger assurance but needs an approval workflow. Most organisations start with the proxy and curate high-risk ecosystems.
  • Disable install scripts or isolate them: disabling scripts breaks some native packages; where that is unacceptable, run installs in an isolated job with no secrets and no network beyond the proxy.
  • Small teams: a single project .npmrc, lockfiles with npm ci, organisation scopes and pinned Actions deliver most of the benefit without new infrastructure.
  • Large estates: enforcement has to be central: proxy, egress rules and policy checks on configuration files, because per-team guidance drifts.

Evidence and assessment

Evidence itemSourceWhat good looks like
Registry configuration per repositoryCommitted .npmrc, pip.conf, nuget.config and policy check resultsAll point to the internal repository; no extra public indexes
Egress rules for build runnersFirewall or proxy policyPublic registries reachable only from the proxy
Lockfile and hash coverageRepository scanEvery production build uses a lockfile or hashed requirements
Namespace ownershipRegistry organisation and scope settingsAll internal packages scoped or reserved
Pipeline secret placementWorkflow definitionsNo secrets or OIDC permission in install jobs
Proxy logs and alertsSIEMFetches attributable to builds; alerts on blocked collisions and malware hits

Detection signals: requests for public packages matching internal names; first-seen packages or maintainers; versions published within hours of being pulled; outbound connections or DNS lookups from install steps; new lifecycle scripts in dependency updates; and credential use from runner IP ranges outside expected jobs. In ATT&CK v20 the activity maps to T1195.001 Compromise Software Dependencies and Development Tools, with follow-on T1059 Command and Scripting Interpreter and T1552.001 Credentials In Files.

Metrics:

  • Proxy coverage: share of builds resolving all packages through the internal repository.
  • Lockfile and hash coverage: share of production repositories using npm ci, hashed requirements or equivalent.
  • Namespace protection: internal package names that are scoped or reserved, against the total.
  • Secret-free install jobs: share of pipelines whose install step has no secrets or federation permissions.
  • Time to block: hours from a public malicious package advisory to the proxy denying it.

Mapping to other frameworks

FrameworkRelevant itemsHow CICD-SEC-3 maps
OpenSSF S2C2FING-1, ING-2, ING-3, SCA-4, INV-1, AUD-2, AUD-3, ENF-1, ENF-2Trusted package managers, binary repository manager, deny list, malware scanning, inventory, auditing the ingestion path, integrity validation, secure package source files, curated feed
NIST SP 800-53 Rev. 5SR-3, SR-4, SR-5, SR-11, SI-7, SI-7(15), CM-7(5), CM-8Supply chain controls, provenance, acquisition, component authenticity, integrity and code authentication, allow-by-exception software, component inventory
NIST CSF 2.0GV.SC-05, GV.SC-07, ID.AM-02, PR.PS-02, DE.CM-09Supply chain requirements and supplier risk, software inventory, software maintenance, monitoring of software and runtime environments
CIS Controls v8.12.5, 16.4, 16.5Allowlist authorised software, inventory of third-party components, up-to-date and trusted components
ISO/IEC 27001:2022 Annex A5.19, 5.21, 8.8, 8.25Supplier relationships, ICT supply chain, technical vulnerabilities, secure development life cycle
MITRE ATT&CK v20T1195.001, T1195.002, T1059, T1552.001Compromised dependencies and software supply chain, execution and credential theft that follow

For provenance and signing, see the SLSA and Build Provenance Guide; for the wider programme, see the Software Supply Chain Security Guide.

Common pitfalls

  • Using --extra-index-url for private packages. pip treats both indexes as equal and installs the highest version, the exact behaviour Birsan exploited.
  • A proxy that is optional. If runners can still reach public registries, one repository with a missing .npmrc bypasses every control at the proxy.
  • Running installs in the deploy job. The ChainDrop and Shai-Hulud payloads harvested secrets available at install time; anything in the job environment or runner memory is in scope.
  • Treating provenance as a trust verdict. Valid provenance from a hijacked maintainer account still describes a malicious build.
  • Vulnerability scanning mistaken for this control. SCA finds known CVEs; it does not stop a brand-new malicious package with no advisory from executing at install.
  • Hashing only some requirements. pip's documentation explains that partial hashing is of little use because a malicious dependency can enter through an unhashed line, which is why hash mode is all or nothing.

Practitioner checklist

  • Route every package fetch through an internal repository and block runner egress to public registries.
  • Commit package manager configuration to every repository and fail builds that resolve elsewhere.
  • Move private packages under organisation scopes or reserved names; refuse public packages that collide.
  • Use npm ci with lockfiles and pip hash-checking mode with pinned versions in CI.
  • Disable install scripts by default and run installs without secrets or OIDC permissions.
  • Pin CI actions and plugins to full-length commit SHAs.
  • Move package publishing to trusted publishing and disallow token publishing where supported.
  • Delay adoption of freshly published versions where tooling allows.
  • Alert on name collisions, first-seen packages and network activity during installs.
  • Keep an SBOM per release so exposure can be checked within hours of an advisory.

Standards and references

Related NHI Mgmt Group resources: Malicious Package and Dependency Confusion Guide · Top 10 CI/CD Security Risks · OWASP CI/CD Top 10 CICD-SEC-2 Inadequate Identity and Access Management Guide · OWASP CI/CD Top 10 CICD-SEC-9 Improper Artifact Integrity Validation Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 26 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org