{"id":"MAL-2026-17927","kind":"package","aliases":["MAL-2026-17927"],"related":[],"title":"Malicious code in fabtoolkit (PyPI)","description":"---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (e55333b9d934a04c029943e0e6fbf34fff7c1344e0d1964b6860bc02d322855d)\nfabtoolkit executes a payload (embedded as a CHILD string run via `subprocess.run([sys.executable,'-I','-c',CHILD],...)`) that fetches a JSON config from https://transfer.archivete.am/H2Uxm/fabdeploycheck-config.json with TLS verification disabled (`ssl._create_unverified_context()`) and dispatches on config-supplied `kind` values: `file` reads arbitrary filesystem paths, `run` executes attacker-supplied argv via subprocess, `http` issues attacker-chosen requests with Bearer tokens chained from previously-read files, `tcp` probes ports, and `revsh` forks a daemon that polls `base+'/'+ident+'-cmd.txt'` and pipes the returned bytes into `/bin/sh -c`, PUTting stdout/stderr back to the same host. Collected file contents, command output, HTTP responses, and probe results are packed into an in-memory zip and PUT to transfer.archivete.am under an attacker-chosen report name. Before daemonizing, the payload walks `/proc/*/cmdline` and SIGKILLs processes whose cmdlines contain `FABDRV3`, `fabdrv2`, or `connection ready`, enforcing single-instance persistence and clearing prior variants. The entry points `python -m fabtoolkit` and any import path reaching `selftest()`/`check()` trigger the payload. The destination is an anonymous public file-transfer host; config-controlled file reads enable harvesting of credentials such as `~/.aws/credentials` and `~/.ssh/*` along with cloud metadata via the `http` kind. The package has no legitimate functionality matching its naming.","summary":null,"severity":"critical","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"fabtoolkit","fixed":[],"affected":"= 0.1.2; = 0.1.1; = 0.1.0; = 0.2.1","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["malicious","package"],"not_affected_if":[],"how_to_check":null,"fix":null,"status":"open","published_at":"2026-10-19T02:26:31+00:00","first_seen_at":"2026-10-26T20:52:00+00:00","triaged_at":"2026-10-26T21:04:10+00:00","updated_at":"2026-10-26T21:04:10+00:00","category":"package","confidence":null,"triage":null,"analyst_status":null,"analyst_note":null,"search":"'-17927':8A,11A '-2026':7A,10A '/.aws/credentials':216C '/.ssh':218C '/bin/sh':114C '/cmdline':158C '/h2uxm/fabdeploycheck-config.json':53C '/proc':157C 'along':219C 'amazon':26C 'amazon-inspector':25C 'anonym':199C 'arbitrari':69C 'argv':77C 'attack':75C,83C,148C 'attacker-chosen':82C,147C 'attacker-suppli':74C 'back':118C 'base':105C 'bearer':87C 'byte':112C 'c':43C,115C 'chain':89C 'check':191C 'child':36C,44C 'chosen':84C,149C 'clear':176C 'cloud':221C 'cmd.txt':107C 'cmdline':163C 'code':2A 'collect':123C 'command':126C 'config':49C,63C,206C 'config-control':205C 'config-suppli':62C 'connect':168C 'contain':164C 'content':125C 'control':207C 'credenti':213C 'daemon':102C,153C 'destin':196C 'detail':17C 'disabl':57C 'dispatch':60C 'e55333b9d934a04c029943e0e6fbf34fff7c1344e0d1964b6860bc02d322855d':28C 'edit':20C 'embed':33C 'enabl':210C 'enforc':170C 'entri':180C 'execut':30C,73C 'fabdrv2':166C 'fabdrv3':165C 'fabtoolkit':4A,12A,29C,184C 'fetch':46C 'file':67C,94C,124C,202C,208C 'file-transf':201C 'filesystem':70C 'fork':100C 'function':232C 'harvest':211C 'host':122C,204C 'http':80C,128C,225C 'ident':106C 'import':187C 'in-memori':137C 'inspector':27C 'instanc':173C 'issu':81C 'json':48C 'kind':65C,226C 'legitim':231C 'line':23C 'm':183C 'mal':6A,9A 'malici':1A,13B 'match':233C 'memori':139C 'metadata':222C 'name':151C,235C 'output':127C 'pack':134C 'packag':14B,228C 'path':71C,188C 'payload':32C,155C,194C 'per':15C 'persist':174C 'pipe':109C 'point':181C 'poll':104C 'port':97C 'previous':92C 'previously-read':91C 'prior':177C 'probe':96C,131C 'process':161C 'public':200C 'put':116C,142C 'pypi':5A 'python':182C 'reach':189C 'read':68C,93C,209C 'readi':169C 'report':150C 'request':85C 'respons':129C 'result':132C 'return':111C 'revsh':99C 'run':38C,72C 'selftest':190C 'sigkil':160C 'singl':172C 'single-inst':171C 'sourc':16C,24C 'ssl._create_unverified_context':58C 'stdout/stderr':117C 'string':37C 'subprocess':79C 'subprocess.run':40C 'suppli':64C,76C 'sys.executable':41C 'tcp':95C 'tls':55C 'token':88C 'transfer':203C 'transfer.archivete.am':52C,144C 'transfer.archivete.am/h2uxm/fabdeploycheck-config.json':51C 'trigger':192C 'valu':66C 'variant':178C 'verif':56C 'via':39C,78C,223C 'walk':156C 'whose':162C 'zip':140C","nicknames":[],"mitigations":[],"who_affected":null,"tier":null,"verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-19T02:26:31+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"osv-malicious","external_id":"MAL-2026-17927","url":"https://osv.dev/vulnerability/MAL-2026-17927","severity":"critical","published_at":"2026-10-19T02:26:31+00:00","modified_at":"2026-10-20T19:00:04+00:00","first_seen_at":"2026-10-26T20:52:00+00:00","fetched_at":"2026-10-26T20:52:00+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"}