{"id":"MAL-2026-16475","summary":"Malicious code in memoryos (PyPI)","details":"On September 23, 2026, an attacker published malicious versions of two MemTensor packages. The affected packages are the OpenClaw plugin @memtensor/memos-cloud-openclaw-plugin on npm and the MemOS Python library MemoryOS on PyPI. Both versions contain the same Go implant, sckit. The binary runs in the background each time the package loads. It collects credentials from the home directory and sends them to servers under skyleen[.]fr. It also includes the code it needs to copy itself into other repositories and packages that the stolen credentials can reach.\n\nCredential collection: the implant's `credentialPaths`, `readCredentialFile` and `extractJSONCredentials` functions target `.npmrc`, `.pypirc`, `.git-credentials`, `.netrc`, `id_rsa`, `id_ecdsa`, `id_ed25519`, `.vault-token`, `msal_token_cache`, `access_tokens.json` and `access_tokens.db`. Two regular expressions pick out secrets: one matches secret-like variable names (`token`, `secret`, `password`, `api_key`, `database_url`), the other matches known token formats.\n\nC2 protocol: the `internal/wire` package uses CBOR, X25519 key exchange and XChaCha20-Poly1305 (`sckit/xchacha/v1`), and handles signed leases, manifests and modules. The server delivers the modules at run time, so their contents were not observed. `scheduleSelfDelete` and `deleteExecutable` remove the binary after it runs.\n\nC2 paths: `/\u003c24 hex\u003e/config` (control), `/status` (preflight), `/batch` (results).\n\nPackage archive SHA-256 digests:\n- memoryos-2.0.34-py3-none-any.whl: 39ee644406829a4b630b31759c20478bc22d576d6a59b253ed86f72c360aa5ef\n- memoryos-2.0.34.tar.gz: 92b46d18fc553c494eda714f204459edb74c205bf53b18a9092bcf02c7a6c5be\n\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (91081756ee0d7e550180abd300ce4ed9634862248dd07ea9eed5fb740e4aaffc)\nOn `import memos`, memos/__init__.py invokes configure_logging() which reaches memos._stage0.trigger(). That function locates a per-OS/arch prebuilt Go binary shipped inside the wheel at src/memos/.sckit/{darwin,linux,windows}-{amd64,arm64}/sckit (linux-amd64 is a 7.4MB ELF, sha256 c1b0998347b489582bae7b7f4930f9831d9ef4b6bc150cfd488ee1a43272dd36) and Popen-launches it detached (start_new_session=True, output silenced) with a base64 --config64 payload. The decoded configuration declares campaign_id \"memos-semi-nuclear\", an Ed25519 root_public key, state_dir $HOME/.memos/.cache/runtime, inventory_roots=[\"$HOME\"], and three anonymous hex-subdomain fronts https://c747d139e7e9.skyleen.fr, https://73376a079d87.skyleen.fr and https://d4f77a3a8cb0.skyleen.fr with config/status/batch endpoints — instructing the launched agent to enumerate the installer's home directory and POST batches to attacker-controlled infrastructure. Separately, the package's PEP 517 build backend (sckit_poetry_build.py) wraps poetry.core.masonry and, when GITHUB_ENV is set, appends BASH_ENV=src/memos/_pypi_bridge.sh to $GITHUB_ENV so that any subsequent bash step in the same CI job auto-sources _pypi_bridge.sh; under a twine publish path this invokes _initial_ci_delivery.py to fetch and execute an Ed25519-signed emitter from https://10729e014d0e.skyleen.fr and reads $INPUT_PASSWORD and $PYPI_API_TOKEN before unsetting them, giving the attacker access to downstream publishing credentials. The combination of import-time detached execution of a bundled multi-arch binary, base64-obfuscated runtime manifest, anonymous hex-subdomain C2 fronts, declared $HOME inventory harvest, and a CI-only sideloader that steals publish tokens is a supply-chain implant.\n\n## Source: kam193 (d17530b4f32046961be6354a73139dafa5a7d73ca9f7226dcf6bb3a3510bde20)\nVersions 2.0.34 were compromised.\n\n\nThe package was compromised and contains a malicious executable. First discovered by Safedep.\n\n\n---\n\nCategory: MALICIOUS - The campaign has clearly malicious intent, like infostealers.\n\n\nCampaign: 2026-09-compr-memoryos\n\n\nReasons (based on the campaign):\n\n\n - compromised-package\n","aliases":["PYSEC-2026-3987"],"modified":"2026-09-23T23:00:07.893618935Z","published":"2026-09-23T00:00:00Z","database_specific":{"iocs":{"urls":["https://10729e014d0e.skyleen.fr/eb57efaa7365698fc1e4decc/initial-ci-v2"],"domains":["c747d139e7e9.skyleen.fr","73376a079d87.skyleen.fr","d4f77a3a8cb0.skyleen.fr"],"files":[{"paths":["memos/_stage0.py"],"source":"PACKAGE_ARCHIVE","note":"Stage-0 loader shipped in the package."},{"digests":{"sha256":"c1b0998347b489582bae7b7f4930f9831d9ef4b6bc150cfd488ee1a43272dd36"},"note":"sckit Go implant, linux-amd64 build.","source":"PACKAGE_ARCHIVE"},{"digests":{"sha256":"8f647f17a1934679c4095e21bee2b9bd83e28476603758bc91408a0c8443e3b4"},"note":"sckit Go implant, linux-arm64 build.","source":"PACKAGE_ARCHIVE"},{"note":"sckit Go implant, darwin-amd64 build.","source":"PACKAGE_ARCHIVE","digests":{"sha256":"9de0d5b0ca184f71f630be5781d134998883a02d5d7bc65aeb9559d8f9efb364"}},{"digests":{"sha256":"5405e330507602e803f7dd6f2a9d4555aec8558ab222b51413594a962da6888a"},"note":"sckit Go implant, darwin-arm64 build.","source":"PACKAGE_ARCHIVE"},{"note":"sckit Go implant, windows-amd64 build.","source":"PACKAGE_ARCHIVE","digests":{"sha256":"16de381deb978744535b10f68fe15165251374b86eef18ffc2c47f61ea673047"}},{"digests":{"sha256":"f7c4014e284f3d56c452b8b222a287c54f73dc4a40a7e022e765ac8376362947"},"note":"sckit Go implant, windows-arm64 build.","source":"PACKAGE_ARCHIVE"},{"source":"DROPPED","note":"Implant state directory.","paths":["$HOME/.memos/.cache/runtime"]},{"paths":["runtime-update.yml"],"source":"DROPPED","note":"GitHub Actions workflow written by the worm for persistence; runs 'sckit stage0'."},{"source":"DROPPED","note":"CI tampering scripts; the implant also writes BASH_ENV= to $GITHUB_ENV.","paths":["sckit_poetry_build.py","_pypi_bridge.sh","sckit-publish-bridge.sh"]}]},"malicious-packages-origins":[{"sha256":"d17530b4f32046961be6354a73139dafa5a7d73ca9f7226dcf6bb3a3510bde20","source":"kam193","versions":["2.0.34"],"id":"pypi/2026-09-compr-memoryos/memoryos","import_time":"2026-09-23T11:39:55.779888783Z","modified_time":"2026-09-23T11:05:40Z"},{"source":"kam193","versions":["2.0.34"],"id":"pypi/2026-09-compr-memoryos/memoryos","import_time":"2026-09-23T12:27:29.81554581Z","modified_time":"2026-09-23T11:24:20.192213Z","sha256":"f615efcaee7120884365656085be5fdd17450a486945e6154004e36ddab0ac89"},{"sha256":"91081756ee0d7e550180abd300ce4ed9634862248dd07ea9eed5fb740e4aaffc","source":"amazon-inspector","versions":["2.0.34"],"id":"IN-MAL-2026-020490","import_time":"2026-09-23T14:19:31.842786769Z","modified_time":"2026-09-23T14:10:14Z"},{"versions":["2.0.34"],"id":"pypi/2026-09-compr-memoryos/memoryos","import_time":"2026-09-23T19:16:13.107645438Z","modified_time":"2026-09-23T11:24:20.192213Z","sha256":"86a27870b919aa000ef05a66cedd4622cbf521a2ea6867a579dbec8c90d66f77","source":"kam193"}]},"references":[{"type":"WEB","url":"https://safedep.io/memtensor-sckit-worm-npm-pypi/"},{"type":"EVIDENCE","url":"https://www.virustotal.com/gui/file/8f647f17a1934679c4095e21bee2b9bd83e28476603758bc91408a0c8443e3b4/detection"},{"type":"WEB","url":"https://bad-packages.kam193.eu/pypi/campaign/2026-09-compr-memoryos"},{"type":"PACKAGE","url":"https://pypi.org/project/MemoryOS/2.0.34/"},{"type":"REPORT","url":"https://safedep.io/memtensor-sckit-worm-npm-pypi/"}],"affected":[{"package":{"name":"memoryos","ecosystem":"PyPI","purl":"pkg:pypi/memoryos"},"versions":["2.0.34"],"database_specific":{"cwes":[{"description":"The product contains code that appears to be malicious in nature.","name":"Embedded Malicious Code","cweId":"CWE-506"},{"name":"Embedded Malicious Code","cweId":"CWE-506","description":"The product contains code that appears to be malicious in nature."}],"source":"https://github.com/ossf/malicious-packages/blob/main/osv/malicious/pypi/memoryos/MAL-2026-16475.json","indicators":{"evidence_files":[{"path":"src/memos/_stage0.py","sha256":"881ea19936b0275f0d77c9d1a669b29595f7e274fef7bb7d82ec1690f8dbc591","tlsh":"ad41e699cb283f8ca146423152117b6883a7c4437b0754ad34dc4dc8179b4aba0e48ff"},{"path":"sckit_poetry_build.py","sha256":"497be589f382b321fa08d5583e7c7ff76daca18f988607a0051f8797b046ed86","tlsh":"5621b734d21426a6a2f101e53922532182f7a06f4e426d28fd8cdd881f4e42a02f247d"}],"package_integrity":[{"filename":"memoryos-2.0.34-py3-none-any.whl","hashes":{"md5":"3d8db89d9fc419780fa557b5bbb6dd53","sha256":"39ee644406829a4b630b31759c20478bc22d576d6a59b253ed86f72c360aa5ef","blake2b_256":"166972a6cc7f2a7a6ce286631bb176fb575dfd2378c2b74058a3e9b4cd0f1df9"}},{"hashes":{"sha256":"92b46d18fc553c494eda714f204459edb74c205bf53b18a9092bcf02c7a6c5be","blake2b_256":"3e9a4d766a52dcabcbf440aa8f8f1eaf2adca041f93913271d8c342c20ae167c","md5":"ecac3e301bc0b287fb4f5740a2cd8b8f"},"filename":"memoryos-2.0.34.tar.gz"}]}}}],"schema_version":"1.9.0","credits":[{"name":"Amazon Inspector","contact":["inspector-research@amazon.com"],"type":"FINDER"},{"name":"Kamil Mańkowski (kam193)","contact":["https://github.com/kam193","https://bad-packages.kam193.eu/"],"type":"REPORTER"},{"name":"Kamil Mańkowski (kam193)","contact":["https://github.com/kam193","https://bad-packages.kam193.eu/"],"type":"ANALYST"},{"name":"SafeDep","contact":["https://safedep.io"],"type":"FINDER"}]}