Why does mathmain need an encrypted loader?

(safedep.io)

86 points | by abhisek 3 hours ago ago

23 comments

  • j2kun 2 hours ago

    Why in the world would that specific 3x3 matrix be a trigger for an attack? Are they trying to find someone doing some particular kind of numerical analysis?

    • zarzavat 2 hours ago

      Presumably it's so it can be used as a subdependency for setting up an attack in a popular, legitimate package, e.g. via a pull request. The code in the legitimate package would not arouse suspicion at all.

      • krackers 2 hours ago

        Now I'm curious what the target was. Are there any notable classes of programs/problems where you'd do an LU decomposition of this specific matrix?

    • ajkjk an hour ago

      Perhaps they just need a way to sneakily activate it? Or perhaps they have a target application which they know uses that. This method suggests a supply chain attack where a valid contributor to a library 'accidentally' includes this package and the hack carries out before anyone notices.

      My guess is that it's crypto related but of course it could be anything.

    • TimedToasts 29 minutes ago

      A status code for (industrial/the-man) equipment? You could target specific environments by activating on obscure error codes that can be remotely triggered.

      Aka If someone from the outside can make your equipment emit X internally, they can target X in some way.

    • tranceylc 2 hours ago

      I would assume it’s actually so they can allow it to spread before it gets activated. Then do something that affects the entire chain of package dependencies

    • coder-pm 2 hours ago

      This matrix is not a condition, it’s a key. JSON.stringify with it’s data goes to the scrypt as a password and that creates an AES-256-GCM key. There is no if, every other input won’t decrypt. That’s why no one will get payload from the package without knowing the exact input.

      • stymaar an hour ago

        1. “The X is not Y, it's Z” 2. 3 months old account

        Bad bot.

        (I still wonder what these not operators have to gain in that process, but they sure want HN karma).

        • smokel 35 minutes ago

          Interestingly, the presumed bot uses unicode apostrophes (’) instead of ', yet misspells "its".

  • WorldMaker an hour ago

    A lot of this seems to be a reminder that the CommonJS module format should just be left to die already. Not that you can't pull similar tricks with `await import()` in ESM, but you can't easily grep an entire dependency for dynamic `require()` half as easily as you can can `grep import\s*\(` for dynamic import and analysis tools for static `import` keyword are easy to use/build rather than no such thing for CommonJS.

    Someone thought I was joking when I said I always check JSR before NPM now, because I trust ESM so much more than CommonJS.

    • bastawhiz 20 minutes ago

      This is only partially true: dynamic imports are syntax (like super) but that's not a huge deterrent to hiding them. You could easily do `i = x => import(x)` to obfuscate the imports. Suddenly something looking like `await globalThis[computedValueEqualToI]` is doing imports. You still know stuff is being imported, you just have no idea what without a hell of a lot of effort, which is almost exactly the same effort as with require().

  • nextzck 2 hours ago

    Fascinating how intricate the target selection is on this

  • hiddenvulkcan 2 hours ago

    I actually came across someone that cracked it (or use Claude/China to crack it)

    Turns out the second stage is completely broken, which is even more odd..

    https://research.veryserious.systems/lusolve-and-you-shall-r...

  • fshafique 2 hours ago

    Does the FBI or any other law-enforcement office follow up on these backdoors? Is this considered a crime, or even conspiracy to commit a crime, or is it only the act of using the backdoor that's a crime?

    I can also see that it's still up in NPM without any warning of any kind: - https://www.npmjs.com/package/mathmain

    But the Github repo for the package and the author are down: - https://github.com/allendev12 - https://github.com/allendev12/mathmain

    • altairprime 2 hours ago

      > This package contained malicious code and was removed from the registry by the npm security team.

  • TZubiri 2 hours ago

    My strategy of not using dependencies at all seems to be getting stronger everyday.

    Also no LLM generated skipping this hypetrain completely. Just hand written code I can personally vouch for. Code in exchange for cash, this is professional business, Boss.

    Btw, I'm available for hire, preferably by Pre Market Fit or pre-MVP startups, email in profile.

    • VorpalWay an hour ago

      So, where do you draw the line? Do you accept having an OS? Because that is a huge dependency. So I assume you run directly on BIOS or UEFI? But even those are fairly sizable on modern systems.

      • TZubiri 41 minutes ago

        >So, where do you draw the line? Do you accept having an OS?

        Yes I accept using an OS usually, I guess there's much more than could fit on a single catchy sentence, but there's a clear policy.

        Operating System is the biggest exception, for Windows it's pretty simple to carve out everything that is manufactured by Microsoft itself. But for the main Linux OS (Debian/RHEL), I include everything that is distributed by the main package manager (apt/yum) as allowed by the OS policy exception. (On Windows, this is equivalent to adding software packaged and signed by microsoft, like Git).

        Alternative package managers like flatpak or snap are against my personal policy, not only are they very bloaty, but they kind of break the OS monopoly and push towards less safe supply chains, if it's not in apt/yum, then I don't use it.

        > So I assume you run directly on BIOS or UEFI?

        I have gone that route, but only experimentally, it's not very hard to get C compiled binaries to run and interface with keyboard and display through BIOS, but there's a lot of extra work that needs to be done incrementally, in order to use features in the sequence that they have historically been available, like 16 bit, 32 bit, 64 bits, 4GB memory. If you think of Wirth's law, this might actually be an effective long-term pacing strategy.

        But I'm not that hardcore personally, not for lack of want, in a professional settings I pull towards the pragmatic side and start conceding to stuff like using an OS, maybe using one or two packages. I would probably revisit booting directly to binary if any startup I work with hits a home run and needs to upgrade to at least 10k+ concurrent users. It's like one step removed from an ASIC, which is a stage almost no company enters, but I would have definitely have passed the baton at that stage, custom hardware is another discipline.

        >But even those are fairly sizable on modern systems.

        Well not BIOS, but UEFI and device drives certainly are. BIOS would just be some (mostly unwritten) standards on how to initialize, then it dissapears. Of course hardware itself is a dependency, and I'm definitely not going to be summoning computing from heat, sand, and electricity, but my line is definitely at the OS and above.

        One final exception that wasn't mentioned is the programming language and its 'built in libraries'. I use the programming language along with its standard distribution. For Python (my main language), that means I don't use pip, but I might use 'import sockets' (it's almost the same as using cffi and glibc anyways). There's an analogue in almost all languages, node with npm, java with maven, php with composer, I just don't add those kinds of dependencies if I have control over it. I chmod ugo-rwx requirements.txt to avoid other engineers from adding leftpadisms.

        That's not to say that it never happens, maybe even I imported Flask to meet a deadline, and maybe there's that perfect library from a good source that someone else suggests and it gets accepted, but it doesn't hurt to add some friction, it catches a lot of trash packages from being added to the foundation of a startup, which give almost no benefits at great expense over the lifecycle of the core.

        The end result has a few advantages if I may explicitly sell myself and my strategy:

        - Basal stack: Instead of having to hire yarn,yum,pnpm,react,tailwind,buzzword,jev,shadcn, developers (developers of very specific modern deep tech stacks that will only be used and popular during a very narrow timeline), if the startup grows, they have a much broader space to search talent from, which means that hiring can occur across other search parameters, MOST importantly business domain knowledge. I think it's much more productive to hire devs that are interested in dentistry if you are a dentistry startup, rather than devs that know, say, the intersection of Kubernetes, FastAPI, Kafka and some AWS Branded tech.

        - Long term Foundation: Usually the simpler basal tech takes a bit longer to get started, as opposed to exclusively prioritizing delivery speed, but it allows for reasonable development speeds in later stages.

        We sometimes call it tech debt, in this case the mechanics create debt by: increasing the Lines of Code count (you should count the lines of the dependencies you import), and by reducing the personnel system knowledge.

        It is a tradeoff yes, but it isn't really a huge advantage to be able to get the first version up in 2 hours, as opposed to 1 month. Much less getting a first version up in 15 seconds with a prompt. I'd rather just work with someone that can spend like 5K in a 1 month prototype, and thinks about pacing for the long term winner-takes-all condition, rather than trying to save 5K and having a prototype in 2 hours, (or in 15 seconds). Nothing wrong with that, but it just doesn't seem like I would fit in there. If someone wants to setup their prototype in 2 hours, they don't need me, and if they ever call me, we are going to be building the 1-month prototype from scratch, and using the vibecoded or Framework prototype as a Proof of Concept, not an architectural base.

        - Proprietary advantage/Moat: Haven't seen this mentioned elsewhere, but code is the main asset of a company, if you import a lot of code to achieve your goal, sure you accomplish that, but you have not accomplished a very distinctive or defensible advantage. Strategically it's more profitable to pursue the kinds of challenges you need to write code for, than the ones you need to import and glue together components for.

        - Strategic conditioning: Similar to the above, but you want to think and write code at the same time, if you use someone else's framework you think according to their terms, whether that is to confer them a strategic advantage, or whether the goal of thinking is to reduce development costs. The kind of thinking that occurs in software development should ideally be as free as possible from the influences of actors that are not goal-aligned with the company's mission.

        Opinionated software is great, but ideally other software should be incorporated with a commercial relationship in the middle, carved out by some other exception. And even then, their goals should be acknowledged strategically, if you are building, say: a DRM or surveillance system on top of Debian, that's bound to have some sort of conflict. Similarly using Microsoft for a public hospital project is another conflict that is worth at least taking note of.

        - Personnel knowledge: I pointed to this, but the knowledge of personnel of the system AND the business domain is relevant. The objective of making software is not JUST to achieve the end-goal, the knowledge acquired in the process of creating that software is a valuable byproduct for both operational and strategic reasons. Similar to writing an essay, it's not just that we want to have the essay in order to slap it into someone else (well maybe sloppers do), but that we actually gain insights and develop our own thoughts while we write it.

        - User/Producer separation: For the cases where the product is about LLMs or DevTools. If you both consume dev tools and build devtools, or consume LLMs to code and are building LLM features, I find that people tend to get lost in an unhealthy spiral more often, it's a dangerous task to endeavor, if there's ever a time not to use LLMs to code, it's when your product actually includes LLMs as a feature for users. Which is even a more important goal, right? What's more important, putting this super technology at the hands of the user? Or consuming this super technology to accelerate development?

        ---

        Regarding costs this is not particularly expensive either, it's not like you are missing out on a particularly valuable revolution if you miss out on abusing Open Source supply chains or on abusing vibecoding thingies. An idea-stage startup that hires me to build an MVP would cost like 5K and a month, maybe if they really want to polish it, that's 6 months which is like 30K, plus the (co)founder's salary, whatever that is, as it's not hands-off work.

        I'm sure to some the idea of saving 29K and spending 1K in AI subscriptions is enticing, maybe they can even attempt vibecoding before hiring talent, for sure, that's valid. It even helps refining and conveying the idea, and getting more accurate cost and feasibility estimations. But it's also a perfectly skippable step, that bootstrapped investment route has been used for decades now.

    • iLoveOncall 2 hours ago

      Let us know in 2838 when you finish your first program, would love to check it out!

  • zzril 2 hours ago

    Had I found sthg like this, I'd be proud to tell everyone and certainly enjoy doing the writeup. But this smells like it was ai-written...

    • mavamaarten an hour ago

      Yeah lots of weird emphasis on things a human wouldn't care about. And emphasis on what it isn't, rather than what it is. It's not Y, it's X. And there are two files!!!

  • altairprime 2 hours ago

    > We found a remote access implant hidden inside [email protected], an npm package that copies the popular mathjs library.

    The NPM package not named in the clickbait-y post title is “mathmain@1.0.0”, for those who run into this particular site obstacle; the later packages also named are “mathsbase” and “math-universe”. (EDIT: I see the submission title has been updated, so that’s my complaint addressed, thanks mods!)

    Safedep, if you’re reading this, perhaps you should reconsider having that site feature applied to your post — or if it’s something you enabled in, say, Cloudflare, perhaps file a support ticket noting that their email protection is hiding package version strings.

    • QuantumNomad_ 2 hours ago

      Probably Cloudflare. For me it shows the package name rather than a redaction. But from memory, Cloudflare email protection redacts it that way in the HTML and then adds a little JS to put it back in which might also do some kind of check to see if it thinks you are a real user before unredacting it.