⌁AI·CYBER·BRIEF▌
AI Threats11 min read

The first supply-chain worm built for the AI memory layer — and why it skipped the install hook

The sckit worm reached npm and PyPI through MemTensor's release pipeline. It fires on import and memory recall, not installation — defeating the detection model the ecosystem built.

On 23 September 2026, attackers published backdoored versions of MemOS — an open-source memory layer for LLMs and AI agents — to both npm and PyPI, carrying a Go implant called sckit that harvests developer and cloud credentials and ships templates for republishing itself into other packages. The technically significant detail is not the theft but the trigger: sckit does not run during installation, where every package scanner is watching. It runs when the library is imported and when an agent recalls a memory. That single design choice makes a large part of the ecosystem's supply-chain tooling blind to it.

The short version

MemOS, published by the Chinese AI company MemTensor, gives agents long-term memory — a place to store what a user said last week and retrieve it today. It is widely used, with roughly 11,100 GitHub stars, and it ships on the two registries developers rely on most.

Someone took control of MemTensor's GitHub account and went after the release machinery rather than the source code. Per SafeDep's analysis, the attacker pushed commits that caused MemTensor's own GitHub Actions release workflow to hand over its npm and PyPI publishing tokens. With those in hand, they uploaded their own builds. Three malicious npm versions appeared inside roughly two hours, with clean versions interleaved between them — a pattern that makes a maintainer's release history look busy rather than compromised.

Affected: npm @memtensor/memos-cloud-openclaw-plugin versions 0.1.21, 0.1.23 and 0.1.25, and PyPI MemoryOS 2.0.34. If anything in your estate installed one of those, the credentials reachable from that machine should be treated as gone and rotated from a clean host. If you do not use MemOS, there is nothing to remediate — but the mechanism below is worth twenty minutes regardless, because it is not specific to MemOS.

Timeline

  • 15 September 2026 — the command-and-control domain skyleen[.]fr is registered, per SafeDep — eight days before the packages were published.
  • 23 September 2026 — three malicious npm releases of @memtensor/memos-cloud-openclaw-plugin are published within about two hours, alongside PyPI MemoryOS 2.0.34. Advisory MAL-2026-16475 is issued the same day.
  • 23 September 2026 — StepSecurity, SafeDep and The Hacker News publish. The Hacker News reports that analysis came from Aikido, SafeDep, Socket and StepSecurity. Malicious versions are removed from both registries and the PyPI project is quarantined.
  • 25 September 2026 — on our check, MemTensor had published no statement or advisory of its own and the MemOS repository carried no notice.

What we know

The delivery mechanism. SafeDep's account, quoted by The Hacker News: "the attacker obtained the publish tokens from MemTensor's own GitHub Actions release pipelines by pushing commits that caused the workflow to hand over the npm or PyPI token." The compromise was of MemTensor's account and pipeline, not of a flaw in MemOS's code.

The trigger. This is the finding that matters. Per SafeDep and Semgrep's analyses, sckit does not use an install hook. On the Python side, importing the library is sufficient — it hooks a logging-configuration path that runs on module import. On the npm side, it fires when the agent gateway starts and on memory-recall operations. In other words, it activates during ordinary use of the library rather than during npm install or pip install.

What it takes. SafeDep reports credential harvesting from .npmrc, .pypirc, .git-credentials, SSH key files and cloud CLI token caches, with regex patterns matching tokens for AWS, GitHub, GitLab, npm, PyPI, Hugging Face, HashiCorp Vault, Slack, Stripe and SendGrid. Anything readable under the user's home directory should be assumed exposed.

It is a framework, not a one-off dropper. SafeDep describes command and control over CBOR-encoded encrypted messages, X25519 key exchange with XChaCha20-Poly1305, and signed leases that limit how long an implant stays active and how long it may run offline. Separate binaries are built per campaign — 6.8 to 7.7 MB for the npm and PyPI variants — with unique subdomains and distinct configuration per campaign. SafeDep states the code and infrastructure do not match a known malware family.

The self-replication. The implant embeds templates for Python imports, Node.js binaries and GitHub Actions workflows, allowing it to install itself into other packages and pipelines using the publishing tokens it steals. SafeDep specifically flags a workflow file named runtime-update.yml.

Forensic indicators. Process execution matching sckit stage0 --config64, runtime state directories at ~/.openclaw/.cache/runtime and ~/.memos/.cache/runtime, and a schema identifier sckit.control.v1. StepSecurity reports three primary C2 domains resolving to 139.84.223.178, plus a fourth used only in CI environments. Artefact hashes are in the MAL-2026-16475 advisory.

Attribution. None. No source reviewed here names an actor, and neither do we.

Technical analysis

The install hook was the whole detection model, and it just stopped being enough. For years, defending against malicious packages has rested on a reasonable assumption: hostile code runs at install time, because that is the first moment the attacker controls. So scanners watch preinstall and postinstall scripts, sandboxes execute installs and observe what happens, and CI gates inspect what a package does when it is fetched. sckit sidesteps all of it by doing nothing at install and everything at import.

The consequences are worth spelling out, because they are not symmetrical with the old model. A package that only misbehaves at install time is harmless if it is installed and never used — plenty of transitive dependencies sit in node_modules untouched. sckit inverts that: it is inert until the library is actually exercised, which means it fires precisely on the machines that matter, in the processes that have live credentials loaded, at the moment the application is doing real work. It also survives the common remediation of "we removed the package from the lockfile" if the implant has already established its own runtime state.

Our assessment: this is the most transferable part of the incident. The trigger technique has nothing to do with AI, memory layers, or MemTensor. Any project with a plausible import-time initialisation path can be backdoored this way, and the detection gap it exploits is industry-wide. Expect reuse.

Push access and publish access are still the same privilege. The root cause here is a design most organisations share. An automated release pipeline holds a long-lived publishing token and executes whatever the repository's build configuration says. Because that configuration is code, and because it runs before any human reviews the resulting artefact, anyone who can push a commit can usually reach the token. The attacker did not smuggle malicious code past a reviewer; they used one credential to obtain a second, more valuable one. Trusted publishing with short-lived, workflow-scoped credentials exists specifically to break this chain, and this incident is an argument for adopting it that is hard to wave away.

Why a memory layer? Follow the credentials. Semgrep's framing is the right one and deserves amplification: AI tooling is targeted because of credential density. An agent stack is, structurally, a pile of keys — model providers, vector stores, object storage, model hubs, plus whatever the agent has been granted in order to act. Compare a logging library with an identical install footprint and far less to steal. On the numbers alone, an attacker choosing where to spend a stolen GitHub account should pick the AI dependency.

But there is a second reason specific to memory, and it has had less attention. A memory component sits on the path where user prompts and retrieved context flow. That content is routinely unclassified — nobody ran a data inventory on what users type into an agent — and it frequently contains exactly what a data-protection team would care about. An implant positioned at the memory layer has a data-access vantage point, not just a credential one. Nothing in the public reporting says sckit exploited that position, and we are not claiming it did. But the tier is now demonstrably reachable, and it is a tier almost nobody has in their asset inventory.

The OpenClaw path is the uncomfortable detail. The compromised npm package is an OpenClaw plugin, which connects this to the largest open-source agent platform in use. That platform's third-party extension ecosystem has been flagged repeatedly — Cisco researchers documented a third-party skill performing data exfiltration and prompt injection without user awareness back in January 2026, and Mandiant's AI Risk and Resilience 2026 reports VirusTotal observing weaponised OpenClaw agent skills in February. A credential-stealing worm arriving through a first-party-looking plugin in a vendor's own npm scope is a different and harder problem than a malicious community skill, because the trust signal a developer would normally check — the publisher — was genuine.

Built for more than one campaign. Signed leases, per-campaign subdomains, per-campaign configuration and separate binaries are engineering investments that only pay off across repeated operations. Combined with a C2 domain registered eight days ahead, this reads as infrastructure rather than opportunism. Our assessment: MemTensor is unlikely to be the only target this framework was built for, and defenders should treat the sckit indicators as a standing detection, not an incident-specific cleanup.

What remains unclear

  • Advisories disagree on which version is safe. The Hacker News, citing the research, names npm v0.1.24 as a safe version; other remediation guidance points to 0.1.20. Because the malicious releases were 0.1.21, 0.1.23 and 0.1.25 with clean versions interleaved, both statements can be locally true while being confusing in practice. Anyone remediating should verify the specific artefact they are pinning against the hashes in MAL-2026-16475 rather than trusting a version number from coverage — including ours.
  • How the MemTensor GitHub account was taken over. No published account explains the initial compromise. This is the most important gap, because it determines whether other maintainers are exposed the same way.
  • How many installs the malicious versions received before removal. No source reviewed here gives a figure.
  • Whether the stolen tokens have been used. The worm's value is in the second hop. Whether any downstream package or workflow was republished with sckit is not publicly established — and it is the outcome that would turn one compromise into many.
  • Whether exfiltration actually succeeded. The researchers state plainly that they cannot confirm successful data transmission, which credentials were taken, or whether the PyPI CI delivery chain ever fired.
  • MemTensor's side of the story. As of 25 September there was no vendor statement or repository notice. Treat the vendor account as incomplete.
  • Severity has no score, by design. This is malicious-package abuse, so it carries a malware advisory rather than a CVE with a CVSS rating. For an organisation that installed an affected version it is critical; for everyone else it is zero. That bimodal distribution is typical of supply-chain incidents and a reason headline severity language misleads.

Lessons and what to do

For security teams. Start with the concrete: search lockfiles, requirements.txt and built container images — not just source trees — for memos-cloud-openclaw-plugin and MemoryOS. If you find a hit, rotate from a clean machine in this order: npm and PyPI publishing tokens, Git tokens and SSH keys, cloud CLI credentials, Hugging Face tokens, Vault tokens, database connection strings, .env contents. Then review your own repositories' release history for publishes nobody authorised, and look for unexpected workflow files.

Beyond this incident, the structural change is the detection one. If your supply-chain controls only observe installation, you are covering the older half of the threat. Add runtime egress monitoring from build agents and developer machines, and treat first-time outbound connections from a CI runner as a signal — a runner that suddenly talks to a domain registered last week is a strong indicator regardless of which package carried the payload.

For AI builders. Two things. Move release pipelines to trusted publishing with short-lived, workflow-scoped credentials, so that push access stops conferring publish access; this incident is a direct demonstration of why that matters. And recognise that shipping an agent plugin puts you in a high-value target class — credential density makes AI tooling worth more per compromise than equivalent general-purpose libraries, and attackers are pricing that in. Plugin and extension ecosystems need signature verification and integrity checks as a platform feature, not as advice in a security guide.

For leadership. Ask one question: do we have an inventory of the AI components in our stack, including agent plugins and memory layers, at the version level? For most organisations the honest answer is no, because these dependencies entered through developer experimentation rather than procurement. An AI-specific software bill of materials is the unglamorous prerequisite for responding to the next one of these in hours rather than days — and there will be a next one, because the framework behind this attack was clearly built to be reused.

Sources

Primary

Coverage:

Get the daily brief

AI + security signal by email: headlines, a two-line summary, a link. No noise, no spam.

How often