Cafiyn Pulse
← Startup Signals
7 min readUpdated 2026-09-25Issue 4

A package install reads your home directory. This week two of them did it on purpose.

The implant did nothing clever. It read the files your shell reads, in the place your credentials live, and sent them somewhere else. That is the whole attack, and it works.

ByKarthik KumarCafiyn Innovations
At a glance
Published
23 September 2026
npm
memos-cloud-openclaw-plugin, versions 0.1.21, 0.1.23, 0.1.25
PyPI
memoryos, version 2.0.34
Payload
A Go implant named sckit, runs on package load
Exfiltration
Servers under skyleen[.]fr
OSV records
MAL-2026-16476 (npm), MAL-2026-16475 (PyPI)

What was published

On 23 September, OSV recorded malicious versions of two related packages. On npm, memos-cloud-openclaw-plugin under the memtensor scope, at versions 0.1.21, 0.1.23 and 0.1.25. On PyPI, memoryos at version 2.0.34. The interleaved version numbers are worth noticing: 0.1.22 and 0.1.24 are reported clean, so a team pinning to a recent version had roughly even odds.

An open issue on the project's own GitHub repository, filed by an outside researcher, reports that versions were published to npm that do not correspond to any commit or tag in the repository, and says the package's npm publish token appears to have been compromised. That is the researcher's assessment. The maintainers have not publicly commented, and no primary source describes a compromise of the company itself, so we are not going to.

What the implant does

The payload is a Go binary called sckit that executes when the package loads. OSV describes functions named credentialPaths, readCredentialFile and extractJSONCredentials that target a specific list of files: .npmrc, .pypirc, .git-credentials, .netrc, id_rsa, id_ecdsa, id_ed25519, .vault-token, msal_token_cache, access_tokens.json and access_tokens.db. It collects credentials from the home directory and sends them to servers under skyleen[.]fr.

There is nothing sophisticated in that list, and that is the point worth internalising. It is simply the set of places developer tooling stores long-lived secrets by convention. Registry tokens, git credentials, SSH private keys, a Vault token, cached cloud tokens. Everything a working developer machine accumulates and rarely audits.

In CI the implant adds a second stage. OSV records that when GITHUB_ENV is set, it appends a BASH_ENV entry pointing at a script inside the package, which gives it a hook into subsequent shell invocations in the job. The quoted behaviour concerns capturing PyPI publishing tokens.

The scope problem nobody prices in

When you add a dependency, you are asking a program to run on your machine with your permissions. Package managers run install scripts, and imported modules execute code at load time. There is no sandbox between a dependency and your home directory by default, on any of the major ecosystems.

That means the blast radius of one bad package is not the feature that package provides. It is every credential the process can read. A small utility library that helps format dates has, by default, exactly as much access to your SSH key as your deployment script does.

This is why the rotation list after an incident like this is so much longer than the package itself suggests. The question is not what the package could legitimately need. It is what was reachable from the account that ran the install.

If you think you were exposed

Work from the machine outward. Every credential that was readable from the home directory of the user that ran the install should be treated as known to someone else.

  • Check lockfiles across every repository, and check agent and tool configurations, which often pull packages outside your main dependency tree
  • Rotate npm and PyPI tokens first, because those let an attacker publish as you and widen the blast radius to your own users
  • Rotate GitHub personal access tokens, SSH keys and any cloud credentials cached on the machine or runner
  • Search CI logs and network egress records for connections to skyleen[.]fr
  • Check for unexpected releases of your own packages, and review the publish history of anything you maintain

The structural fix landed five days earlier

On 18 September GitHub shipped a new npm token permission level, read and write, stage only. A workflow with that token runs npm stage publish to submit a version for review, and npm rejects a direct npm publish attempt with that token even if it is configured to bypass two-factor authentication for automation. A maintainer then approves the release with a second factor. GitHub says npm is targeting January 2027 to remove direct publishing through bypass-2FA tokens.

That change is aimed squarely at this class of attack, where the entire objective is a publish token sitting in a release job. A stolen stage-only token cannot ship anything to your users on its own.

It has a genuine cost, and it is worth stating rather than glossing: releases now require a human being with a second factor, which is slower and occasionally inconvenient at the wrong hour. That is the trade. Given what a stolen publish token does to everyone downstream of you, it is a reasonable one.

What to do

  1. 1Search every lockfile and agent configuration for the affected package names and versions.
  2. 2If found, rotate registry tokens, git credentials, SSH keys and cached cloud tokens from that machine or runner.
  3. 3Grep CI logs for outbound connections to skyleen[.]fr.
  4. 4Replace npm CI automation tokens with stage-only tokens, or move to trusted publishing.
  5. 5Pin dependencies by exact version and review lockfile diffs on every update, so an unexpected version bump is visible.

Common questions

Which package versions are malicious?

Per OSV, the npm package memos-cloud-openclaw-plugin under the memtensor scope at versions 0.1.21, 0.1.23 and 0.1.25, and the PyPI package memoryos at version 2.0.34. Versions 0.1.22 and 0.1.24 are reported clean.

What does the implant steal?

OSV lists .npmrc, .pypirc, .git-credentials, .netrc, SSH private keys including id_rsa, id_ecdsa and id_ed25519, .vault-token, msal_token_cache, access_tokens.json and access_tokens.db, collected from the home directory and sent to servers under skyleen[.]fr.

What should I rotate if I installed an affected version?

Everything readable from that user's home directory: npm and PyPI tokens, GitHub personal access tokens, SSH keys, and any cached cloud credentials. Start with registry tokens, since those let an attacker publish as you.

What is a stage-only npm token?

A token permission level GitHub added on 18 September 2026. It can submit a version with npm stage publish for a maintainer to approve with two-factor authentication, but npm rejects a direct npm publish attempt with it, even if it is configured to bypass 2FA for automation.

Has the maintainer confirmed the compromise?

Not publicly, as of 25 September 2026. The claim that the npm publish token appears to have been compromised comes from an outside researcher in an open issue on the project repository, not from the maintainers.

Sources

Read against the primary documentation rather than secondary coverage. Where a figure comes from a provider's own docs, it is quoted as published on 2026-09-25.

Related

More from Signals

A 9.5 in next/og. Whether it reaches you depends on one line in your OG route.
The advisory rates it 9.5, but it only fires if your OG image route puts attacker-controlled text into SVG. Here is how to find out which side of that line you are on.
OpenAI and Anthropic both cut prices on 22 September. One of them costs you a refactor.
Two frontier price cuts in one day is a good week for anyone paying a token bill. The migration cost is not evenly distributed, and one of the two prices comes with an expiry hedge.
GitHub is switching off SHA-1 SSH keys. Find out now whether yours is one of them.
The keys at risk are the old ones, on the machines nobody logs into, in the pipelines that have run untouched for three years. Those are also the ones that will fail loudest.
Every third-party script tag is a standing grant to run code on your visitors.
A marketing form, a chat widget, an analytics snippet. Each one is permission for someone else's server to execute whatever it sends, on every page it sits on, forever.
1.8 million Android apps were scanned for hardcoded keys. Here is how to check yours.
Finding secrets in shipped apps is now a cheap, automated pipeline. Anything compiled into an APK, an IPA or a JavaScript bundle should be treated as already published.
OpenAI's Agents API will hold your agent state. What breaks if you ever need to leave.
Two major providers moved into the agent state layer in the same week. A managed harness is a real shortcut, as long as you keep a copy of what it holds.
Meta's Muse agent can now check out at your store. What merchants should change.
Agent purchases are arriving through wallets and single-use cards, not through merchants adopting a new protocol. Many merchants will receive them without choosing to.
What Brevo's SSO incident teaches about multi-tenant SAML and hijacked sending accounts.
One incident, two lessons: why email authentication did not help, and the tenant-scoping mistake anyone shipping SSO can make.
Cloudflare now sorts bots into Search, Training and Agent. What it means for your site and your agent.
The same change lands on two audiences. Site owners can now accidentally block search; agent builders will find more doors closed.
OpenAI has published seven shutdown dates. Here is the calendar.
Seven dates between 23 October and 26 February. Every one announced months ahead, in public. The failure mode is never the notice.
Nvidia bought Hugging Face. Your open-weight fallback is now a vendor relationship.
The commitments say nothing breaks. The structural change is that "we can always self-host" is now a dependency on one vendor rather than on a neutral commons.
The Videos API goes away on 24 September and OpenAI names nothing to move to.
Every other deprecation on OpenAI's page offers a migration target. This one does not, which makes it a different kind of problem.
Whisper shuts down on 26 February. The risk is not the deadline.
Five months is a generous window. Whisper is also typically wired into a background job that fails into a queue rather than into a user's face.
The Assistants API is gone. Your app may not have told you yet.
It shut down on 26 August 2026. The replacement is not a drop-in, and the most common migration mistake changes your model's behaviour without throwing an error.
One Copilot code review costs 13 requests. Here is the rest of the maths.
Copilot now bills on usage rather than seats. The headline change is simple. The multipliers underneath it are where teams get surprised.
Row-level security is on by default now. That is not the same as being protected.
Lovable fixed the default. The gap that actually leaks data was never the default, it was the policy, and no platform can write that for you.
Your model comparison is measuring the wrong number.
Every price list is per token. Your bill is per finished piece of work. Those two numbers can rank models in opposite orders.
An agent with production log access is a new identity. Treat it like one.
Always-on agents that read production logs are arriving fast. The access-control question they raise is old and well understood, which is the good news.

Open the tool.

Ten production categories, three minutes, and a ranked list of what to fix first.

Check your own stack