Poisoned Pipeline / Incidents / AS39
sckit worm in MemTensor npm plugin and PyPI MemoryOS
StepSecurity documented malicious releases of the legitimate MemTensor
AI-memory plugin @memtensor/memos-cloud-openclaw-plugin on 23 September
2026. Versions 0.1.21, 0.1.23, and 0.1.25 added lib/sckit.js and
platform-native .sckit binaries. There was no install/preinstall/
postinstall script: the plugin's own gateway-startup and memory-recall
paths import launchStageZero, spawn a detached sckit binary with
--config64, copy the parent environment (including credentials), and
on recall also pass the user's prompt as SCKIT_EVENT_TEXT. Clean
0.1.22 and 0.1.24 restored the package; malicious contents returned
3 minutes 36 seconds and 3 minutes 28 seconds later. Unpacked size
jumped from ~272 KB to ~43.6 MB. MemTensor issue 173 reports npm
artifacts with no matching git commits or tags, so publishing
credentials were used rather than the source repo. An uncalled
collectStageZero helper maps NPM_TOKEN/NODE_AUTH_TOKEN. PyPI
MemoryOS 2.0.34 is the Python counterpart: a logging-init hook in
configure_logging() reaches the launcher on import, six hashed
payloads, and a hash-pinned CI delivery chain. Binary strings name
recursivePublish and a GitHub Actions template; StepSecurity treats
those as intended propagation, not observed extra publishes.
Mapped techniques
- T0112 Compromised token
- T0121 Compromised legitimate artifact
- T0109 Publish malicious artifact
- T0159 Malicious artifact execution
- T0140 Harvest tokens from environment variables
- T0184 Harvesting sensitive information from files
- T0193 Sensitive information in environment variables
supply-chain Compromised MemTensor npm plugin
npm artifacts had no matching git commits or tags; publish credentials, not the repo.
Real @memtensor/memos-cloud-openclaw-plugin versions 0.1.21/0.1.23/0.1.25.
Three malicious npm versions on 23 Sep; latest pointed at 0.1.25.
No install scripts; launcher runs from gateway startup and memory-recall.
Child inherits process.env; collectStageZero maps NPM_TOKEN/NODE_AUTH_TOKEN.
Decoded config sets inventory_roots to $HOME; binary strings match cloud, VCS, and registry tokens.
Parent env plus SCKIT_EVENT_TEXT (user prompt on recall) are handed to the detached binary.
supply-chain PyPI MemoryOS 2.0.34
MemoryOS 2.0.34 on PyPI; same sckit payload family.
Wheel/sdist include six platform binaries via a custom Poetry build backend.
Import of memos reaches configure_logging() then memos._stage0.trigger().
Python launcher copies os.environ into the child; CI helper can inherit INPUT_PASSWORD.
Framework gaps noted
- HTTP C2 fronts on skyleen.fr (/config, /status, /batch) are not a named technique.
- recursivePublish / GitHub Actions implant strings in the binary are intended worm behaviour; extra victim publishes were not shown.
- Passing the user's memory-recall prompt as SCKIT_EVENT_TEXT is not a named technique.
Sources
- https://www.stepsecurity.io/blog/sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes
- https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin/issues/173
- https://safedep.io/memtensor-sckit-worm-npm-pypi
- https://safedep.io/sckit-go-implant-framework
- https://www.aikido.dev/blog/novel-supplychain-local-go-worm-appears
- https://www.aikido.dev/blog/supplychain-local-memtensor-npm-pypi
- https://socket.dev/blog/memtensor-compromise