{"id":"MAL-2026-18181","kind":"package","aliases":["MAL-2026-18181"],"related":[],"title":"Malicious code in test-brotli-testmetest (npm)","description":"test-brotli-testmetest 1.0.0 ships a rebuild of the data-pipeline-testmetest 2.0.1 credential stealer and runs it on `npm install`: its `install` script runs `node-gyp rebuild`, and the `binding.gyp` source `<!(env node index.js >/dev/null 2>&1; echo stub.c)` makes node-gyp run `index.js`, an obfuscated loader that decrypts a Brotli-compressed payload and pipes it into Bun. Published by npm account `testnewtestme2` on 2026-10-21.\n\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (d79f43824b57545810f0628c311b37ec5640a6c969053057d0158f46af613b33)\nThe package ships a binding.gyp whose sources field uses GYP command expansion `<!(env node index.js...; echo stub.c)` to shell out and run `node index.js` during node-gyp rebuild. The gyp target type is `none` and no C/C++ sources are shipped, so the file has no legitimate native-build purpose; its only effect is to invoke index.js at install time. index.js is a ~586KB char-code array decoded via a Caesar-shift substitution and passed to eval. The decoded body uses node:crypto createDecipheriv(\"aes-128-gcm\") with hardcoded hex key/IV/AAD to decrypt a large hex ciphertext, wrapped in a self-executing async IIFE with a swallowed catch. The combination of a build-config command-expansion execution vector, absence of any real native source, and a multi-layer obfuscated/encrypted opaque payload executed at install is the canonical install-time dropper shape — the installer runs attacker-supplied code on `npm install` with no visibility into what the decrypted payload does.","summary":null,"severity":"critical","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"test-brotli-testmetest","fixed":[],"affected":"= 1.0.0","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["malicious","package"],"not_affected_if":[],"how_to_check":null,"fix":null,"status":"open","published_at":"2026-10-21T18:00:00+00:00","first_seen_at":"2026-10-26T20:51:49+00:00","triaged_at":"2026-10-26T20:59:55+00:00","updated_at":"2026-10-26T21:05:48+00:00","category":"package","confidence":null,"triage":null,"analyst_status":null,"analyst_note":null,"search":"'-10':92C '-128':196C '-18181':11A,14A '-2026':10A,13A '-21':93C '/dev/null':59C '1':61C '1.0.0':25C '2':60C '2.0.1':35C '2026':91C '586kb':172C 'absenc':232C 'account':88C 'ae':195C 'amazon':105C 'amazon-inspector':104C 'array':176C 'async':214C 'attack':261C 'attacker-suppli':260C 'binding.gyp':54C,112C 'bodi':190C 'brot':6A,23C,77C 'brotli':17A 'brotli-compress':76C 'build':157C,225C 'build-config':224C 'bun':84C 'c/c':145C 'caesar':181C 'caesar-shift':180C 'canon':251C 'catch':219C 'char':174C 'char-cod':173C 'ciphertext':207C 'code':2A,175C,263C 'combin':221C 'command':118C,228C 'command-expans':227C 'compress':78C 'config':226C 'createdecipheriv':194C 'credenti':36C 'crypto':193C 'd79f43824b57545810f0628c311b37ec5640a6c969053057d0158f46af613b33':107C 'data':32C 'data-pipeline-testmetest':31C 'decod':177C,189C 'decrypt':74C,203C,273C 'detail':96C 'dropper':255C 'echo':62C,123C 'edit':99C 'effect':161C 'env':56C,120C 'eval':187C 'execut':213C,230C,246C 'expans':119C,229C 'field':115C 'file':151C 'gcm':197C 'gyp':50C,67C,117C,135C,138C 'hardcod':199C 'hex':200C,206C 'iif':215C 'index.js':58C,69C,122C,131C,165C,169C 'inspector':106C 'instal':43C,45C,167C,248C,253C,258C,266C 'install-tim':252C 'invok':164C 'key/iv/aad':201C 'larg':205C 'layer':242C 'legitim':154C 'line':102C 'loader':72C 'make':64C 'mal':9A,12A 'malici':1A,19B 'multi':241C 'multi-lay':240C 'nativ':156C,236C 'native-build':155C 'node':49C,57C,66C,121C,130C,134C,192C 'node-gyp':48C,65C,133C 'none':142C 'npm':8A,42C,87C,265C 'obfusc':71C 'obfuscated/encrypted':243C 'opaqu':244C 'packag':20B,109C 'pass':185C 'payload':79C,245C,274C 'per':94C 'pipe':81C 'pipelin':33C 'publish':85C 'purpos':158C 'real':235C 'rebuild':28C,51C,136C 'run':39C,47C,68C,129C,259C 'script':46C 'self':212C 'self-execut':211C 'shape':256C 'shell':126C 'shift':182C 'ship':26C,110C,148C 'sourc':55C,95C,103C,114C,146C,237C 'stealer':37C 'stub.c':63C,124C 'substitut':183C 'suppli':262C 'swallow':218C 'target':139C 'test':5A,16A,22C 'test-brotli-testmetest':4A,15A,21C 'testmetest':7A,18A,24C,34C 'testnewtestme2':89C 'time':168C,254C 'type':140C 'use':116C,191C 'vector':231C 'via':178C 'visibl':269C 'whose':113C 'wrap':208C","nicknames":[],"mitigations":[],"who_affected":null,"tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-21T18:00:00+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"osv-malicious","external_id":"MAL-2026-18181","url":"https://osv.dev/vulnerability/MAL-2026-18181","severity":"critical","published_at":"2026-10-21T18:00:00+00:00","modified_at":"2026-10-22T06:45:05+00:00","first_seen_at":"2026-10-26T20:51:49+00:00","fetched_at":"2026-10-26T20:51:49+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"}