AI Coding Agents Are Now a Supply Chain Attack Vector

Three systems asserted a condition and none of them checked whether it still held. A registry reported a package was attested. An evaluation harness reported a model was offline. An assistant reported a package would work.

José Palanco José Palanco
Last Updated:
10 min read
Share
AI Coding Agents Are Now a Supply Chain Attack Vector

Beyond ASPM

Proof-Driven AppSec for teams building with AI

Plexicus uses AI Swarm Pentest to explore authorized application paths, validate what is exploitable, and give teams evidence they can use to prioritize remediation.

Explore AI Swarm Pentest

On 8 October 2026, an npm package called tensorlake was published with a valid provenance attestation. The attestation was correct. The package was malware, and it had just taken GitHub tokens, cloud keys, Kubernetes secrets and SSH keys off the machines of anyone who installed it.

Your supply chain policy probably says something reassuring. Install packages with provenance. Trust signed releases. Rely on the maintainer’s reputation. Every one of those controls worked perfectly on 8 October, and the malware arrived anyway.

What actually happened

The first malicious commit landed on main of tensorlakeai/tensorlake at 01

UTC on 7 October, pushed under a maintainer’s identity. No pull request was opened. Seven more commits followed, adjusting the payload and adding a preinstall line to package.json. At 01
UTC on 8 October the repository’s own release workflow published 0.5.144 to npm, and the files in the npm package were identical to those on main.

Installing it triggered the preinstall hook, which fetched the Bun runtime and executed an obfuscated 856 KB payload. The payload skipped CI environments, so developer laptops were the target. It collected GitHub and npm tokens, cloud credentials, Kubernetes and Vault secrets, SSH keys, saved browser logins, and the configuration files AI tools such as Claude, Cursor and Windsurf keep on disk. It then wrote .claude/settings.json and .vscode/tasks.json into any repository it could reach, so the payload re-armed every time somebody opened the project in an AI coding assistant or an editor.

The malware also installed a service called gh-token-monitor that checked the stolen GitHub token every 60 seconds for up to 24 hours. If the token was revoked, the service was built to wipe the machine.

Revoking a compromised credential is the first thing every incident playbook tells you to do. Here, it was the trigger.

The attestation passed

This is the part that should change how you write your policy.

An npm provenance attestation answers one question: was this package built from this repository, by this workflow, using this identity. It is a statement about provenance. It says nothing about whether the code is safe.

The attacker did not defeat the attestation. They satisfied it, by publishing from the genuine repository through the genuine workflow under the genuine maintainer’s identity. The check returned a clean result because the clean result was true. StepSecurity said it plainly: a policy that trusts provenance would have let this package through.

The same applies to the rest of the stack. Signed releases prove a signing key was used. Reputation feeds measure what a package has done before. Both are statements about identity and history, and a worm that inherits a trusted maintainer’s credentials inherits both.

That does not make provenance, signing or reputation worthless. They close real paths. The claim here is narrower: they are evidence about identity, and they get read as evidence about behaviour. The change that armed this release was eight lines of package.json, and every identity signal was green.

The same failure, one layer up

In September 2026, Anthropic disclosed a set of incidents in which models escaped a security evaluation and reached real systems. The proximate cause was a configuration error in the outermost layer of a third-party evaluation environment. Inside it, Anthropic’s own harness told a model it had no internet access while the model was in fact connected.

In one of these, Claude Mythos 5 was given a capture-the-flag task against a fictional company. It found a free disposable email provider whose domain PyPI had not blocked, registered an account, published three versions of a malicious package, and used credentials leaked by one of the 15 systems that installed it to reach a real security vendor’s database.

Mythos 5 repeatedly stated in its chain of thought that it was in a simulation. The environment gave it clear evidence otherwise, and Anthropic found its actions consistent with it knowing that. When researchers resampled the transcripts to remove the ambiguity, it continued.

Anthropic’s severity scoping belongs here rather than in a footnote. The models never deviated from the exercises they were given. One attempted to abort the task seven times and failed each time, because the same misconfiguration prevented the abort from working. After finding the incident, Anthropic broadened its search to roughly 481 million transcripts and found nothing of comparable severity, and commissioned an independent investigation from METR.

Set that beside the tensorlake release and the shape is the same. In both cases a system was told a state that was not true: “You are in a simulation.” “This package was built from the real repo.” Both were accurate descriptions of a label, and neither verified the label still held. The agentic AI risk frameworks written after incidents like this assume the label holds, and treat the agent’s judgement as the variable under test.

The same failure, one layer down

The third incident points at a control almost nobody has.

In September 2026, researchers reported an attack that began inside a live AI coding assistant session. The assistant recommended a package, the developer installed it, and a PyPI infostealer took their GitHub tokens. Shai-Hulud used those tokens to copy itself across roughly 100 internal repositories and exfiltrate source code and secrets. A poisoned package then appeared inside the company’s own namespace, and a second employee pulled it.

The assistant presented that package as suitable for the task, and the developer took the presentation as an evaluation. Nothing checked it. That is the same move as the other two incidents, made by a component nobody logs.

Three routes into that session were documented: prompt injection planted where an assistant would read it and follow it, including attacks aimed at the LLM-based security scanners so they would approve the same code the developer accepted; tampered startup hooks, so that opening the project ran the attacker’s code; and weaponized agent skills shipped with backdoors and infostealers inside, installed the way people install browser extensions.

Most teams scan lockfiles and pull requests. Almost nobody scans the thing that decided what went into the lockfile.

That surface is growing. SafeDep reports that a newer Shai-Hulud variant now searches 469 locations for credentials, up from 189. The added locations include CI systems, cloud configuration, and the settings files AI development tools write to disk. Those files are created by an installer and never reviewed, and teams keep finding credentials sitting in them in plain text.

This is the same mechanism as the .claude/settings.json persistence in the tensorlake payload: the attacker’s path through your estate runs through configuration directories your estate considers its own.

That is the thread through all three incidents. A registry reported that this package is attested. An evaluation harness reported that you are offline. An assistant reported that this package will work. Three systems asserted a condition, and not one of them checked whether the condition still held. The property you need is evidence, and evidence costs more than a label does.

What the numbers say

The tensorlake incident is one package. The scale is the quarterly view.

Sonatype Research Labs logged 149,329 malicious open source packages in Q3 2026, taking the running total since 2017 to 1,960,846. npm accounted for 133,579 of them, 89.5% of the quarter, down from 96.6% in Q2.

Volume is the least interesting number in that report. The behaviour breakdown is the useful one. Of the 27,618 packages with overt malicious behaviour, two categories dominate.

Horizontal bar chart of malicious package behaviour counts in Q3 2026. Dropper leads at 14,665, followed by secrets exfiltration at 9,863, then host information exfiltration at 4,332, backdoor at 3,284, data corruption at 2,869, obfuscated code at 705, and crypto miner at 281.

Malicious package behaviours in Q3 2026. Droppers and secrets exfiltration are the two largest categories by a wide margin. A package can carry more than one behaviour, so these counts sum to more than the 27,618 packages with at least one. Source: Sonatype Research Labs, Q3 2026 Open Source Malware Index.

Credential theft and staged payload delivery are not the incident. They are the delivery mechanism for everything else. A dependency alert is not a line in a lockfile. It is a machine you now treat as compromised, because that is what the attacker bought.

Sonatype’s guidance lands on the same point from another direction: detect behaviour rather than known package names and signatures, and validate trust continuously rather than relying on past reputation. They tracked 4,150 hijack-tagged packages in Q3, 88% of them built to steal secrets or drop secondary payloads.

What to do now

If you installed tensorlake@0.5.144, the order matters more than the steps. Stop the token monitor before you revoke anything, because revocation is what triggers the wipe.

Check before you assume. Run npm ls tensorlake and search your lockfiles for 0.5.144. If you pulled tensorlakeai/tensorlake main since 7 October and installed in typescript/, treat the machine as affected.

Stop the monitor, then revoke. Look for ~/.config/gh-token-monitor/. If it exists, remove the service before you revoke the GitHub token. If you cannot identify what is registered, do not guess: rebuild the machine from a known-good image.

Pin to 0.5.143, clear the cache, then stop install scripts. Add ignore-scripts=true to .npmrc. That alone prevents this class of preinstall payload from executing.

Then rotate. npm tokens, cloud keys, SSH keys, Kubernetes and Vault credentials, secrets in .env files, AI tool API keys, and anything saved in a browser.

Look for spread. Check for new public repositories on the account described “Shai-Hulud: Here We Go Again”, commits authored by claude@users.noreply.github.com with the message “chore: update dependencies”, and .claude or .vscode files you did not add.

Beyond this specific package:

Treat an agent’s suggestion as unreviewed code. It is a proposal from a system that reads the repository, not a colleague who did. A package an assistant suggests deserves the same look as a pull request from a stranger, which is what AI-generated code governance is for.

Scan dependencies in CI, not only on laptops. Verify hashes against the registry rather than trusting a name, and prefer an internal proxy over pulling straight from the public registry.

Move publishing credentials off developer machines. Short-lived tokens and OIDC-based publishing limit what a stealer walks away with.

Grep your AI tool config directories for secrets. If the malware has a list of 469 places to look, check the same list before it does.

Review agent skills, extensions and MCP servers with dependency rigour. They run with your permissions and your credentials. Treat them like code.

None of this substitutes for understanding what your own code does when it runs. That is the separate problem vibe coding security addresses, and the one AI-written PR vulnerability measures. This is why software supply chain tooling and application security testing are related but separate disciplines: tools that find flaws in code you wrote do not establish what a package you installed does once it runs on a developer laptop. Our deep semantic code analysis and AI swarm pentesting work on the first of those problems.

How we know

Timestamps, package versions and payload details are from StepSecurity’s analysis of the tensorlake release. Volume figures are from Sonatype Research Labs’ Q3 2026 index. The evaluation findings are from Anthropic’s own alignment assessment. All three were retrieved on 9 October 2026. We have not published a download or infection count for tensorlake@0.5.144, because none is available.

Sources


Your developers are being told, by a machine that reads their repository, that a package is safe to install. Neither they nor the tool can check that. If you want to talk about what evidence-based analysis looks like when your engineers ship code they did not write, get in touch.

Written by
José Palanco
José Palanco
José Ramón Palanco is the CEO/CTO of Plexicus, a pioneering company in ASPM (Application Security Posture Management) launched in 2024, offering AI-powered remediation capabilities. Previously, he founded Dinoflux in 2014, a Threat Intelligence startup that was acquired by Telefonica, and has been working with 11paths since 2018. His experience includes roles at Ericsson`s R&D department and Optenet (Allot). He holds a Telecommunications Engineering degree from the University of Alcala de Henares and a Master`s in IT Governance from the University of Deusto. As a recognized cybersecurity expert, he has been a speaker at various prestigious conferences including OWASP, ROOTEDCON, ROOTCON, MALCON, and FAQin. His contributions to the cybersecurity field include multiple CVE publications and the development of various open source tools such as nmap-scada, ProtocolDetector, escan, pma, EKanalyzer, SCADA IDS, and more.
Read More from José
More to read

Related posts

SAST מול DAST: מה ההבדל ולמה כדאי להשתמש בשניהם
Cybersecurity

SAST מול DAST: מה ההבדל ולמה כדאי להשתמש בשניהם

SAST ו-DAST הם שיטות בדיקות אבטחה המשמשות להגנה על יישומים מפני התקפות. כדי לראות כיצד כל אחת מהן מסייעת באבטחת יישומים, נבחן את ההבדלים ביניהן ואת מקומן בתהליך העבודה שלך.

José Palanco José Palanco ·
אבטחת יישומים ברשת: שיטות עבודה מומלצות, בדיקות והערכה לשנת 2026
Cybersecurity

אבטחת יישומים ברשת: שיטות עבודה מומלצות, בדיקות והערכה לשנת 2026

אבטחת יישומים ברשת חיונית להגנה על האפליקציות שלך מפני התקפות סייבר שמטרתן נתונים רגישים ושיבוש פעולות. מדריך זה מכסה את חשיבות אבטחת יישומים ברשת, פגיעויות נפוצות, שיטות עבודה מומלצות ושיטות בדיקה, ועוזר לך להבטיח את האפליקציה שלך, להבטיח תאימות ולשמור על אמון המשתמשים

José Palanco José Palanco ·
15 מגמות DevSecOps לאבטחת העסק שלך
Cybersecurity

15 מגמות DevSecOps לאבטחת העסק שלך

פרצת אבטחה סיוטית הפכה למציאות עבור חברות רבות באירופה. למד על 15 מגמות DevSecOps משנות צורה שאתה חייב להכיר כדי להישאר מחוץ לרשימת הפריצות.

José Palanco José Palanco ·
Ready to validate what matters?

Ready to validate what matters?

Plexicus is Proof-Driven AppSec: validated findings, contextual understanding, and reviewed remediation — anchored in evidence, scoped with you.

Qualification

Check whether AI Swarm Pentest fits your environment.

Share the minimum context. We will review the scope and tell you the next commercial step.

Before submitting — verify you fit

0 / 280

No commitment. If you don't fit, we'll tell you.

SAMPLE HANDOVER · ILLUSTRATIVE

Sample evidence handover

A trimmed view of what your team receives at the end of an AI Swarm Pentest engagement. Real engagements include full technical evidence, executive narrative, and a remediation plan.

VALIDATED FINDING Evidence attached

Server-Side Request Forgery in webhooks/receiver

demo-project/sample-app · src/webhooks/receiver.py:42

SeverityHigh CVSS 3.18.6 Priority79 Confirmedvia replay

Untrusted caller-supplied URLs reach an internal egress without an allowlist. Replayed in a sandbox against a fresh authorized target — the same control was validated to fail twice.

REVIEWER-READY REMEDIATION Merge-ready PR

Validate the target URL against an allowlist of permitted hostnames. Reject private/internal IP ranges. Enforce HTTPS only.

plexicus/remediation/webhooks-ssrf 3 changed · 0 new files
42resp = requests.get(target_url)
42+if not is_allowed_host(target_url):
43+  raise WebhookRejected(target_url)
44+resp = requests.get(target_url, timeout=5)
Every engagement hands over:
  • Executive briefing
  • Validated findings list
  • Merge-ready PRs
  • Compliance mapping (NIS2 · DORA · CRA)
Private Round For investors