{"id":"MAL-2026-4221","summary":"Malicious code in selfservsweeper (PyPI)","details":"\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (81843a6f21fe31627b1e97fdb8ffe41789c1f921c60512347bbf2b0c2fb30121)\nPackage self-describes as a 'Touch-friendly Minesweeper overlay for NCR SelfServ kiosks', but the advertised CLI entrypoints (`selfservsweeper`, `selfservsweeper-cli`) call `run_app()` which auto-spawns `python -m selfservsweeper.selfservclient` as a side process. That module long-polls `https://api.telegram.org/bot\u003credacted\u003e/` using a hardcoded bot token shipped in `src/selfservsweeper/api_url.pkl`, accepts commands prefixed `B2B1:` from the Telegram channel `@selfservserverbot`, and executes attacker-supplied 'jobs'. The job handler in `selfservclient.py` includes a `/file \u003cpath\u003e` directive that writes attacker-supplied content to disk, and `send_file_result` reads any `path` field from a job result and uploads the raw bytes back to Telegram via `sendDocument` — a bidirectional read/write file primitive on the installer's machine. The Telegram bot token is identical for every install, so anyone who unpacks the wheel inherits command authority over every running instance. `grammarly.py` additionally loads bundled `.pkl` artifacts (`levenshtein.pkl`, `user_config_tempdir.pkl`) via `pickle.load` and binds the resulting callables as `edit_distance_cls` and `Sandbox._is_valid_path`, invoking them on attacker-controlled job text — an obfuscation channel for arbitrary code reduction. The `install --enable-startup` subcommand (and the GUI 'Enable' button) writes `%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\SelfServSweeper.vbs`, persisting the supervisor (and thus the Telegram client) across logins, and the supervisor's auto-update path `pip install`s the package on every boot to keep the backdoor live and self-updating. The minesweeper UI is cover; the package's effect on any installer who runs the advertised binary is a persistent, attacker-controlled remote command channel with file read/write reach.\n\n## Source: kam193 (261d2d72c05ac44f1cc977e3ec5e1f42ff1634f80b06a4b84b62e9079b8de8db)\nWhen used, the package executes remote commands disguised as OCR job requests.\n\n\n---\n\nCategory: MALICIOUS - The campaign has clearly malicious intent, like infostealers.\n\n\nCampaign: 2026-05-selfservsweeper\n\n\nReasons (based on the campaign):\n\n\n - obfuscation\n\n\n - The package contains code to execute remote commands (probably limited to a specific set) on the victim's machine.\n\n\n - persistence\n\n\n - backdoor\n","modified":"2026-05-26T06:03:13.548994694Z","published":"2026-05-21T01:29:54Z","database_specific":{"malicious-packages-origins":[{"source":"kam193","sha256":"261d2d72c05ac44f1cc977e3ec5e1f42ff1634f80b06a4b84b62e9079b8de8db","import_time":"2026-05-21T10:46:39.537921051Z","id":"pypi/2026-05-selfservsweeper/selfservsweeper","modified_time":"2026-05-21T10:28:36.915892Z","versions":["0.1.7"]},{"source":"kam193","sha256":"f4823d3b817e9fbcbf9261be9b7d108a6321b3dfa3ad5ef945c89a16bb4e5286","import_time":"2026-05-21T12:05:52.75329947Z","id":"pypi/2026-05-selfservsweeper/selfservsweeper","modified_time":"2026-05-21T10:28:36.915892Z","versions":["0.1.7"]},{"sha256":"81843a6f21fe31627b1e97fdb8ffe41789c1f921c60512347bbf2b0c2fb30121","import_time":"2026-05-26T05:51:06.988260508Z","id":"IN-MAL-2026-003689","modified_time":"2026-05-21T01:29:54Z","versions":["0.1.7"],"source":"amazon-inspector"}]},"references":[{"type":"WEB","url":"https://bad-packages.kam193.eu/pypi/package/selfservsweeper"},{"type":"PACKAGE","url":"https://pypi.org/project/selfservsweeper/0.1.7/"}],"affected":[{"package":{"name":"selfservsweeper","ecosystem":"PyPI","purl":"pkg:pypi/selfservsweeper"},"versions":["0.1.7"],"database_specific":{"cwes":[{"cweId":"CWE-506","description":"The product contains code that appears to be malicious in nature.","name":"Embedded Malicious Code"}],"indicators":{"evidence_files":[{"sha256":"5f9e1acf96226cefa859c227add154a6d5ceadc74bcc3c87c0f6576db3e32c86","tlsh":"6d2361ba5d1aac219073cc1fa91bba47e75f43132a2d0917b87c52941f38026c1ecef9","path":"src/selfservsweeper/app.py"},{"tlsh":"38b012a386ac2221dd6654330c05a28b4105f1155d9508704ba09012cc548101083248","path":"src/selfservsweeper/api_url.pkl","sha256":"0c6089f82ae94a2e1eb7f00e8324f5c56febead2665834f2bd39ab60b54e16ef"},{"tlsh":"bc422057cc4bac0a81b2d25e7e50a48bf70823071b541827bebcc2582f74117abed79d","path":"src/selfservsweeper/selfservclient.py","sha256":"45931feae017e973cdf7ebb910e892ec571a8f656c55255eb30a75ea73e9621b"},{"path":"src/selfservsweeper/grammarly.py","sha256":"5488cb06f20b4fef6f30813506ab96b9e0a1cc3632b216d3d2efe669763564d2","tlsh":"64b18489ce8e952352b1974d2f34d572f72147a78b9019a3b87c81181ff97c1e6b1e4c"},{"sha256":"74f7332d9ff29d6e4ec8741efebd2539e173380d8be4f6b10820924cf9471ed2","tlsh":"ab31dedfac87d9832331031e5a0ec51ef68af7c7668aa521f12d64b43b2e164f0b444d","path":"src/selfservsweeper/config.py"}],"package_integrity":[{"filename":"selfservsweeper-0.1.7-py3-none-any.whl","hashes":{"blake2b_256":"c31ae3b99a91111f9721eee2f366560b12b48b857c49877792b731865ff150ba","md5":"fade751176939f310f09bd2279694338","sha256":"4cec3b7032b20f3e4d3634c3070326238e3ef06f597c4df8ccecb44def88b962"}},{"filename":"selfservsweeper-0.1.7.tar.gz","hashes":{"blake2b_256":"44eede4556bf5a179bda50e1fe1489ac012b32dcd0006b42fdda249da522f47b","md5":"be40bff066e70c645b34092c4b0b3452","sha256":"5ae1b7a6dc209c97434e0849857ebef3571f78ceba782f5923f93e07c1520a97"}}]},"source":"https://github.com/ossf/malicious-packages/blob/main/osv/malicious/pypi/selfservsweeper/MAL-2026-4221.json"}}],"schema_version":"1.7.5","credits":[{"name":"Amazon Inspector","contact":["actran@amazon.com"],"type":"FINDER"},{"name":"Kamil Mańkowski (kam193)","contact":["https://github.com/kam193","https://bad-packages.kam193.eu/"],"type":"ANALYST"}]}