{"id":"MAL-2026-15925","kind":"package","aliases":["MAL-2026-15925"],"related":[],"title":"Malicious code in tailwind-contact-forms (npm)","description":"---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (956943b584d41e6307a8bb5bfdd821bd062f5f9f4776b912ee05ce41fe1829e5)\nThe package is published under a name that mimics the Tailwind CSS forms plugin and its package.json points repository at tailwindlabs/tailwindcss-forms, while the actual main entry src/index.js is a heavily obfuscated Node loader (obfuscator.io-style rotated string array _0x18ab with 303 entries, decoder _0x35ba, control-flow-object dispatch). On require(), the loader constructs an Etherscan-style indexer URL and Ethereum JSON-RPC endpoint list (eth.blockscout, eth.drpc.org, ethereum-rpc.publicnode.com, eth-mainnet.public.blastapi.io) from decoded string fragments, queries eth_blockNumber / eth_getBlockByNumber / eth_getTransactionCount and the txlist API for hardcoded attacker addresses (0xa322E5f3...9aDC2490Ef and 0x...D311D3080e...6f0121063e), and assembles a runtime code payload injected via global['_V...']/global['_t_u']/global['_t_s']/global['_H']/global['_H2']. The loader imports node:child_process.spawn to execute the retrieved payload. This is the EtherHiding pattern: the attacker updates transaction data on-chain to rotate second-stage code without republishing the package, and every consumer that loads tailwind-contact-forms in their tailwind.config.js executes whatever the attacker's on-chain transaction currently points to. A Tailwind plugin has no legitimate need for obfuscation, Ethereum RPC access, block-explorer indexers, or child_process spawning.","summary":null,"severity":"critical","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"tailwind-contact-forms","fixed":[],"affected":"= 0.5.12; = 0.5.1; = 0.5.5; = 0.5.9; = 0.5.8","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["malicious","package"],"not_affected_if":[],"how_to_check":null,"fix":null,"status":"open","published_at":"2026-09-04T06:48:54+00:00","first_seen_at":"2026-11-11T21:29:24+00:00","triaged_at":"2026-11-11T21:30:27+00:00","updated_at":"2026-11-11T21:30:27+00:00","category":"package","confidence":null,"triage":null,"analyst_status":null,"analyst_note":null,"search":"'-15925':11A,14A '-2026':10A,13A '/global':141C,144C,147C,149C '0x':128C '0x18ab':73C '0x35ba':78C '0xa322e5f3':125C '303':75C '6f0121063e':130C '956943b584d41e6307a8bb5bfdd821bd062f5f9f4776b912ee05ce41fe1829e5':34C '9adc2490ef':126C 'access':219C 'actual':58C 'address':124C 'amazon':32C 'amazon-inspector':31C 'api':120C 'array':72C 'assembl':132C 'attack':123C,167C,199C 'block':221C 'block-explor':220C 'blocknumb':112C 'chain':173C,203C 'child':225C 'child_process.spawn':155C 'code':2A,135C,179C 'construct':88C 'consum':186C 'contact':6A,17A,191C 'control':80C 'control-flow-object':79C 'css':46C 'current':205C 'd311d3080e':129C 'data':170C 'decod':77C,107C 'detail':23C 'dispatch':83C 'edit':26C 'endpoint':100C 'entri':60C,76C 'eth':111C,113C,115C 'eth-mainnet.public.blastapi.io':105C 'eth.blockscout':102C 'eth.drpc.org':103C 'ethereum':96C,217C 'ethereum-rpc.publicnode.com':104C 'etherhid':164C 'etherscan':91C 'etherscan-styl':90C 'everi':185C 'execut':157C,196C 'explor':222C 'flow':81C 'form':7A,47C,192C 'forms':18A 'fragment':109C 'getblockbynumb':114C 'gettransactioncount':116C 'global':139C 'h':148C 'h2':150C 'hardcod':122C 'heavili':64C 'import':153C 'index':93C,223C 'inject':137C 'inspector':33C 'json':98C 'json-rpc':97C 'legitim':213C 'line':29C 'list':101C 'load':188C 'loader':67C,87C,152C 'main':59C 'mal':9A,12A 'malici':1A,19B 'mimic':43C 'name':41C 'need':214C 'node':66C,154C 'npm':8A 'obfusc':65C,216C 'obfuscator.io':68C 'object':82C 'on-chain':171C,201C 'packag':20B,36C,183C 'package.json':51C 'pattern':165C 'payload':136C,160C 'per':21C 'plugin':48C,210C 'point':52C,206C 'process':226C 'publish':38C 'queri':110C 'repositori':53C 'republish':181C 'requir':85C 'retriev':159C 'rotat':70C,175C 'rpc':99C,218C 'runtim':134C 'second':177C 'second-stag':176C 'sourc':22C,30C 'spawn':227C 'src/index.js':61C 'stage':178C 'string':71C,108C 'style':69C,92C 'tailwind':5A,16A,45C,190C,209C 'tailwind-contact-form':4A,189C 'tailwind-contact-forms':15A 'tailwind.config.js':195C 'tailwindlabs/tailwindcss-forms':55C 'transact':169C,204C 'txlist':119C 'u':143C 'updat':168C 'url':94C 'v':140C 'via':138C 'whatev':197C 'without':180C","nicknames":[],"mitigations":[],"who_affected":null,"tier":null,"verified":{},"analyst_revisit_at":null,"fix_status":null,"audience":null,"plain_action":null,"pkeys":["tailwindcontactforms"],"ptokens":["contact","forms","tailwind"],"labels":["critical","malicious","npm","package"],"campaign_type":null,"search_a":"'-15925':11A,14A '-2026':10A,13A 'code':2A 'contact':6A,17A 'form':7A 'forms':18A 'mal':9A,12A 'malici':1A 'npm':8A 'tailwind':5A,16A 'tailwind-contact-form':4A 'tailwind-contact-forms':15A","search_b":"'malici':19B 'packag':20B","search_c":"'/global':141C,144C,147C,149C '0x':128C '0x18ab':73C '0x35ba':78C '0xa322e5f3':125C '303':75C '6f0121063e':130C '956943b584d41e6307a8bb5bfdd821bd062f5f9f4776b912ee05ce41fe1829e5':34C '9adc2490ef':126C 'access':219C 'actual':58C 'address':124C 'amazon':32C 'amazon-inspector':31C 'api':120C 'array':72C 'assembl':132C 'attack':123C,167C,199C 'block':221C 'block-explor':220C 'blocknumb':112C 'chain':173C,203C 'child':225C 'child_process.spawn':155C 'code':135C,179C 'construct':88C 'consum':186C 'contact':191C 'control':80C 'control-flow-object':79C 'css':46C 'current':205C 'd311d3080e':129C 'data':170C 'decod':77C,107C 'detail':23C 'dispatch':83C 'edit':26C 'endpoint':100C 'entri':60C,76C 'eth':111C,113C,115C 'eth-mainnet.public.blastapi.io':105C 'eth.blockscout':102C 'eth.drpc.org':103C 'ethereum':96C,217C 'ethereum-rpc.publicnode.com':104C 'etherhid':164C 'etherscan':91C 'etherscan-styl':90C 'everi':185C 'execut':157C,196C 'explor':222C 'flow':81C 'form':47C,192C 'fragment':109C 'getblockbynumb':114C 'gettransactioncount':116C 'global':139C 'h':148C 'h2':150C 'hardcod':122C 'heavili':64C 'import':153C 'index':93C,223C 'inject':137C 'inspector':33C 'json':98C 'json-rpc':97C 'legitim':213C 'line':29C 'list':101C 'load':188C 'loader':67C,87C,152C 'main':59C 'mimic':43C 'name':41C 'need':214C 'node':66C,154C 'obfusc':65C,216C 'obfuscator.io':68C 'object':82C 'on-chain':171C,201C 'packag':36C,183C 'package.json':51C 'pattern':165C 'payload':136C,160C 'per':21C 'plugin':48C,210C 'point':52C,206C 'process':226C 'publish':38C 'queri':110C 'repositori':53C 'republish':181C 'requir':85C 'retriev':159C 'rotat':70C,175C 'rpc':99C,218C 'runtim':134C 'second':177C 'second-stag':176C 'sourc':22C,30C 'spawn':227C 'src/index.js':61C 'stage':178C 'string':71C,108C 'style':69C,92C 'tailwind':45C,190C,209C 'tailwind-contact-form':189C 'tailwind.config.js':195C 'tailwindlabs/tailwindcss-forms':55C 'transact':169C,204C 'txlist':119C 'u':143C 'updat':168C 'url':94C 'v':140C 'via':138C 'whatev':197C 'without':180C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-09-04T06:48:54+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"osv-malicious","external_id":"MAL-2026-15925","url":"https://osv.dev/vulnerability/MAL-2026-15925","severity":"critical","published_at":"2026-09-04T06:48:54+00:00","modified_at":"2026-11-11T21:15:16+00:00","first_seen_at":"2026-11-11T21:29:24+00:00","fetched_at":"2026-11-11T21:29:24+00:00","note":null}],"documents":[],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}