Skip to content

Back to the catalog

Episode 3: Malicious Dependencies Aren't an Accident
youtu.bevideo

Episode 3: Malicious Dependencies Aren't an Accident

Tanya Janca analyzes the deliberate nature of malicious dependency attacks, demonstrating how threat actors use typosquatting and copied documentation to quietly exfiltrate cloud credentials. She outlines a practical four-step defense strategy to add intentional workflow friction, enforce pull request reviews, and validate AI-suggested packages.

TL;DR Tanya Janca analyzes the deliberate nature of malicious dependency attacks, demonstrating how threat actors use typosquatting and copied documentation to quietly exfiltrate cloud credentials.
Document

Overview

In this episode of the DevSec Station podcast (Episode 3), host Tanya Janca (also known as SheHacksPurple) addresses the growing threat of malicious dependencies in software supply chains. Rather than resulting from accidental uploads or software zero-days, these attacks represent deliberate social engineering campaigns aimed at developer trust and speed. Janca breaks down how attackers mimic package names, replicate documentation, and silently exfiltrate environment variables and cloud credentials. She critiques passive approaches that rely entirely on developer vigilance and provides a practical, four-step mitigation model designed to introduce intentional process friction into code repositories without impeding developer productivity.


Contents

0:00 Credential Theft via Package Typosquatting

The speaker opens with a real-world scenario illustrating how package managers can be leveraged to steal sensitive credentials:

  • Attack Nature: Amazon Web Services (AWS) credentials were stolen through a package manager without exploiting zero-day vulnerabilities or system bugs.
  • Attack Mechanism: The compromise relied entirely on a developer installing a package with a misspelled or slightly altered package name.
  • Frequency: The speaker stresses that typosquatting and dependency confusion attacks occur significantly more frequently than most engineers assume.

0:20 Introduction and Podcast Overview

  • Host Identification: Tanya Janca, also known as SheHacksPurple (0:22).
  • Show Purpose: DevSec Station is a podcast tailored for software developers aiming to write more secure code.
  • Format: Short, practical lessons covering secure coding, software security, and architecture without slowing down development cycles. No prerequisites or prior episode knowledge are required.

0:48 Sponsor Spotlight: Mayze

The speaker introduces episode sponsor Mayze (0:50):

  • Industry Pain Point: Modern vulnerability scanners and cloud security posture tools generate high volumes of "critical" alerts, overwhelming development and security teams.
  • Solution: Mayze utilizes AI agents to investigate vulnerabilities in context, determining whether an issue is genuinely exploitable in the target runtime environment.
  • Remediation: The platform generates and prioritizes consolidated fixes capable of addressing multiple vulnerabilities simultaneously (mayzehq.com/devsec shown on screen at 1:28).

1:31 The Myth of Accidental Dependencies

The speaker targets developers who frequently install third-party packages, rely on package manager autocompletion, copy-paste install commands from Stack Overflow, or accept package recommendations from AI coding assistants.

Common Developer Behaviors:
├── Autocompleting package names in package managers
├── Copying installation commands from Stack Overflow
└── Accepting dependency recommendations directly from AI assistants
  • The Myth: Malicious dependencies are rare anomalies or accidental uploads where someone unintentionally published flawed code.
  • The Reality: Malicious dependencies are intentional attacks (2:02). Threat actors carefully craft package names, calculate release timing strategically, and construct packages explicitly designed to blend seamlessly into open-source ecosystems to socially engineer developers.

2:27 Anatomy of a Malicious Dependency Attack

The attack lifecycle proceeds through specific operational stages:

  1. Target Identification: An attacker identifies popular public packages, known internal organizational package names, or common developer spelling errors.
  2. Name Crafting: If the target legitimate package is named aws-helper, the adversary might register aws-helpers (pluralization) or aws_helper (delimiter variation) (2:44). In dependency confusion attacks, the adversary registers an internal private package name on a public registry prioritized by developer build tooling.
  3. Deceptive Packaging: The package includes a copied, authentic README file. The description matches the genuine library.
  4. Silent Execution: Upon installation, the package executes pre-install or initialization hooks. It inspects local environment variables to extract sensitive secrets: AWS access and secret keys GitHub personal access tokens Continuous Integration (CI) service credentials It exfiltrates the collected data to an external command-and-control server.
  5. Absence of Indicators: The application does not crash and builds cleanly. No error alerts or visible malfunctions are triggered, leaving the compromise unnoticed.

3:33 Flawed Approaches vs. Workflow Friction

The speaker highlights that modern developer ecosystems make these errors trivially easy to commit. She contrasts three security responses:

ApproachDescriptionVulnerability / Failure Mode
Bad Approach: Blind Trust (3:50)Trusting packages based on familiar-sounding names, clean installations, or plausible documentation.Names and documentation are cheap to counterfeit; attackers purposefully emulate expected names.
Better Approach: Developer Vigilance (4:13)Instructing developers to slow down, scrutinize spelling, read docs, and rely on caution.Relies on individual memory and willpower, which inevitably fail when engineers are rushed, fatigued, or under deadline pressure.
Best Approach: Systemic Friction (4:52)Inserting deliberate, automated checkpoints at the exact moment a dependency is introduced.Transfers responsibility from human cognitive load to organizational systems and tooling.

5:22 Action Plan: 4 Steps to Secure Dependency Ingestion

To defend against malicious dependencies, the speaker provides a concrete implementation plan centered on locking down dependency entry points:

The following sequence illustrates the enforcement barrier required when introducing third-party packages:

flowchart TD
    A[Developer Adds Dependency] --> B{Entry Mechanism}
    B -- Direct commit / Unreviewed --> C[HIGH RISK: Malicious package executes]
    B -- Pull Request --> D[Independent Human Code Review]
    D --> E{Lightweight Check}
    E -- SCA Policy / Bot / Checklist --> F[Verify Package Name & Registry Source]
    F -- AI-Generated Suggestion? --> G[Treat as Untrusted Input: Manual Validation]
    G --> H[Safe Ingestion / Merge]

Step 1: Select a Repository (5:37)

Choose a single repository currently under active, regular development rather than attempting an immediate organization-wide overhaul.

Step 2: Establish Ingestion Controls (5:40)

  • Audit the current method by which dependencies are added.
  • Mandate Pull Requests: Eliminate direct commits of dependency manifests. Enforce that every new dependency is introduced via a pull request (PR) requiring explicit approval from at least one peer reviewer other than the author (6:00).

Step 3: Implement an Automated Workflow Check (6:06)

Integrate at least one automated, lightweight barrier into the pull request pipeline:

  • A CI script that parses manifest files and flags newly added dependencies.
  • A Software Composition Analysis (SCA) policy that raises warnings on unvetted or novel packages.
  • A PR template checklist item requiring explicit verification: "Is this dependency name spelled exactly as expected?" (6:22).

Step 4: Treat AI Package Suggestions as Untrusted Input (6:28)

  • Never install libraries suggested by AI coding tools without independent manual confirmation.
  • Verify both the exact name and the package registry source. Assume that AI hallucinations or poisoned suggestions may introduce vulnerable or malicious packages.

6:56 Exploiting Trust and Speed

  • Core Vulnerability: Malicious dependency attacks succeed because they exploit developer trust and development velocity, not developer apathy.
  • Strategic Objective: Adding seconds of structured process pause at high-risk moments drastically diminishes the window for malicious code ingestion. The pause does not slow down developers—it slows down attackers (7:19).

7:22 Conclusion and Contact Information

  • Viewers are encouraged to subscribe, leave reviews, and share the episode.
  • Tanya Janca provides secure coding training for software developers.
  • Web Resource: shehackspurple.ca (7:44).

Data & Visuals Index

TimestampTypeDescription
0:24On-screen TextEpisode title: "DevSec Station Episode 3" and speaker credit: "I'm Tanya Janca AKA SheHacksPurple".
0:50On-screen TextSponsor identification: "Sponsored by Mayze".
1:28On-screen URLSponsor website display: mayzehq.com/devsec.
1:32On-screen TextSection header: "This episode is about malicious dependencies".
2:02On-screen TextClaim statement: "Malicious dependencies are intentional".
2:19On-screen TextConcept label: "This is threat actors targeting developers directly".
2:27On-screen TextConcept label: "What this attack looks like".
2:56On-screen TextStage label: "The package looks fine...".
3:09On-screen TextStage label: "The attack unfolds".
3:17On-screen TextStage label: "Then it exfiltrates your secrets and data".
3:33On-screen TextThesis label: "The ecosystem makes it easy to make this mistake".
3:48On-screen TextStrategy comparison: "Bad Approach: just trust".
4:13On-screen TextStrategy comparison: "Better Approach: Slow down and be more careful".
4:29On-screen TextStrategy evaluation: "It's so easy to get wrong".
4:52On-screen TextStrategy comparison: "The Best Approach: Add friction when the decision happens".
5:01On-screen TextArchitectural guideline: "Systems that make it harder to make a mistake".
5:22On-screen TextAction trigger: "If you do just one thing... Lock down how dependencies are introduced".
5:37On-screen TextAction list: "Step 1: Choose a repo".
5:40On-screen TextAction list: "Step 2: Figure out how dependencies are added".
5:57On-screen TextPolicy statement: "New dependencies must be added through a pull request, with approval".
6:06On-screen TextAction list: "Step 3: Add one check to your workflow".
6:28On-screen TextAction list: "Step 4: Treat AI dependency suggestions as untrusted".
6:56On-screen TextConclusion statement: "Malicious dependencies exploit trust and speed".
7:44On-screen URLEducational resource: shehackspurple.ca.

Key Takeaways

  • Targeted Social Engineering: Malicious packages are engineered deliberately to deceive developers via typosquatting, naming conventions, and mirrored documentation.
  • Silent Secret Harvesting: Compromised dependencies typically do not break builds or throw errors; they focus on reading environment variables to exfiltrate cloud and CI tokens.
  • The Failure of Willpower: Telling engineers to "be more careful" does not work under tight release deadlines or fatigue. Security must be built into systems, not human memory.
  • Enforced Peer Review: Direct addition of dependencies must be blocked. Every dependency change must pass through a pull request approved by an independent human reviewer.
  • Workflow Checkpoints: Automated gates—such as CI notification scripts, SCA policies, or explicit pull request checklist questions—provide the necessary pause before merging.
  • Zero Trust for AI Suggestions: Package suggestions generated by AI coding tools must be treated as unvetted inputs and manually validated for naming accuracy and authentic origin.

Transcript

Englishen6.2k chars
Let me tell you about a package manager that stole AWS credentials. It didn't use a zero-day. It didn't exploit a vulnerability. It relied on one thing: someone installing the wrong package name. And yes, that happens way more often than you think. Hi! I'm Tanya Janca, also known as SheHacksPurple. Welcome to DevSec Station, a podcast for software developers who want to build more secure software. In each episode, I'll share a short, practical lesson about secure coding, software security, and how to build safer systems without slowing development down. You can jump in at any episode, at any time, no homework required. This episode is sponsored by Maze. One of the biggest problems in security right now is that every vulnerability or cloud scanner says everything is critical, and honestly, no one has time for that. Maze uses AI agents to investigate vulnerabilities in context, so you can focus on the issues that are actually exploitable in your environment and not just theoretically scary. Their AI agents also generate and prioritize fixes that knock out multiple vulnerabilities at once, which is honestly the kind of scaling that security teams really need right now. Learn more about Maze at mazehq.com/devsec. If you install dependencies regularly, use auto-complete in your package manager, copy install commands from Stack Overflow, or let AI suggest libraries to you, this episode is definitely for you. There's a myth that malicious dependencies are rare occasions, they're accidents. Someone accidentally uploaded something bad, and whoops, here we are. But that is not what is happening right now. Most malicious dependencies are intentionally created. They are named very carefully. Their release is timed strategically. They are absolutely 100% designed to blend in. None of this is random. This is threat actors socially engineering software developers every single day. So here's how this usually works. An attacker looks for popular packages, internal package names, or commonly mistyped names. So maybe the real package is called aws-helper, so they publish aws-helpers, or aws_helper, or they upload a package with the same name to a public registry that your tooling prefers. The package looks fine, the README is copied over so it's a perfect copy, the description sounds super legit, and then you install it. What the package does next is quiet. It reads your environment variables, it grabs the AWS keys, the GitHub token, the CI credentials, whatever, and then it sends them to someone else. Nothing in your app visibly breaks, the app still works, there are no errors, there's no alerts, except now your credentials are in the wrong hands. And here's the very important part. This didn't happen because you were reckless or careless. It happened because the ecosystem we work in makes it very, very easy to trust the wrong thing. So how do we fix this? A bad approach, which I'm seeing a lot of, is trusting dependencies based on name recognition. "It looks right, it sounds right, it installs cleanly, I'm sure it's fine." This approach fails because names are cheap, and attackers know exactly which ones developers expect to see. It's easy for them to fake this. A better approach might be telling developers to slow down and be more careful. You should double-check the name, you should read the README, you should trust your instincts. This might help a bit, but it still relies on attention to detail, memory, and perfect judgment. It relies on us having a lot of willpower, and that's usually a losing proposition. And when we're busy or tired or we have a deadline, that's exactly when mistakes happen. That's when they happen to me. So the best approach we could take is adding intentional friction at the moment where a dependency is being added. So that means systems that make it harder to install the wrong thing and easier for us to notice when something's not quite right. When a pause is built into our workflow, developers don't have to remember to be cautious; the system just does it for them. It literally reminds them to do it. If you do just one thing after this episode, please do this: lock down how new dependencies are introduced into your project. So you can choose, but here's a practical way to do this. So step one: pick one repo that you are working on regularly. Step two: look at how you and your team add dependencies. How are you currently adding them? Can anyone add a new dependency directly, or does it go through a pull request with a review? If it's not already required, make this change: new dependencies must be added through a pull request and reviewed by at least one other human. So if you add it, you can't review it, someone else needs to. Step three: add one lightweight check. It could be a script that flags new dependencies in PRs, an SCA policy that highlights new packages, or even a simple checklist item in your PR template that says, "Is this dependency name exactly what you expected?" Even that little reminder can help. Okay, so now step four: if you use AI coding assistants, treat dependency suggestions as untrusted input and never install directly from an AI suggestion without double-checking the package name and the source. Assume there might be a problem every single time. You don't need to fix your entire supply chain today, but we want to add friction at that moment where the mistake is most likely to happen. Malicious dependencies are working because they exploit trust and speed. It's not because developers don't care about security. If we can add small pauses at high-risk moments, we can dramatically reduce the chances of something bad slipping through. This isn't about slowing developers down—the pause is just a few seconds. It's about slowing attackers down. Thanks for listening to DevSec Station! If you enjoyed this episode, please subscribe, share it with a friend, or leave a review. It helps more people discover the show. If you'd like to learn more, I'm Tanya Janca, also known as SheHacksPurple, and I teach secure coding training for software developers. You can find me online at shehackspurple.ca. Thank you for being here!

Organisations named here

  • DevSec Station
  • Maze
  • Tanya Janca (SheHacksPurple)

Technologies named here

  • AWS
  • GitHub
  • Maze
  • Software Composition Analysis
  • Maze: AI-agent vulnerability investigation and remediation prioritization platform

Techniques named here

  • Package typosquatting and delimiter variation
  • Dependency confusion via public registries
  • Typosquatting public and internal package names