{"id":"MAL-2026-17417","kind":"package","aliases":["MAL-2026-17417"],"related":[],"title":"Malicious code in beautifytext (PyPI)","description":"beautifytext 1.0.3 imports beautifyText/_compat.py from its __init__.py and from a setup.py install hook. That module starts a detached background process that registers the host (hostname, user, OS, working directory) with https://bleodw.wisp.uno, then polls it for jobs to run shell commands or read and write files, and posts the results back.\n\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (488a492f2e87fa16d545c2605cb1ca4eb18c5e912a8e1645248e7ababafc10f8)\nbeautifyText 1.0.3 is a backdoor disguised as a text utility. On `import beautifyText`, the package spawns a detached background Python process (via a module named `_compat`) that decodes a base64-obfuscated C2 URL (https://bleodw.wisp.uno) and enters a long-poll loop against `/work/{id}`. The command channel implements three job kinds: `exec` runs arbitrary shell commands via subprocess with `shell=True`, `pull` reads arbitrary files from the installer's host, and `push` writes arbitrary files to the installer's host, with results POSTed back to `/result`. On registration, host metadata (hostname, OS/release, Python version, USER/USERNAME, current working directory) is sent to `/register`, and `/heartbeat` maintains the session. setup.py installs an `install` and `develop` cmdclass override whose `run()` calls `_post_install()`, which imports `beautifyText._compat` and triggers the same beacon during `pip install`, so the backdoor activates on install even without a subsequent import. The C2 host is stored as a base64 literal (`_HOST_B64 = aHR0cHM6Ly9ibGVvZHcud2lzcC51bm8=`) and decoded at runtime to evade static string matching. The process is detached so it survives parent-process exit.\n\n## Source: kam193 (cba19cfc0b2bdeec177fafdffa10e730769079a14ece3bb4740bfc0ded9fef3b)\nDuring import, the package silently spans a separate process that waits for and executes remote commands.\n\n\n---\n\nCategory: MALICIOUS - The campaign has clearly malicious intent, like infostealers.\n\n\nCampaign: 2026-07-beautifytext\n\n\nReasons (based on the campaign):\n\n\n - rat\n\n\n - The package contains code to execute remote commands (probably limited to a specific set) on the victim's machine.","summary":null,"severity":"critical","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"beautifytext","fixed":[],"affected":"= 1.0.3; = 1.0.4; = 1.0.7","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["malicious","package"],"not_affected_if":[],"how_to_check":null,"fix":null,"status":"open","published_at":"2026-09-30T11:47:45+00:00","first_seen_at":"2026-10-26T20:51:59+00:00","triaged_at":"2026-10-26T21:08:21+00:00","updated_at":"2026-10-26T21:08:21+00:00","category":"package","confidence":null,"triage":null,"analyst_status":null,"analyst_note":null,"search":"'-07':286C '-17417':8A,11A '-2026':7A,10A '/heartbeat':184C '/register':182C '/result':166C '/work':123C '1.0.3':16C,81C '2026':285C '488a492f2e87fa16d545c2605cb1ca4eb18c5e912a8e1645248e7ababafc10f8':79C 'activ':215C 'ahr0chm6ly9ibgvvzhcud2lzcc51bm8':234C 'amazon':77C 'amazon-inspector':76C 'arbitrari':134C,144C,154C 'b64':233C 'back':65C,164C 'backdoor':84C,214C 'background':34C,98C 'base':289C 'base64':110C,230C 'base64-obfuscated':109C 'beacon':208C 'beautifytext':4A,12A,15C,80C,92C,287C 'beautifytext._compat':203C 'beautifytext/_compat.py':18C 'bleodw.wisp.uno':46C,114C 'c2':112C,224C 'call':198C 'campaign':277C,284C,292C 'categori':274C 'cba19cfc0b2bdeec177fafdffa10e730769079a14ece3bb4740bfc0ded9fef3b':257C 'channel':127C 'clear':279C 'cmdclass':194C 'code':2A,297C 'command':55C,126C,136C,273C,301C 'compat':105C 'contain':296C 'current':176C 'decod':107C,236C 'detach':33C,97C,247C 'detail':68C 'develop':193C 'directori':44C,178C 'disguis':85C 'edit':71C 'enter':116C 'evad':240C 'even':218C 'exec':132C 'execut':271C,299C 'exit':254C 'file':60C,145C,155C 'hook':28C 'host':39C,150C,160C,169C,225C,232C 'hostnam':40C,171C 'id':124C 'implement':128C 'import':17C,91C,202C,222C,259C 'infosteal':283C 'init':21C 'inspector':78C 'instal':27C,148C,158C,189C,191C,200C,211C,217C 'intent':281C 'job':51C,130C 'kam193':256C 'kind':131C 'like':282C 'limit':303C 'line':74C 'liter':231C 'long':119C 'long-pol':118C 'loop':121C 'machin':312C 'maintain':185C 'mal':6A,9A 'malici':1A,13B,275C,280C 'match':243C 'metadata':170C 'modul':30C,103C 'name':104C 'obfusc':111C 'os':42C 'os/release':172C 'overrid':195C 'packag':14B,94C,261C,295C 'parent':252C 'parent-process':251C 'per':66C 'pip':210C 'poll':48C,120C 'post':62C,163C,199C 'probabl':302C 'process':35C,100C,245C,253C,266C 'pull':142C 'push':152C 'py':22C 'pypi':5A 'python':99C,173C 'rat':293C 'read':57C,143C 'reason':288C 'regist':37C 'registr':168C 'remot':272C,300C 'result':64C,162C 'run':53C,133C,197C 'runtim':238C 'sent':180C 'separ':265C 'session':187C 'set':307C 'setup.py':26C,188C 'shell':54C,135C,140C 'silent':262C 'sourc':67C,75C,255C 'span':263C 'spawn':95C 'specif':306C 'start':31C 'static':241C 'store':227C 'string':242C 'subprocess':138C 'subsequ':221C 'surviv':250C 'text':88C 'three':129C 'trigger':205C 'true':141C 'url':113C 'user':41C 'user/username':175C 'util':89C 'version':174C 'via':101C,137C 'victim':310C 'wait':268C 'whose':196C 'without':219C 'work':43C,177C 'write':59C,153C","nicknames":[],"mitigations":[],"who_affected":null,"tier":null,"verified":{},"analyst_revisit_at":null,"first_public_at":"2026-09-30T11:47:45+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"osv-malicious","external_id":"MAL-2026-17417","url":"https://osv.dev/vulnerability/MAL-2026-17417","severity":"critical","published_at":"2026-09-30T11:47:45+00:00","modified_at":"2026-10-08T20:30:04+00:00","first_seen_at":"2026-10-26T20:51:59+00:00","fetched_at":"2026-10-26T20:51:59+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}