On July 31, my development machine began behaving in ways that did not add up. Files disappeared. Parts of repositories were overwritten. Comments and code appeared that I could not account for.

01 · Initial signal

When normal development noise stopped looking normal

My first suspicion was the tooling closest to the code. I had been using AI coding assistants, and public discussion at the time made them an easy explanation. But the available histories and logs did not explain the changes.

I reinstalled the operating system. For a few days, everything appeared clean. Then the same class of unexplained changes returned. That was the important turning point: a reinstall had removed the visible symptoms without removing the path that brought them back.

A recurring anomaly is evidence. Treat it as a system behavior, not an inconvenience.

02 · Root clue

Obfuscated JavaScript where build configuration should have been

I widened the review to repositories, Git history, configuration files, and dependencies. Inside postcss.config.js, I found obfuscated JavaScript that had no legitimate reason to be there.

This was not ordinary minified dependency code. It was making network requests, querying Ethereum RPC endpoints, and searching transactions associated with a hardcoded wallet address. A build configuration file had become an execution entry point.

Why configuration files matter

Build tools execute them with Node.js privileges. A familiar filename does not make the code inside it passive or trustworthy.

03 · Network resolution

Using an Ethereum transaction as a moving signpost

The resolver followed the wallet’s latest outbound transaction, took the destination Ethereum address, and decoded bytes from that address into IP addresses. Instead of embedding a fixed command-and-control address in the malware, the operator could change the infrastructure by making another blockchain transaction.

The resolved host was then used to contact remote endpoints, retrieve additional payloads, decode them, and execute them through Node. The behavior aligned with the technique reported as NullReceiver in trojanized npm packages; that similarity is a technical indicator, not by itself proof of attribution.

hardcoded walletlatest outbound transactiondestination bytesC2 IPpayload execution

04 · Expanded search

The extension said “font.” The file header said otherwise.

Another useful indicator was a set of .woff2 files that did not contain valid WOFF2 headers. A genuine WOFF2 file begins with the expected wOF2 magic bytes. These files had the right extension but the wrong identity.

I built a small scanner to turn the investigation into a repeatable check across the machine and repositories. It looked for:

  • known malicious signatures and suspicious package names, including tailwind-anim and scrollbar-hide-plugin;
  • unexpected node -e processes and known C2 connections;
  • the attacker wallet indicator and invalid WOFF2 files;
  • related traces hidden in Git history across branches.

05 · Practical takeaway

Developer environments are part of the production supply chain

Developers clone repositories, install packages, run build tools, and enable extensions every day. Each action introduces executable code into an environment that often has access to source, credentials, cloud infrastructure, and deployment systems.

The first signal of compromise may not be a security alert. It may be a changed comment, an unfamiliar line, a missing file, or a configuration diff that seems too small to investigate.

01

Verify unexplained changes

Do not normalize code or files changing without an accountable source.

02

Inspect executable config

Review build files and package scripts with the same care as application code.

03

Trust file signatures

Extensions are labels. Magic bytes and actual content establish file type.

04

Search history, not only HEAD

Indicators may remain in branches, prior commits, caches, or generated artifacts.