<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: pycanis</title>
    <description>The latest articles on DEV Community by pycanis (@pycanis).</description>
    <link>https://dev.to/pycanis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4061243%2F3c6d047a-da97-4244-a4f8-a2c8b5edd013.png</url>
      <title>DEV Community: pycanis</title>
      <link>https://dev.to/pycanis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pycanis"/>
    <language>en</language>
    <item>
      <title>I got offered a Web3 job on LinkedIn. The "codebase" was built to rob me.</title>
      <dc:creator>pycanis</dc:creator>
      <pubDate>Mon, 03 Aug 2026 19:31:04 +0000</pubDate>
      <link>https://dev.to/pycanis/title-suggestion-i-got-offered-a-web3-job-on-linkedin-the-codebase-was-built-to-rob-me-e59</link>
      <guid>https://dev.to/pycanis/title-suggestion-i-got-offered-a-web3-job-on-linkedin-the-codebase-was-built-to-rob-me-e59</guid>
      <description>&lt;p&gt;A stranger messaged me on LinkedIn about a job in the Web3 space. Friendly, low pressure, said it sounded like a good fit. To show me what the team was building, they shared a private GitHub repository and asked me to spend "15 to 30 minutes running it and looking around" to see whether the project made sense to me.&lt;/p&gt;

&lt;p&gt;That repository was not a job assessment. It was a trap designed to steal from the developer who runs it. Here is what it actually was, how it works in plain language, and the red flags that let you spot this without being a security expert.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;The repo looks like a real, working crypto staking app. Most of it genuinely functions. That is the whole point: it needs to be convincing enough that you clone it and run it.&lt;/p&gt;

&lt;p&gt;Hidden inside is a single booby-trapped file, disguised as a harmless styling plugin. The moment you &lt;strong&gt;run or build&lt;/strong&gt; the project on your own machine, that file executes as a program with full access to your computer. It then quietly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;steals the passwords saved in your browser,&lt;/li&gt;
&lt;li&gt;steals cryptocurrency wallet data and browser wallet extensions like MetaMask,&lt;/li&gt;
&lt;li&gt;hunts your hard drive for anything that looks like a secret (seed phrases, private keys, &lt;code&gt;.env&lt;/code&gt; files, SSH keys),&lt;/li&gt;
&lt;li&gt;and opens a hidden remote connection so the attacker can control your machine and browse your files at will.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, none of this targets the app's "users". There is no scam website draining visitors' wallets. The victim is &lt;strong&gt;you, the developer&lt;/strong&gt;, the moment you try it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened to me
&lt;/h2&gt;

&lt;p&gt;I was suspicious from the first message. A recruiter I have never spoken to, handing me a whole codebase and asking me to run it before we have even had a real conversation, is odd. Running someone's code is not the same as reading it. But the ask seemed reasonable on the surface, "just have a look", so I started to look.&lt;/p&gt;

&lt;p&gt;Here is the part I want other developers to sit with, because it is where I nearly got caught.&lt;/p&gt;

&lt;p&gt;I did not open the project and start typing commands myself. I asked my AI coding agent to look at the repo: check the architecture, read the code, and explain what the project is and how it works. This is now a completely normal way to evaluate an unfamiliar codebase. Delegate the first pass to the agent.&lt;/p&gt;

&lt;p&gt;The problem: modern coding agents can &lt;strong&gt;run&lt;/strong&gt; code, not just read it. To "see how it works", an agent can quite reasonably decide to build the project or start the dev server. In this repo, that is exactly the trigger. The agent could have sprung the trap for me, without me ever typing the fatal command.&lt;/p&gt;

&lt;p&gt;I watched the agent work and noticed it was mostly running read-only commands to describe the project. Then it clicked: this thing &lt;em&gt;can&lt;/em&gt; execute code, and this is unfamiliar code I just downloaded from a stranger. That was the moment I stopped, and rewrote my instructions to tell the agent to treat the entire repository as hostile and never run or build anything. I then had it analyse the code statically, and that is when the payload turned up.&lt;/p&gt;

&lt;p&gt;If you take one thing from this: &lt;strong&gt;"just ask the AI to look at it" is not automatically safe.&lt;/strong&gt; An agent that can run commands is a loaded gun pointed at your own machine when the code is untrusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the trap works (plain language, then the details)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The plain version
&lt;/h3&gt;

&lt;p&gt;When you set up a JavaScript project, there are two separate steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install&lt;/strong&gt; the building blocks the project depends on (&lt;code&gt;npm install&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run or build&lt;/strong&gt; the project to actually start it (&lt;code&gt;npm run dev&lt;/code&gt;, &lt;code&gt;npm start&lt;/code&gt;, and so on).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most people assume the &lt;em&gt;install&lt;/em&gt; step is the dangerous one. This attack deliberately leaves the install step clean and safe, and hides the trap in the &lt;em&gt;run&lt;/em&gt; step, the thing you naturally do next to see the app working.&lt;/p&gt;

&lt;p&gt;To style a web page, this project uses a popular tool called Tailwind. Tailwind lets projects load small "plugins". Six of those plugins are real and tiny. The seventh is the weapon. When the project builds its styling, it loads that plugin, and the plugin is not styling code at all. It is a program that runs on your computer, with your permissions, doing everything listed above.&lt;/p&gt;

&lt;h3&gt;
  
  
  The technical details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The malicious file is &lt;code&gt;theme/js/auron-core.min.js&lt;/code&gt;, registered as a Tailwind plugin in &lt;code&gt;tailwind.config.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Its six sibling plugins are 101 to 299 bytes each. This one is &lt;strong&gt;4,073,468 bytes&lt;/strong&gt;, roughly 14,000 times larger. That size difference alone is visible from &lt;code&gt;ls -la&lt;/code&gt; before you read a single line.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm install&lt;/code&gt; does nothing (there are no install hooks). The payload fires on &lt;code&gt;npm run dev&lt;/code&gt;, &lt;code&gt;npm start&lt;/code&gt;, or &lt;code&gt;next build&lt;/code&gt;, because any CSS compilation loads the plugin.&lt;/li&gt;
&lt;li&gt;It only activates when &lt;code&gt;NODE_ENV === "development"&lt;/code&gt;, so it targets developers evaluating the repo and stays dormant in anything deployed to production, where it might get noticed.&lt;/li&gt;
&lt;li&gt;The file is heavily obfuscated (an &lt;code&gt;obfuscator.io&lt;/code&gt; build with a ~24,000-entry string table, control-flow flattening, and anti-debugging traps) so that a casual look, or even a naive dump, reads as noise rather than as a decoded payload.&lt;/li&gt;
&lt;li&gt;It fetches its real dependencies at runtime with &lt;code&gt;npm install ... --no-save&lt;/code&gt;, so they never appear in &lt;code&gt;package.json&lt;/code&gt; or the lockfile, then spawns a detached background process by piping the script over &lt;code&gt;stdin&lt;/code&gt;, so nothing malicious is ever written to disk.&lt;/li&gt;
&lt;li&gt;Command-and-control runs over a &lt;strong&gt;bare IP address&lt;/strong&gt; (&lt;code&gt;153.75.87.26&lt;/code&gt;, ports 8085 to 8087) with no domain name. That means there is no DNS lookup, so Pi-hole, NextDNS, AdGuard and corporate DNS filtering never see it. A clean DNS log here proves nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The whole repo is a stage set
&lt;/h2&gt;

&lt;p&gt;What makes this dangerous is not cleverness in the payload, it is the plausibility around it. The attackers built an entire believable project to buy the few seconds between "run it" and "infected".&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fabricated git history.&lt;/strong&gt; 245 commits faking a maintained project. The tell: every backdated commit is stamped at exactly &lt;code&gt;12:00:00&lt;/code&gt;, one per day, with templated, nonsensical messages like "Fix bug in metamask.svg" and "Polish code in placeholder.svg". The payload was slipped in under an innocuous "Polish code" commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A pre-emptive alibi.&lt;/strong&gt; The README contains a tidy "Security Note" explaining away an unrelated backend folder as harmless legacy code. A comment that answers a suspicious question &lt;em&gt;before you have asked it&lt;/em&gt; is itself a warning sign.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load-bearing real code.&lt;/strong&gt; Genuinely clean, competent code sits right next to the payload, in exactly the files a reviewer is most likely to open. The authenticity is the camouflage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A facade that is hollow where nobody looks.&lt;/strong&gt; The "smart contracts" cannot even compile. The custom theme emits CSS classes the app never uses. The "legacy backend" is 90 files of an unrelated e-commerce app used as padding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Red flags you can spot without being a security expert
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A stranger asks you to run their code.&lt;/strong&gt; A recruiter you have never spoken to, sharing a whole repo and asking you to &lt;em&gt;run&lt;/em&gt; it as a "task", is the entire scam. Reading code is low risk. Running it is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web3 or crypto plus urgency-free friendliness.&lt;/strong&gt; These campaigns lean on a plausible, pleasant job offer. The niceness is part of the method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One file wildly bigger than its neighbours.&lt;/strong&gt; &lt;code&gt;ls -la&lt;/code&gt; is a security tool. A single file thousands of times larger than its siblings is a giant flashing sign.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comments or notes that pre-emptively reassure you.&lt;/strong&gt; "Don't worry, this only runs in Node, not the browser." That is not reassurance. In Node it has your filesystem, your network, and no browser sandbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A config file that loads local files.&lt;/strong&gt; &lt;code&gt;tailwind.config&lt;/code&gt;, &lt;code&gt;postcss.config&lt;/code&gt;, &lt;code&gt;next.config&lt;/code&gt;, &lt;code&gt;vite.config&lt;/code&gt; and &lt;code&gt;webpack.config&lt;/code&gt; all run real code at build time. Every &lt;code&gt;require()&lt;/code&gt; of a local path in a config file is worth a look.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perfect-looking but empty history.&lt;/strong&gt; Identical commit timestamps, templated messages that do not match the files they touch, and author names with empty emails are cheap to spot once you know to look.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What to do if you have already run something like this
&lt;/h2&gt;

&lt;p&gt;If you cloned and installed but never built or ran it, you are almost certainly fine. Installing alone did not trigger it. Delete the checkout, remove any dev container or volume, and report the repo.&lt;/p&gt;

&lt;p&gt;If you &lt;strong&gt;did&lt;/strong&gt; run or build it, treat the machine as fully compromised and act quickly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disconnect the machine from the network before doing anything else.&lt;/li&gt;
&lt;li&gt;Assume every password saved in any Chromium-based browser is stolen. Rotate all of them.&lt;/li&gt;
&lt;li&gt;Move funds out of any wallet whose seed phrase or keystore was anywhere on that machine, and treat those seeds as burned.&lt;/li&gt;
&lt;li&gt;Rotate SSH keys, cloud API keys, and every secret in every &lt;code&gt;.env&lt;/code&gt; on the machine.&lt;/li&gt;
&lt;li&gt;Rotate anything that was in your clipboard during the exposure window (it watches the clipboard continuously, which is enough to catch a pasted wallet address).&lt;/li&gt;
&lt;li&gt;If you use WSL, treat the entire Windows host as in scope, not just the Linux side. This malware pivots from WSL into &lt;code&gt;C:&lt;/code&gt; drive user folders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If in any doubt, get help from someone who does incident response. Rotating credentials is cheap. Regret is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A safe &lt;code&gt;npm install&lt;/code&gt; does not mean a safe build. Supply-chain awareness fixates on install hooks. This attack ignores them and uses ordinary build configuration, which is just executable code with no sandbox.&lt;/li&gt;
&lt;li&gt;Read the config files, not only the source. That is where untrusted code gets to run.&lt;/li&gt;
&lt;li&gt;Compare file sizes. One outlier was the entire tell.&lt;/li&gt;
&lt;li&gt;Treat pre-emptive "this is safe" comments as signals, not comfort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your AI agent can be the attack vector.&lt;/strong&gt; If you delegate "have a look at this repo" to an agent that can execute commands, you have handed untrusted code a way to run. Sandbox it, or explicitly tell the agent to treat the repo as hostile and never build or run it.&lt;/li&gt;
&lt;li&gt;When you evaluate anything untrusted, do it in a throwaway virtual machine or container. Isolation is what saved me. Note that a bind-mounted folder still exposes that folder, so isolation is a spectrum, not a switch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The friendly job offer, the working app, the detailed roadmap and the busy commit history all exist for one reason: to earn the few seconds of trust between "run it" and execution. Do not give it to a stranger.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Indicators of compromise (safe to share): repo &lt;code&gt;BitAngelsLabs/auron&lt;/code&gt;; malicious file &lt;code&gt;theme/js/auron-core.min.js&lt;/code&gt; at 4,073,468 bytes; C2 at &lt;code&gt;153.75.87.26&lt;/code&gt; on ports 8085, 8086 (&lt;code&gt;/upload&lt;/code&gt;), 8087; runtime install of &lt;code&gt;sql.js&lt;/code&gt;, &lt;code&gt;socket.io-client&lt;/code&gt;, &lt;code&gt;node-pty&lt;/code&gt; via &lt;code&gt;--no-save&lt;/code&gt;; background process &lt;code&gt;node --max-old-space-size=4096 --no-warnings -&lt;/code&gt;. If you found this repo, report it to GitHub as malware and warn anyone who may have cloned it. The malicious file itself should not be shared or re-hosted.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>web3</category>
      <category>career</category>
    </item>
  </channel>
</rss>
