[HN Gopher] GitLab discovers widespread NPM supply chain attack
       ___________________________________________________________________
        
       GitLab discovers widespread NPM supply chain attack
        
       Author : OuterVale
       Score  : 368 points
       Date   : 2025-11-27 15:36 UTC (1 days ago)
        
 (HTM) web link (about.gitlab.com)
 (TXT) w3m dump (about.gitlab.com)
        
       | ChrisArchitect wrote:
       | Discussion: https://news.ycombinator.com/item?id=46032539
        
         | ares623 wrote:
         | Phew, thought it was another one.
        
           | gchamonlive wrote:
           | > Our internal monitoring system has uncovered multiple
           | infected packages containing what appears to be an evolved
           | version of the "Shai-Hulud" malware.
           | 
           | Although it's not entirely new, it's something else.
        
             | prophesi wrote:
             | Gitlab's post and the linked discussion thread are both
             | from November 24th 2025. I may be misreading the parent
             | comment, but I'm personally thankful there isn't a Return
             | of the Return of Shai-Hulud, as I assumed this was a third
             | recent incident. For those concerned about these attacks,
             | Helixguard's post (from the linked discussion) lists out
             | the packages they found to be effected, while Gitlab's post
             | gives more information on how the attack works. Since it's
             | self-propagating though, assume the list of affected
             | packages might be longer as more NPM tokens are
             | compromised.
        
       | TZubiri wrote:
       | Not all the npm packages, but always an npm package
        
         | cyanydeez wrote:
         | While you think this is a producer problem, it's simply a
         | userland market.
         | 
         | Just like in the 90s when viruses primarily went to windows,
         | it' wasn't some magical property of windows, it was the market
         | of users available.
         | 
         | Also, following this logic, it then becomes survivorship bias,
         | in that the more attacks they get, the more researchers spend
         | time looking & documenting.
        
           | TZubiri wrote:
           | right, npm users. The extreme demand for simple packages and
           | the absent consideration creates an opportunity for attackers
           | to insert "free" solutions. The problem are the 'npm install'
           | happy developers no doubt.
        
           | KevinMS wrote:
           | > it' wasn't some magical property of windows
           | 
           | no, it really was windows
        
             | foobiekr wrote:
             | It really wasn't. MacOS classic was full of vulnerabilities
             | as was OS/2 and Linux up through 2004. Windows dominated
             | because it was the biggest ecosystem.
        
               | elwebmaster wrote:
               | And had the highest proportion of ignorant users.
        
               | ndsipa_pomu wrote:
               | What made Windows easy to exploit was that it enabled a
               | bunch of network services by default. I don't know about
               | MacOS, but Linux disabled network services by default and
               | generally had a better grasp of network security such as
               | requiring authentication for services (e.g. compare
               | telnet and ssh).
               | 
               | Also, Windows had the ridiculous default of immediately
               | running things when a user put in a CD or USB stick -
               | that behaviour led to many infections and is obviously a
               | stupid default option.
               | 
               | I'm not even going to mention the old Windows design of
               | everyone running with admin privileges on their desktop.
        
               | cesarb wrote:
               | > Also, Windows had the ridiculous default of immediately
               | running things when a user put in a CD or USB stick -
               | that behaviour led to many infections and is obviously a
               | stupid default option.
               | 
               | Playing devil's advocate: absent the obvious security
               | issues, it's a brilliant default option from an user
               | experience point of view, especially if the user is not
               | well-versed in the subtleties of filesystem management.
               | Put the CD into the tray, close the tray, and the
               | software magically starts, no need to go through the file
               | manager and double-click on an obscurely named file.
               | 
               | It made more sense back when most software was
               | distributed as pressed CD-ROMs, and the publisher of the
               | software (which you bought shrink-wrapped at a physical
               | store) could be assumed to be trusted. Once CD-R writers
               | became popular, and anyone could and did write their own
               | data CDs, these assumptions no longer held.
               | 
               | > I'm not even going to mention the old Windows design of
               | everyone running with admin privileges on their desktop.
               | 
               | That design makes sense for a single-user computer where
               | the user is the owner of the computer, and all software
               | on it is assumed to be trusted. Even today, many Linux
               | distributions add the first (and often only) user to a
               | sudoers group by default.
        
               | ndsipa_pomu wrote:
               | > Playing devil's advocate: absent the obvious security
               | issues, it's a brilliant default option from an user
               | experience point of view, especially if the user is not
               | well-versed in the subtleties of filesystem management.
               | Put the CD into the tray, close the tray, and the
               | software magically starts, no need to go through the file
               | manager and double-click on an obscurely named file.
               | 
               | It's a stupid default, though. One way round the issue is
               | to present the user with the option to either just open a
               | disc or to run the installer and allow them to change the
               | default if they prefer the less secure option.
               | 
               | > It made more sense back when most software was
               | distributed as pressed CD-ROMs, and the publisher of the
               | software (which you bought shrink-wrapped at a physical
               | store) could be assumed to be trusted
               | 
               | This allowed Sony BMG to infect so many computers with
               | their rootkit (https://en.wikipedia.org/wiki/Sony_BMG_cop
               | y_protection_rootk...).
               | 
               | > That design makes sense for a single-user computer
               | where the user is the owner of the computer, and all
               | software on it is assumed to be trusted. Even today, many
               | Linux distributions add the first (and often only) user
               | to a sudoers group by default.
               | 
               | A sudoers group is different though as it highlights the
               | difference between what files they are expected to change
               | (i.e. that they own) and which ones require elevated
               | permissions (e.g. installing system software). Earlier
               | versions of Windows did not have that distinction which
               | was a huge security issue.
        
           | elwebmaster wrote:
           | While it can happen to anyone npm does preselect the users
           | most likely to unknowingly amplify such an attack. Just today
           | I was working on a simple JS script while disconnected from
           | the Internet, Qwen Coder suggested I "npm install glob" which
           | I couldn't because there was no internet, so I asked for an
           | alternative and sure enough the alternative solution was two
           | lines of vanilla JS. This is just one example but it is the
           | modus operandi of the NPM ecosystem.
        
       | Incipient wrote:
       | Surely in this day and age we can fairly trivially find out these
       | come from the usual suspects - China, Russia, Iran, etc. Being in
       | such a digital age, where our economies are built on this
       | tech...is this not effectively (economic) warfare? Why are so
       | many governments blase about it?
        
         | Nextgrid wrote:
         | Proving the attack is state-sponsored is difficult (as any
         | attack you attribute to a country can very well be a false-flag
         | operation), and "state sponsorship" is itself a spectrum; for
         | example, you could argue India's insufficient action against
         | tech-support scammers is effectively state-sanctioned.
         | 
         | This can of course be resolved, but here's the kicker: our own
         | governments equally enjoy this ambiguity to do their own
         | bidding; so no government truly has an incentive to actually
         | improve cross-border identity verification and cybercrime
         | enforcement.
         | 
         | Not to mention, even besides government involvement, these
         | malicious actors still "engage" or induce "engagement" which
         | happens to be the de-facto currency of the technology industry,
         | so even businesses don't actually have any incentive of
         | fighting them.
        
           | mc32 wrote:
           | A one or two off can be a false flag, thousand upon thousands
           | is not going to be a false flag.
        
         | halJordan wrote:
         | It shouldn't be a "get the foreigners!" situation. Sure that is
         | a method of solving the symptoms. But what you're really asking
         | for is ... a software bill of materials. Why dont we have that
         | yet? Bc it's cheaper to get ripped off than it is to pay for a
         | bom. Thats the real problem
        
           | c0balt wrote:
           | SBOMs exist. You can get them generated for most software via
           | package managers in standard forms like cyclonedx.
           | 
           | It's just not that effective when the SBOM becomes
           | unmanageable. For example, our JS project at $work has 2.3k
           | dependencies just from npm. I can give you that SBOM (and
           | even include the system deps with nix) but that won't really
           | help you.
           | 
           | They are only really effective when the size is reasonable.
        
           | Ekaros wrote:
           | SBOM really doesn't do much when compromise happens before or
           | while you are building it. It really is orthogonal to these
           | types of attacks. Best you can do is to find that you were
           | compromise afterwards.
        
         | epolanski wrote:
         | They aren't, in fact the very true happens, that we are
         | bombarded non stop with information that everything is the
         | fault of actors from these companies even when it isn't.
         | 
         | We should fight this kind of behavior (and our privacy)
         | regardless of whose involved, yet our governments in the west
         | have nurtured this narrative of always pointing at big tech and
         | foreign actors as scape goats for anything privacy or hacking
         | related.
         | 
         | Also, any cyber attack tracker will show you this is a global
         | issue, if you think there aren't millions of attacks carried
         | out from our own countries, you're not looking enough.
        
         | csomar wrote:
         | We are still bound to our primal instincts. If you cut the
         | throat of a baby in the middle of Times Square, the outrage
         | will be insane. Yet, lack of financing to hospitals can do that
         | many times over but people are numb to it.
         | 
         | Take the Jaguar hack, the economic loss is estimated at 2.5bn.
         | Given an average house price in the UK of $300k, that's like
         | destroying ~8.000 homes.
         | 
         | Do you think the public and international response will be the
         | same if Russia or China leveled a small neighborhood even with
         | no human casualties?
        
         | kachapopopow wrote:
         | majority of these are actually north korea, india and america.
         | the really disappointing ones are usually india and american
         | and ones that lay dormant code are usually north korea.
        
         | bhouston wrote:
         | The US and Israel also have advanced penetration teams. But
         | they wouldn't be this sloppy - they want persistent advanced
         | access. I suspect Iran, Russia and China also wouldn't be this
         | sloppy. This is too wide ranging and easily detectable and
         | scattershot.
         | 
         | This feels like opportunistic cyber criminals, or North Korea
         | (which acts like cyber criminals.)
        
           | Towaway69 wrote:
           | Or anti-virus companies selling more of their wares.
           | 
           | This kind of large scale attack is perfect advertising for
           | anyone selling protection against such attacks.
           | 
           | Spy agencies have no interest in selling protection.
        
         | lionkor wrote:
         | I wonder that, too. Surely, this is a fantastic opportunity to
         | claim that it comes from whoever is declared evil right now,
         | and force a harder us-vs-them mindset. If people don't have a
         | clearly defined "evil bad guy" that is responsible for
         | _everything bad_ , how will you get teenagers to die for your
         | country in war?
         | 
         | Or, in other words; maybe the nature of humans and the inherent
         | pressure of our society to perform, to be rich, to be
         | successful, drives people to do bad things without any state
         | actor behind it?
        
       | yupyupyups wrote:
       | Something helpful here would be to enable developers to
       | optionally identify themselves. Not Discord-style where only the
       | platform knows their real identity, but publically as well.
        
         | gruez wrote:
         | So, EV code signing certificates? Windows has that, and it'll
         | verify that right in the OS. Git for instance, shows as being
         | signed by
         | 
         | CN = Johannes Schindelin O = Johannes Schindelin S = Nordrhein-
         | Westfalen C = DE
         | 
         | Downside is the cost. Certificates cost hundreds of dollars per
         | year. There's probably some room to reduce cost, but not by
         | much. You also run into issues of paying some homeless person
         | $50 to use their identity for cyber crimes.
        
           | mc32 wrote:
           | How would the homeless chap have the creds or gravitas for
           | people to trust him or her?
        
             | veeti wrote:
             | I don't really know who Johannes Schindelin is either but
             | use git quite happily.
        
           | brabel wrote:
           | You don't need certificates , just use PGP keys like Maven.
        
             | gruez wrote:
             | PGP keys don't tell you anything about a developers "real
             | identity". Theoretically theres some "web of trust", but
             | realistically everyone just blindly downloads whatever PGP
             | key is listed on the repo's install instructions.
        
               | brabel wrote:
               | Bullshit. The public key can be obtained by several easy
               | means, like visiting the publisher website or social
               | network site like GitHub which is common. That verifies
               | the identity just as well as any certificate! But with
               | much less trouble.
        
         | dcrazy wrote:
         | This is what macOS codesigning does. Notarization goes one step
         | further and anchors the signature to an Apple-owned CA to
         | attest that Apple has tied the signature to an Apple developer
         | account.
        
           | laserbeam wrote:
           | As I understand it, this attack works because the worm looks
           | for improperly stored secrets/keys/credentials. Once it find
           | them it publishes malicious versions of those packages. It
           | hits NPM because it's an easy target... but I could easily
           | imagine it hitting pip or the repo of some other popular
           | language.
           | 
           | In principle, what's stopping the technique from targeting
           | macos CI runners which improperly store keys used for
           | Notorization signing? Or... is it impossible to automate a
           | publishing step for macos? Does that always require a human
           | to do a manual thing from their account to get a project
           | published?
        
         | morkalork wrote:
         | You don't think bad actors don't have access to entire
         | countries worth of stolen identities to use for supply chain
         | attacks?
        
           | hirsin wrote:
           | This was largely the reason I rejected "real name
           | verification" ideas at GitHub after the xz attack.
           | (Especially if they are state sponsored) it's not that hard
           | for a dedicated actor (which xz certainly was) to get a
           | quality stolen identity.
           | 
           | The inevitable evolution of such a feature is a button on
           | your repo saying" block all contributors from China, Russia,
           | and N other countries". I personally think that's the
           | antithesis of OSS and therefore couldn't find the value in
           | such a thing.
        
             | morkalork wrote:
             | That would be easily defeated by a VPN. The inevitable
             | evolution would be some kind of in-person attestation of
             | identity backed up with some kind of insurance on the
             | contributor's work, and, well you're converging on the
             | employer-employee relationship then.
        
               | hirsin wrote:
               | Yep, I saw the cat and mouse ending at ever increasingly
               | invasive verifications involving more parties, that could
               | ultimately still be worked around by a state actor. We
               | already get asked for "block access from these country ip
               | ranges please" as a security measure despite it being
               | trivially bypassed, so it is easy to predict a useless
               | but strong demand for blocking users based on their
               | verified country.
        
               | berdario wrote:
               | "defeated", yes
               | 
               | "easily", not so much...
               | 
               | As in, services can still detect if you're connecting
               | through a VPN, and if you ever connect directly (because
               | you forgot to enable the VPN), your real location might
               | be detected. And the consequences there might not be
               | "having to refresh the page with the VPN enabled", but
               | instead: "find the whole organisation/project blocked,
               | because of the connection of one contributor"
               | 
               | This is why Comaps is using codeberg, after its
               | predecessor (before the fork) project got locked by
               | GitHub
               | 
               | https://news.ycombinator.com/item?id=43525395
               | 
               | https://mastodon.social/@organicmaps/114155428924741370
               | 
               | Moreover, this kind of stuff is also the reason I stopped
               | accessing Imgur:
               | 
               | - if I try without VPN, imgur stops me, because of the
               | UK's Online Safety Act
               | 
               | - if I try with my personal VPN, I get a 403 error every
               | single time
               | 
               | I'm sure I could get around it by using a different
               | service (e.g. Mullvad), but imgur is just not important
               | enough for me to bother, so I just stopped accessing it
               | altogether
        
               | 1718627440 wrote:
               | So... GPG?
        
       | wiradikusuma wrote:
       | Does anyone know why NPM seems to be the only attractive target?
       | Python and Java are very popular, but I haven't heard anything in
       | those ecosystems for a while. Is it because something inherently
       | "weak" about NPM, or simply because, like Windows or JavaScript,
       | everyone uses it?
        
         | parliament32 wrote:
         | Larger attack surface (JS has been the #1 language on GitHub
         | for years now) and more amateur developers (who are more likely
         | to blindly install dependencies, not harden against dev attack
         | vectors, etc).
        
           | dboreham wrote:
           | Also: a culture of constant churn in libraries which in
           | combination with the potential for security bugs to be fixed
           | in any new release leads to a common practice of ingesting a
           | continual stream of mystery meat. That makes filtering out
           | malware very hard. Too much noise to see the signal. None of
           | the above cultural factors is present in the other
           | ecosystems.
        
           | Sophira wrote:
           | Unfortunately, blindly installing dependencies at compile-
           | time is something that many projects will do by default
           | nowadays. It's not just "more amateur developers" who are at
           | risk here.
           | 
           | I've even seen "setup scripts" for projects that will use
           | root (with your permission) to install software. Such scripts
           | are less common now with containers, but unfortunately
           | containers aren't everything.
        
             | 1718627440 wrote:
             | > blindly installing dependencies at compile-time is
             | something that many projects will do by default nowadays.
             | 
             | I consider this to be a sign that someone is still an
             | amateur, and this is a reason to not use the software and
             | quickly delete it.
             | 
             | If you need a dependency, you can call the OS package
             | manager, or tell me to compile it myself. If you start a
             | network connection, you are malware in my eyes.
        
             | Cthulhu_ wrote:
             | Yes, exactly; I followed a Github course at one point and
             | it was Strongly Recommended that you enable Dependabot for
             | your project which will keep your dependencies up to date.
             | It's basically either already enabled or a one-click setup
             | action at this point. The norm that Github pushes is that
             | you should trust them to keep your stuff updated and
             | secure.
        
         | dtech wrote:
         | Npm has weak security boundaries.
         | 
         | Basically any dependency can (used to?) run any script with the
         | develop permissions on install. JVM and python package managers
         | don't do this.
         | 
         | Of course in all ecosystems once you actually run the code it
         | can do whatever with the permissions of the executes program,
         | but this is another hurdle.
        
           | lights0123 wrote:
           | Python absolutely can run scripts in installation. Before
           | pyproject.toml, arbitrary scripts were the _only_ way to
           | install a package. It 's the reason PyPi.org doesn't show a
           | dependency graph, as dependencies are declared in the Turing-
           | complete setup.py.
        
             | oefrha wrote:
             | Wrong. Wheels were available long before pyproject.toml,
             | and you could instruct pip to only install from wheels.
             | setup.py was needed to build the wheels, but the build step
             | wasn't a necessary part of installation and could be
             | disabled. In that sense its role is similar to that of pre-
             | publish build step of npm packages, unless wheels aren't
             | available.
        
           | silverwind wrote:
           | Deno has tackled some of these issues with their permission
           | system, but afaik it can only be applied to apps, not to
           | dependencies.
           | 
           | What we really need is a system to restrict packages in what
           | they can do (for example, many packages don't need network
           | access).
        
             | duncanbeevers wrote:
             | Lavamoat purports to do this. https://lavamoat.github.io/
             | 
             | There has been some promising prior research such as
             | BreakApp attempting to mitigate unusual supply-chain
             | compromises such as denial-of-service attacks targeting the
             | CPU via pathological regexps or other logic-bomb-flavored
             | payloads.
        
         | kace91 wrote:
         | One factor is that node's philosophy is to have a very limited
         | standard library and rely on community software for a ton of
         | stuff.
         | 
         | That means that not only the average project has a ton of
         | dependencies, but also any given dependency will in turn have a
         | ton of dependencies as well. there's multiplicative effects in
         | play.
        
           | rhubarbtree wrote:
           | This is the main reason. Pythons ecosystem also has silly
           | trends and package churn, and plenty of untrained developers.
           | It's the lack of a proper standard library. As bad a language
           | as it may be, Java shows how to get this right.
        
             | palata wrote:
             | > As bad a language as it may be, Java shows how to get
             | this right.
             | 
             | To be fair Java has improved _a lot_ over the last few
             | years. I really have the feeling that Java is getting
             | better, while C++ is getting worse.
        
             | PhilipRoman wrote:
             | What? Python's standard library seems far more extensive
             | than Java's.
        
               | yunwal wrote:
               | Yeah if anything I'm used to the opposite complaint about
               | python that there's _too much_ included in the stdlib.
        
           | louiskottmann wrote:
           | This is my take as well. I've never come accross a JS project
           | where the built-in datastructures were exclusively used.
           | 
           | One package for lists, one for sorting, and down the rabbit
           | hole you go.
        
             | sensanaty wrote:
             | I think this is mostly historical baggage unfortunately.
             | Every codebase I've ever worked in there was a huge push to
             | only use native ES6 functionality, like Sets, Maps, all the
             | Iterable methods etc., but there was still a large chunk of
             | files that were written before these were standardized and
             | widely used, so you get mixes of Lodash and a bunch of
             | other cursed shit.
             | 
             | Refactoring these also isn't always trivial either, so it's
             | a long journey to fully get rid of something like Lodash
             | from an old project
        
             | silverwind wrote:
             | This has improved recently. Packages like lodash were once
             | popular but you can do most stuff with the standard library
             | now. I think the only glaring exception is the lack of a
             | deep equality function.
        
         | Ekaros wrote:
         | I feel with Python upgrade cycle is slower. I upgrade
         | dependencies when something is broken or there is known issue.
         | That means any active vulnerabilities propagate slower. Slower
         | propagation means lower risk. And also as there is fewer
         | upstream packages impact of compromised maintainer is more
         | limited.
        
         | Balinares wrote:
         | As far as I understand, NPM packages are not self-contained
         | like e.g. Python wheels and can (and often need to) run scripts
         | _on install_.
         | 
         | So just installing a package can get you compromised. If the
         | compromised box contains credentials to update your own
         | packages in NPM, then it's an easy vector for a worm to
         | propagate.
        
           | magnetometer wrote:
           | Python wheels don't run arbitrary code on install, but source
           | distributions do. And you can upload both to pypy. So you
           | would have to run
           | 
           | pip install <package> --only-binary :all:
           | 
           | to only install wheels and fail otherwise.
        
         | broeng wrote:
         | Compared to the Java ecosystem, I think there's a couple of
         | issues in the NPM ecosystem that makes the situation a lot
         | worse:
         | 
         | 1) The availability of the package post-install hook that can
         | run any command after simply resolving and downloading a
         | package[1].
         | 
         | That, combined with:
         | 
         | 2) The culture with using version ranges for dependency
         | resolution[2] means that any compromised package can just
         | spread with ridiculous speed (and then use the post-install
         | hook to compromise other packages). You also have version
         | ranges in the Java ecosystem, but it's not the norm to use in
         | my experience, you get new dependencies when you actively bump
         | the dependencies you are directly using because everything
         | depends on specific versions.
         | 
         | I'm no NPM expert, but that's the worst offenders from a
         | technical perspective, in my opinion.
         | 
         | [1]: I'm sure it can be disabled, and it might even be now by
         | default - I don't know. [2]: Yes, I know you can use a lock
         | file, but it's definitely not the norm to actively consider
         | each upgraded version when refreshing the lockfile.
        
           | Cthulhu_ wrote:
           | To add a few:
           | 
           | * NPM has a culture of "many small dependencies", so there's
           | a very long tail of small projects that are mostly below the
           | radar that wouldn't stand out initially if they get a patch
           | update. People don't look critically into updated versions
           | because there's so many of them.
           | 
           | * Developers have developed a culture of staying up-to-date
           | as much as possible, so any patch release is applied as soon
           | as possible, often automated. This is mainly sold as a
           | security feature, so that a vulnerability gets patched and
           | released before disclosure is done. But it was (is?) also a
           | thing where if you wait too long to update, updating takes
           | more time and effort because things keep breaking.
        
           | silverwind wrote:
           | > The culture with using version ranges for dependency
           | resolution
           | 
           | Yep, auto-updating dependencies are the main culprit why
           | malware can spread so fast. I strongly recommend the use
           | `save-exact` in npm and only update your dependencies when
           | you actually need to.
        
             | tedivm wrote:
             | This advice leaves you vulnerable to log4j style
             | vulnerabilities that get discovered though.
             | 
             | The answer is a balance. Use Dependabot to keep
             | dependencies up to date, but configure a dependency
             | cooldown so you don't end up installing anything too new. A
             | seven day cooldown would keep you from being vulnerable to
             | these types of attacks.
        
               | SAI_Peregrinus wrote:
               | Cooldowns only work if enough people _don 't_ use
               | cooldowns (or don't use cooldowns longer than yours) for
               | attacks to get noticed.
        
           | hiccuphippo wrote:
           | Also badly named commands, `npm install` updates your
           | packages to the latest version allowed by package.json and
           | updates the lock file, `npm ci` is what people usually want
           | to do: install the versions according to the lock file.
           | 
           | IMO, `ci` should be `install`, `install` should be `update`.
           | 
           | Plus the install command is reused to add dependencies, that
           | should be a separate command.
        
             | bakkoting wrote:
             | This hasn't been true since version 5.4.2, released in
             | 2017.
             | 
             | `npm install` will always use the versions listed in
             | package-lock.json unless your package.json has been edited
             | to list newer versions than are present in package-
             | lock.json.
             | 
             | The only difference with `npm ci` is that `npm ci` fails if
             | the two are out of sync (and it deletes `node_modules`
             | first).
        
         | nottorp wrote:
         | Maybe some technical reasons, but more like the mind set of the
         | JS "community" that if you don't have the latest version of a
         | package 30 seconds after it's pushed you're hopelessly behind.
         | 
         | In other "communities" you upgrade dependencies when you have
         | time to evaluate the impact.
        
         | Karliss wrote:
         | For the last 2 years PyPi (main Python package repository)
         | requires mandatory 2FA.
         | 
         | Last time I did anything with Java, felt like use of multiple
         | package repositories including private ones was a lot more
         | popular.
         | 
         | Although higher branching factor for JavaScript and potential
         | target count are probably very important factors as well.
        
         | DANmode wrote:
         | As it turns out, vibe coding started with npm,
         | 
         | not chat bots.
        
         | sgammon wrote:
         | NPM lets you upload literally anything, without approval
        
       | thepasswordapp wrote:
       | The credential harvesting aspect is what concerns me most for the
       | average developer. If you've ever run `npm install` on an
       | affected package, your environment variables, .npmrc tokens, and
       | potentially other cached credentials may have been exfiltrated.
       | 
       | The action item for anyone potentially affected: rotate your npm
       | tokens, GitHub PATs, and any API keys that were in environment
       | variables. And if you're like most developers and reused any of
       | those passwords elsewhere... rotate those too.
       | 
       | This is why periodic credential rotation matters - not just after
       | a breach notification, but proactively. It reduces the window
       | where any stolen credential is useful.
        
         | Towaway69 wrote:
         | > anyone potentially affected
         | 
         | How does one know one is affected?
         | 
         | What's the point of rotating tokens if I'm not sure that I've
         | been affected - the new tokens will just be ex-filtrated as
         | well.
         | 
         | First step would be to identify infection, then clean up and
         | then rotate tokens.
        
           | mcintyre1994 wrote:
           | The article has some indicators of compromise, the main one
           | locally would be .truffler-cache/ in the home directory. It's
           | more obvious for package maintainers with exposed
           | credentials, who will have a wormed version of their own
           | packages deployed.
           | 
           | From what I've read so far (and this definitely could
           | change), it doesn't install persistent malware, it relies on
           | a postinstall script. So new tokens wouldn't be automatically
           | exfiltrated, but if you npm install any of an increasing
           | number of packages then it will happen to you again.
        
             | sierra1011 wrote:
             | It does install a GitHub runner and registers the infected
             | machine as a runner, so remote code execution remains
             | possible. It might be a stretch to call it persistent but
             | it definitely tries.
        
         | dawnerd wrote:
         | Also a good reminder that you should be storing secrets in some
         | kind of locker, not in plain text via environment variables or
         | config files. Impossible to get everyone on board but if you
         | can you should as much as possible.
         | 
         | I hate that high profile services still default to plain text
         | for credential storage.
        
           | internet_points wrote:
           | How do you do this in practice?
           | 
           | If I just need to `fly secrets set KEY=hunter2` one time for
           | production I can copy it from a paper pad even but if it's a
           | key I need to use every time I run a program that I'm
           | developing on, it's likely going to end up at least being in
           | my program's shell environment (and thus readable from its
           | /proc/pid/environ). So if I `npm install compromised-package`
           | - even from some other terminal - can't it just `grep -a KEY=
           | /proc/*/environ`?
           | 
           | Or are you saying the programs we hack on should use some
           | kind of locker api to fetch secrets and do away with env
           | vars?
        
         | mcintyre1994 wrote:
         | Also the user data destruction if it stops being able to
         | propagate itself.
        
         | Ferret7446 wrote:
         | > if you're like most developers and reused any of those
         | passwords elsewhere
         | 
         | Is this true? God I hope not, if developers don't even follow
         | basic security practices then all hope is lost.
         | 
         | I'd assume this is stating the obvious, but storing credentials
         | in environment variables or files is a big no-no. Use a
         | security key or at the very least an encrypted file, and never
         | reuse any credential for anything.
        
           | lionkor wrote:
           | I think so. I know too many developers who cannot be bothered
           | to have a password-manager, beyond the chrome/firefox default
           | one. Anything else, and even those, are usually "the standard
           | 2-3 passwords" they use.
        
           | TeMPOraL wrote:
           | > _Is this true? God I hope not, if developers don 't even
           | follow basic security practices then all hope is lost._
           | 
           | "Basic security practices" is an ever expanding set of hoops
           | to jump through, that if properly followed, stop all work in
           | its tracks. Few are following them diligently, or at all, if
           | given any choice.
           | 
           | Places that care about this - like _actually care_ , because
           | of contractual or regulatory reasons - don't even let you use
           | the same machine for different projects or customers. I know
           | someone who often has to carry 3+ laptops on them because of
           | this.
           | 
           | Point being, there's a cost to all these "basic security
           | practices", cost that security practitioners pretend doesn't
           | exist, but in fact it does exist, and it's quite substantial.
           | Until security world acknowledges this fact openly, they'll
           | always be surprised by how people "stubbornly" don't follow
           | "basic practices".
        
         | throwawayqqq11 wrote:
         | To me, the worming aspect and taking developers data as
         | hostages against infrastructure take down is most concerning.
         | 
         | Previously, you had isolated places to clean up a compromise
         | and you were good to go again. This attack approaches the semi-
         | distributed nature and attacks the ecosystem as a whole and i
         | am affraid this approch will get more sophisticated in the
         | future. It reminds me a little of malicious transactions
         | written into a distributed ledger.
        
         | vedhant wrote:
         | Even with periodoc rotation of credentials, attacker gets
         | enough time to do sufficient damage. Imo, the best way to solve
         | would be to not handle any sort of credentials at all at the
         | application layer! If at all the application must only handle
         | only very short lived tokens. Let there be a sidecar (for
         | example) that does the actual credential injection.
        
       | dmitrygr wrote:
       | Lucky for us C programmers. Each distro provides its own trusted
       | libc, and my code has no other dependencies. :)
        
         | TheTxT wrote:
         | But how do you left pad a string?
        
           | 1718627440 wrote:
           | char *          left_pad (const char * string, unsigned int
           | pad)         {             char tmp[strlen (string)+pad+1];
           | memset (tmp, ' ', pad);             strcpy (tmp+pad, string);
           | return strdup (tmp);         }
           | 
           | Doesn't sound too hard in my opinion. This only works for
           | strings, that fit on the stack, so if you want to make it
           | robust, you should check for the string size. It (like
           | everything in C) can of course fail. Also it is a quite naive
           | implementation, since it calculates the string size three
           | times.
        
             | brabel wrote:
             | Not a C expert but you're using a dynamic array right on
             | the stack, and then returning the duplicate of that.
             | Shouldn't that be Malloc'ed instead?? Is it safe to return
             | the duplicate of a stack allocated array, wouldn't the copy
             | be heap allocated anyway? Not to mention it blows the stack
             | and you get segmentation fault?
        
               | lionkor wrote:
               | strdup allocates
               | 
               | https://en.cppreference.com/w/c/experimental/dynamic/strd
               | up
        
               | 1718627440 wrote:
               | > and then returning the duplicate of that. Shouldn't
               | that be Malloc'ed instead??
               | 
               | Like the sibling already wrote, that's what strdup does.
               | 
               | > Is it safe to return the duplicate of a stack allocated
               | 
               | Yeah sure, it's a copy.
               | 
               | > wouldn't the copy be heap allocated anyway?
               | 
               | Yes. I wouldn't commit it like that, it is a naive
               | implementation. But honestly I wouldn't commit leftpad at
               | all, it doesn't sound like a sensible abstraction
               | boundary to me.
               | 
               | > Not to mention it blows the stack and you get
               | segmentation fault?
               | 
               | Yes and I already mentioned that in my comment.
               | 
               | ---
               | 
               | > dynamic array right on the stack
               | 
               | Nitpick: It's a variable length array and it is auto
               | allocated. Dynamic allocation refers to the heap or
               | something similar, not already done by the compiler.
        
             | newsoftheday wrote:
             | strndup would be safer if I correctly recall from my C
             | days?
        
           | kidmin wrote:
           | snprintf(buf, bufsize, "%*s", padwidth, str)?
        
         | john01dav wrote:
         | Do you rewrite fundamental data structures over and over, like
         | maps, of just not use them?
        
           | 1718627440 wrote:
           | C (actually POSIX) has a hashmap implementation:
           | https://man7.org/linux/man-pages/man3/hsearch.3.html
           | 
           | What it doesn't have is a hashmap type, but in C types are
           | cheap and are created on an ad-hoc basis. As long as it
           | corresponds to the correct interface, you can declare the
           | type anyway you like.
        
           | dmitrygr wrote:
           | Often yes, specialized to the specific thing I am doing. Eg:
           | for a JIT translator one often needs a combo hash-map + LRU,
           | where each node is a member of both structures.
        
         | testdelacc1 wrote:
         | How do you create a hashmap?
        
       | Aeolun wrote:
       | I thought this was a really insightful post, until they used it
       | to try and sell me on Gitlab's security features.
        
         | jaggirs wrote:
         | Why would that make it any less insightfull?
        
           | hu3 wrote:
           | Because bias and incentives matter.
           | 
           | There's a reason disclosures are obligatory in academic
           | papers.
        
             | baq wrote:
             | It's published on gitlab.com, not arxiv
        
               | rockskon wrote:
               | It's almost like the speakers are motivated by
               | advertising a product to solve a problem in their own
               | garden.
        
             | serial_dev wrote:
             | They pulled a little sneaky on ya, mentioning GitLab
             | security features available to GitLab users in a GitLab
             | Security blog post with GitLab logos everywhere.
             | 
             | Call me a conspiracy theorist, but I start to think these
             | people might be affiliated with GitLab.
        
               | TeMPOraL wrote:
               | It's more like, you don't know where honest technical
               | evaluation ends, and an ad starts.
        
               | hiccuphippo wrote:
               | It's all an ad.
        
           | Aeolun wrote:
           | It didn't make it less insightful, but it recontextualized
           | what was, in hindsight, a pretty strong bias towards
           | fearmongering.
        
         | norman784 wrote:
         | You are not the target then, but people using Gitlab might find
         | insightful.
        
       | xyzal wrote:
       | Okay ... what best practices should I as a mere dev follow to be
       | protected? Is the "cooldown" approach enough, or should every npm
       | command be run in bubblewrap ... ?
        
         | mcintyre1994 wrote:
         | In this narrow case, using pnpm or something similar that
         | blocks postinstall scripts by default should be sufficient. In
         | general, you probably want to use a container/vm/sandbox of
         | some sort so dev stuff can't access anything else on your
         | machine.
        
       | dawnerd wrote:
       | Everyone is blaming npm but GitHub should be put on blast too for
       | allowing the repos to be created and not quickly flagged.
       | 
       | GitHub has a massive malware problem as it is and it doesn't get
       | enough attention.
        
         | benatkin wrote:
         | They're part of the same company, but that's a good point. They
         | both have mediocre security.
        
         | princevegeta89 wrote:
         | I love! how Github, as a corporate company now owned by
         | Microsoft, is directly tied to GoLang as the main repository of
         | the vast majority of packages/dependencies.
         | 
         | Imagine the number of things that can go wrong when they try to
         | regulate or introduce restrictions for build workflows for the
         | purpose of making some extra money... lol
         | 
         | The original Java platform is a good example to think about.
        
           | oefrha wrote:
           | Golang builds pulling a github.com/foo/bar/baz module don't
           | rely on any GitHub "build workflow", so unless you mean
           | they're going to start restricting or charging for git clones
           | for public repos (before you mention Docker Hub, yes I know),
           | nothing's gonna change. And even if they're crazy enough to
           | do that, Go module downloads default to a proxy
           | (proxy.golang.org by default, can be configured and/or self-
           | hosted) and only fall back to vcs if the module's not
           | available, so a module only needs to be downloaded once from
           | GitHub anyway. Oh and once a module is cached in the proxy,
           | the proxy will keep serving it even if the repo/tag is
           | removed from GitHub.
        
           | Cthulhu_ wrote:
           | "The original Java platform" had no package management
           | though, that came with Maven and later Gradle, that have
           | similar vectors for supply chain attacks (that is, nobody
           | reviews anything before it's made available on package
           | repositories).
           | 
           | And (to put on my Go defender hat), the Go ecosystem doesn't
           | like having many dependencies, in part because of supply
           | chain attack vectors and the fact that Node's ecosystem went
           | a bit overboard with libraries.
        
           | amiga386 wrote:
           | That's the collective choice of the authors of those
           | packages. A go module path is literally just the canonical
           | URL where you can download the module.
           | 
           | The golang modules core to the language are hosted at
           | golang.org
           | 
           | Module authors have always been free to have their own prefix
           | rather than github.com, even if they host their module on
           | Github. If they say their module is example.com/foo and then
           | set their webserver to respond to https://example.com/foo?go-
           | get=1 with <meta name="go-import" content="example.com/foo
           | mod https://github.com/the_real_repository/foo"> then they
           | will leave no hint that it's really hosted at github, and
           | they could host it somewhere else in future (including at
           | https://example.com directly if they want)
           | 
           | https://go.dev/ref/mod#vcs
           | 
           | Another feature is that go uses a default proxy,
           | https://proxy.golang.org/, if you don't set one yourself.
           | This means that Google, who control that proxy, can choose to
           | make a request for a package like github.com/foo/bar go to
           | some place else, if for whatever reason Microsoft won't
           | honour it any more.
        
         | testdelacc1 wrote:
         | Wouldn't have been that hard to write a rule that matches the
         | repositories being created by this malware. It literally does
         | the same thing to every victim.
        
           | philipwhiuk wrote:
           | Sure, but until the malware spreads quickly you don't know
           | you need the rule.
        
             | testdelacc1 wrote:
             | True. But this was the "second coming" of the exact same
             | malware from a few months ago.
        
         | baobun wrote:
         | I would put blame on contemporary GitHub for a few things but
         | this is not one of them. We need better community practices and
         | tools. We can't expect to rely on Microsoft to content-filter.
        
         | hiccuphippo wrote:
         | Pushing the data to Github was a blessing in disguise. A friend
         | wouldn't have noticed he got caught if it didn't create a repo
         | on his account. It would have been worse if it silently sent
         | the data to some random server.
        
       | AmbroseBierce wrote:
       | Microsoft should just bite the bullet and make a huge JS standard
       | library and then send GitHub notifications to all the project
       | maintainers who are using anything that could be replaced by
       | something from there suggesting them to do such replacement. This
       | would likely significantly reduce the number of supply chain
       | attacks on the npm ecosystem.
        
         | testdelacc1 wrote:
         | This is harder than it sounds. Look at the amount of effort it
         | took to standardise temporal (new time library) and then for
         | all the runtimes to implement it. It's a lot of work.
         | 
         | And what's more, people have proposed a standard library
         | through tc39 without success -
         | https://github.com/tc39/proposal-built-in-modules
         | 
         | Of course any large company could create a massive standard
         | library on their own without going through the standards
         | process but it might not be adopted by developers.
        
         | nottorp wrote:
         | There's an xckd for that :)
         | 
         | The one with 12 competing standards going to 13 competing
         | standards, or something like that.
        
           | latexr wrote:
           | https://xkcd.com/927/
        
           | AmbroseBierce wrote:
           | Pretty sure Microsoft is exponentially bigger than 99% of the
           | library authors out there, and add to that the giant
           | communication channel that GitHub gives it over developers,
           | so the analogy breaks pretty fast.
        
             | nottorp wrote:
             | Or it's worse, because there's a good bunch of devs that
             | don't trust MS by default?
        
               | AmbroseBierce wrote:
               | Even the most hardcore GNU supporters don't think
               | Microsoft would add a supply chain attack to such
               | initiative, or that their software security is worse than
               | the average NPM (popular) package maintainer.
        
         | dominicrose wrote:
         | JS also has a stability issue. The language evolved fast, the
         | tools and the number of tools evolved fast and in different
         | directions. The module system is a mess and trying to make it
         | better caused more mess. There's Node.js, TypeScript and the
         | browser. That's a lot to handle when trying to make something
         | "std".
         | 
         | Meanwhile I have been using Ruby for 15 years and it has
         | evolved in a stable way without breaking everything and without
         | having to rewrite tons of libraries. It's not as powerful in
         | terms of performance and I/O, it's not as far-reaching as JS is
         | because it doesn't support the browser, it doesn't have a
         | typescript equivalent, but it's mature and stable and its power
         | is that it's human-friendly.
        
         | h4ck_th3_pl4n3t wrote:
         | That is literally how the CycloneDX SBOM packages work, well,
         | after the fact and after the disclosure process.
        
         | bakkoting wrote:
         | If you look at the list of compromised packages, very few of
         | them could reasonably be included in a standard library. It's
         | mostly project-specific stuff like `@asyncapi/specs` or
         | `@zapier/zapier-sdk`. The most popular generic one I see is
         | `get-them-args`, which is a CLI argument parser - which is
         | something Node has in the form of `util.parseArgs` since
         | v16.17.0.
        
       | wonderfuly wrote:
       | I'm a victim of this.
       | 
       | In addition to concerns about npm, I'm now hesitant to use the
       | GitHub CLI, which stores a highly privileged OAuth token in plain
       | text in the HOME directory. After the attacker accesses it, they
       | can do almost anything on behalf of me, for example, they turned
       | many of my private repos to public.
        
         | febusravenga wrote:
         | this, this, this
         | 
         | All our tokens should be in is protected keychain and there are
         | no proper cross-platform solutions for this. All gclouds, was
         | aww sdks, gh and other tools just store them in dotfile.
         | 
         | And worst thing, afaik there is no way do do it correctly in
         | MacOS for example. I'd like to be corrected though.
        
           | mcny wrote:
           | What is a proper solution for this? I don't imagine gpg can
           | help if you encrypt it but decrypt it when you login to
           | gnome, right? However, it would be too much of a hassle to
           | have to authenticate each time you need a token. I imagine
           | macOS people have access to the secure enclave using touch ID
           | but then even that is not available on all devices.
           | 
           | I feel like we are barking up the wrong tree here. The plain
           | text token thing can't be fixed. We have to protect our
           | computers from malware to begin with. Maybe Microsoft was
           | right to use secure admin workstations (saw) for privileged
           | access but then again it is too much of a hassle.
        
             | L-four wrote:
             | I think the correct solution is to use a keyring. On Linux
             | there's gnome keyring and last time I worked on a IOS app
             | there was something similar.
             | 
             | This does mean entering your keyring password a lot.
             | 
             | https://en.wikipedia.org/wiki/GNOME_Keyring
        
               | 1718627440 wrote:
               | > This does mean entering your keyring password a lot.
               | 
               | Not when you put that keyrings password into the user
               | keyring. I think it is also cached by default.
        
               | masfuerte wrote:
               | Then what stops the malware accessing the keyring?
        
               | mxey wrote:
               | On disk, it's encrypted. The running service, at least on
               | macOS, only hands the item out to specific apps, based on
               | their code signing identity.
        
               | ElectricalUnion wrote:
               | Who signs an "app" when I download it from Homebrew?
               | 
               | If all Homebrew "apps" are the same key then accepting a
               | keyring notification on one app is a lost cause at it
               | would allows things vulnerable to RCE to read/write
               | everything?
        
             | sakisv wrote:
             | The way I solve the plain text problem is through a
             | combination of direnv[1] and pass[2].
             | 
             | For a given project, I have a `./creds` directory which is
             | managed with pass and it contains all the access tokens and
             | api keys that are relevant for that project, one per file,
             | for example, `./creds/cloudflare/api_token`. Pass encrypts
             | all these files via gpg, for which I use a key stored on a
             | Yubikey.
             | 
             | Next to the `./creds` directory, I have an `.envrc` which
             | includes some lines that read the encrypted files and store
             | their values in environment variables, like so: `export
             | CLOUDFLARE_API_TOKEN=$(pass creds/cloudflare/api_token)`.
             | 
             | Every time that I `cd` into that project's directory,
             | direnv reads and executes that file (just once) and all
             | these are stored as environment variables, but only for
             | that terminal/session.
             | 
             | This solves the problem of plain-text files, but of course
             | the values remain in ENV and something malicious could look
             | for some well known variable names to extract from there.
             | Personally I try to install things in a new termux tab
             | every time which is less than ideal.
             | 
             | I'd like to see if and how other people solve this problem
             | 
             | [1]: https://direnv.net/ [2]:
             | https://www.passwordstore.org/
        
               | gerardnico wrote:
               | You can even go further and delete all your secrets from
               | your env by creating wrapper scripts
               | 
               | Example :
               | https://github.com/combostrap/devfiles/blob/main/dev-
               | scripts...
               | 
               | It's not completely full proof but at least gpg asks my
               | passphrase only when I run the script
        
               | hrimfaxi wrote:
               | At least with direnv your exports are removed when you
               | leave the directory.
        
               | internet_points wrote:
               | but if you `cd project && npm install compromised-
               | package` then compromised-package's setup script can
               | still read your env vars, right?
        
             | flir wrote:
             | It might be possible to lash up a cross-plaform solution
             | with KeePassXC. It's got an API that can be accessed from
             | the command line (chezmoi uses it to add secrets to
             | dotfiles). Yes, you'd be authenticating every time you need
             | a token but that might not be too much of a burden if you
             | spend most of your time on a machine with a fingerprint
             | scanner.
             | 
             | otoh I wouldn't do it, because I don't believe I could
             | implement it securely.
        
               | data-ottawa wrote:
               | I've got this work 1password setup, the only issue is if
               | you have background tasks.
               | 
               | I had a Borg backup script for example and 1password
               | needed me to authenticate to run it.
               | 
               | Authenticating for ssh and git is great.
        
           | 1718627440 wrote:
           | This doesn't sound like a technical problem to me. Even my
           | throw-away bash scripts call to `secret-tool lookup`, since
           | that is actually easier than implementing your own
           | configuration.
           | 
           | Also this is a complete non-issue on Unix(-like) systems,
           | because everything is designed around passing small strings
           | between programs. Getting a secret from another program is
           | the same amount of code, as reading it from a text file,
           | since everything is a file.
        
           | akdev1l wrote:
           | For what it's worth, the recommended way of getting
           | credentials for AWS would be either:
           | 
           | 1. Piggyback of your existing auth infra (eg: ActiveDirectory
           | or whatever you already have going on for user auth) 2.
           | Failing that use identity center to create user auth in AWS
           | itself
           | 
           | Either way means that your machine gets temporary credentials
           | only
           | 
           | Alternatively, we could write an AWS CLI helper to store the
           | stuff into the keychain (maybe someone has)
           | 
           | Not to take away from your more general point
           | 
           | We need flatpak for CLI tools
        
           | naikrovek wrote:
           | > no way do do it correctly in MacOS
           | 
           | What? The MacOS Keychain is designed exactly for this. Every
           | application that wants to access a given keychain entry
           | triggers a prompt from the OS and you must enter your
           | password to grant access.
        
           | mxey wrote:
           | > And worst thing, afaik there is no way do do it correctly
           | in MacOS for example. I'd like to be corrected though.
           | 
           | https://developer.apple.com/documentation/security/keychain-.
           | ..
           | 
           | And similar services exist on Linux desktops. There are
           | libraries that will automatically pick the right backend.
        
         | didntcheck wrote:
         | That's true, but the same may already be true of your browser's
         | cookie file. I believe Chrome on MacOS and Windows (unsure
         | about Linux) now does use OS features to prevent it being read
         | from other executables, but Firefox doesn't (yet)
         | 
         | But protecting specific directories is just whack-a-mole. The
         | real fix is to properly sandbox code - an access whitelist
         | rather than endlessly updating a patchy blacklist
        
           | mcny wrote:
           | > But protecting specific directories is just whack-a-mole.
           | The real fix is to properly sandbox code - an access
           | whitelist rather than blacklist
           | 
           | I believe Wayland (don't quote me on this because I know
           | exactly zero technical details) as opposed to x is a big step
           | in this direction. Correct me if I am wrong but I believe
           | this effort alone has been ongoing for a decade. A proper
           | sandbox will take longer and risks being coopted by corporate
           | drones trying to take away our right to use our computers as
           | we see fit.
        
             | rkangel wrote:
             | Wayland is a significant improvement in one specific area
             | (and it's not this one).
             | 
             | All programs in X were trusted and had access to the same
             | drawing space. This meant that one program could see what
             | another one was drawing. Effectively this meant that any
             | compromised program could see your whole screen if you were
             | using X.
             | 
             | Wayland has a different architecture where programs only
             | have access to the resources to draw their own stuff, and
             | then a separate compositor joins all the results together.
             | 
             | Wayland does nothing about the REST of the application
             | permission model - ability to access files, send network
             | requests etc. For that you need more sandboxing e.g.
             | Flatpak, Containers, VMs
        
             | akshitgaur2005 wrote:
             | Maybe I am missing something but how and why would a
             | display protocol have anything to do with file access
             | model??
        
               | Hendrikto wrote:
               | In Wayland you have these xdg-portals that broker access
               | to the filesystem, microphone, webcam, etc. I am not
               | knowledgeable about the security model though.
        
               | ElectricalUnion wrote:
               | Portals are used to integrate applications to the host if
               | they're being run inside a sandboxed environment.
               | 
               | They are hooks that latch on the common GUI application
               | library calls for things such as "open file dialogs" such
               | that exeptions to the sandbox are implicitly added as-
               | you-go.
               | 
               | They cannot prevent for example direct filesystem access
               | if the application has permission to open() stuff, like
               | if they're not running in a sandbox, or if said sandbox
               | have a "can see and modify entire filesystem" exception
               | (very common on your average flatpak app, btw).
        
               | internet_points wrote:
               | portals are used by wayland, but you can also use them
               | without wayland.
               | 
               | E.g. under X you can use bubblewrap or firejail to
               | restrict access to the web or whatever for some program,
               | but still give that program access to for example an xdg
               | portal that lets you "open url in web browser" (except
               | the locked-down program can't for example see the result
               | of downloading that web page)
        
           | naikrovek wrote:
           | Plan9 had per-process namespaces in 1995.
           | 
           | One could easily allow or restrict visibility of almost
           | anything to any program. There were/are some definite
           | usability concerns with how it is done today (the OS was not
           | designed to be friendly, but to try new things) and those
           | could easily be solved. The core of this existed in the Plan9
           | kernel and the Plan9 kernel is small enough to be understood
           | by one person.
           | 
           | I'm kinda angry that other operating systems don't do this
           | today. How much malware would be stopped in its tracks and
           | made impotent if every program launched was inherently and
           | natively walled off from everything else by default?
        
         | douglascamata wrote:
         | Apparently, The Github CLI only stores its oauth token in the
         | HOME directory if you don't have a keyring. They also say it
         | may not work on headless systems. See
         | https://github.com/cli/cli/discussions/7109.
         | 
         | For example, in my macOS machines the token is safely stored in
         | the OS keyring (yes, I double checked the file where otherwise
         | it would've been stored as plain text).
        
           | naikrovek wrote:
           | Yes. KeePassXC is all you need on Linux to have a compatible
           | secret store.
        
           | kd913 wrote:
           | The defacto install of github CLI on ubuntu systems appears
           | to be snap which is owned by some random dude...
        
         | sierra1011 wrote:
         | I'm also a victim of this. Last time I try and install
         | Backstage.
         | 
         | Have you wiped your laptop/infected machine? If not I would
         | recommend it; part of it created a ~/.dev-env directory which
         | turned my laptop into a GitHub runner, allowing for remote code
         | execution.
         | 
         | I have a read-only filesystem OS (Bluefin Linux) and I don't
         | know quite how much this has saved me, because so much of the
         | attack happens in the home directory.
        
       | mrklol wrote:
       | Is there any reason to keep using postinstall scripts allowed
       | instead of asking e.g. the user? Are they even needed in most
       | cases?
        
         | Cthulhu_ wrote:
         | If you ask the user "should I run this script" after
         | installing, they will just hit yes every time. But also, a lot
         | (I'm confident it's "most") of NPM install operations are done
         | on a CI server, which need to run without human interaction.
        
       | arkh wrote:
       | Most of those attacks do the same kind of things.
       | 
       | So I'm surprised to never see something akin to "our AI systems
       | flagged a possible attack" in those posts. Or the fact Github
       | from AI pusher fame Microsoft does not already use their AI to
       | find this kind of attacks before they become a problem.
       | 
       | Where is this miracle AI for cybersecurity when you need it?
        
         | nottorp wrote:
         | Current "AI" is generative "AI". It can generate bullshit not
         | evaluate anything.
         | 
         | Edit: see the curl posts about them being bombarded with "AI"
         | generated security reports that mean nothing and waste their
         | time.
        
         | michaelt wrote:
         | The security product marketers ruined "a possible attack" as a
         | brag 25 years ago. Every time a firewall blocks something, it's
         | a _possible_ attack being blocked, and imagine how often that
         | happens.
        
         | firesteelrain wrote:
         | SonaType Lifecycle has some magic to prevent these types of
         | attacks. They claim it is AI based. Not sure how it all works
         | as it is proprietary but it is one of the things we use at
         | work. SonaType IQ server powers it
        
       | akdor1154 wrote:
       | Jesus Christ, i can't even get my own package to reliably self-
       | publish in CI without ending up with a fragile pile of twigs, I'm
       | awed they are able to automate infection like that.
        
       | Yokohiii wrote:
       | I have an friend that starts an project next month that will rely
       | on npm. He is quite a noob and didn't code in ages. He will have
       | almost no clue how to harden against this, he will probably not
       | even notice if he becomes a victim until something really bad
       | happens.
       | 
       | Pretty sad.
        
         | mkesper wrote:
         | At least make them run pnpm instead of npm, disabling post-
         | install scripts. https://pnpm.io/supply-chain-security
        
         | newsoftheday wrote:
         | "a friend" because friend starts with a consonant sound, not a
         | vowel sound. "a project" for the same reason.
         | 
         | HTH.
        
       | zx8080 wrote:
       | Everyone wanted to centralise as much as possible to save every
       | cent. No wonder what it got us all into.
       | 
       | Enjoy it while saving your cent!
        
         | Flere-Imsaho wrote:
         | Also layer upon layer of abstractions - to the point where no
         | single person understands the stack from top to bottom.
         | 
         | Perhaps there is a light at the end of the tunnel: with AI
         | coding assistance, the whole application can be written from
         | scratch (like the old days). All the code is there, not buried
         | deep within someone else's codebase.
        
       | efortis wrote:
       | Mitigate this attack vector by adding:                   ignore-
       | scripts=true
       | 
       | to your .npmrc
       | 
       | https://blog.uxtly.com/getting-rid-of-npm-scripts
        
         | philipwhiuk wrote:
         | Or use pnpm
        
           | jMyles wrote:
           | To delay updates, you mean?
           | 
           | I'm curious though: how do you avoid being stuck on the
           | _vulnerable_ versions, delaying updates?
        
             | homebrewer wrote:
             | pnpm disables all install scripts by default and makes it
             | trivial to whitelist the few you need. It's usually just
             | one or two, or sometimes zero, depending on the project.
             | Even without malware, most postinstall scripts are used for
             | spam and analytics, and running them makes your life worse.
             | 
             | npm should have died long ago, I don't know why it's still
             | being used.
        
         | seanwilson wrote:
         | Once you run the JavaScript of the npm library you just
         | installed, if it's Node, what's to stop it accessing
         | environment variables and any file it wants, and sending data
         | to any domain it wants?
        
           | MetaWhirledPeas wrote:
           | Nothing, but at least you'll have time to see the audit if
           | it's aware.
        
           | efortis wrote:
           | fs and net can be mitigated with `--permission`
           | 
           | https://nodejs.org/api/permissions.html
           | 
           | Regardless, it's worth using `--ignore-scripts=true` because
           | that's the common vector these supply chain attacks target.
           | Consider that when automating the attack, adding it to the
           | application code is more difficult than injecting it into
           | life-cycle scripts, which have well-known config lines.
        
         | TeMPOraL wrote:
         | Stupid question, but:
         | 
         | - If it's safe to "ignore scripts", why does this option exist
         | in the first place?
         | 
         | - Otherwise, what kind of cascade breakage in dependencies you
         | risk by suppressing part of their installation process?
        
           | efortis wrote:
           | Yes, it can break deps, some will not install. Puppeteer is a
           | good example because it installs binaries. But it also shows
           | an error with the cmd needed to complete the installation.
           | 
           | Why it is allowed by default?
           | 
           | > it's npm's belief that the utility of having installation
           | scripts is greater than the risk of worms.
           | 
           | NPM co-founder Laurie Voss
           | 
           | https://blog.npmjs.org/post/141702881055/package-install-
           | scr...
        
         | hiccuphippo wrote:
         | Is there a way to list all the packages in the dependency tree
         | with preinstall/postinstall hooks? Preferably before doing the
         | installation?
        
           | efortis wrote:
           | IDK. I usually notice it when it breaks the install
        
       | qubex wrote:
       | About a month ago I had a rather annoying task to perform, and I
       | found an NPM package that handled it. I threw "brew install NPM"
       | or whatever onto the terminal and watched a veritable deluge of
       | dependencies download and install. Then I typed in 'npm ' and my
       | hand hovered on the keyboard after the space as I suddenly
       | thought long and hard about where I was on the risk/benefit curve
       | and then I backspaced and typed "brew uninstall npm" instead, and
       | eventually strung together an oldschool unix utilities pipeline
       | with some awk thrown in. Probably the best decision of my life,
       | in retrospect.
        
         | kubafu wrote:
         | Same story from a month ago. The moment I saw the sheer number
         | of dependencies artillery wanted to pull I gave up.
        
         | sigmoid10 wrote:
         | This is why you want containerisation or, even better, full
         | virtualisation. Running programs built on node, python or any
         | other ecosystem that makes installing tons of dependencies easy
         | (and thus frustratingly common) on your main system where you
         | keep any unrelated data is a surefire way to get compromised by
         | the supply chain eventually. I don't even have the interpreters
         | for python and js on my base system anymore - just so I don't
         | accidentally run something in the host terminal that shouldn't
         | run there.
        
           | baq wrote:
           | ...but the github runners already are virtualized; you'd need
           | to virtualize the secrets they have access to instead.
        
           | Glemkloksdjf wrote:
           | No thats not what i want, that whats i need when i use
           | something like npm.
           | 
           | Which can't be the right way.
        
             | godzillabrennus wrote:
             | The right way (technically) and the commercially viable way
             | are often diametrically opposed. Ship first, ask questions
             | later, or, move fast and break things, wins.
        
             | ndriscoll wrote:
             | Why not? Make a bash alias for `npm` that runs it with
             | `bwrap` to isolate it to the current directory, and you
             | don't have to think about it again. Distributions could
             | have a package that does this by default. With nix, you
             | don't even need npm in your default profile, and can create
             | a sandboxed nix-shell on the fly so that's the only way for
             | the command to even be available.
             | 
             | Most of your programs are trusted, don't need isolation by
             | default, and are more useful when they have access to your
             | home data. npm is different. It doesn't need your
             | documents, and it runs untrusted code. So add the 1 line
             | you need to your profile to sandbox it.
        
               | kernc wrote:
               | I wrote myself a handy and generalized bwrap-wrapping
               | script: https://github.com/sandbox-utils/sandbox-run
        
           | naikrovek wrote:
           | Here I go again: Plan9 had per-process namespaces in 1995.
           | The namespace for any process could be manipulated to see (or
           | not see) any parts of the machine that you wanted or needed.
           | 
           | I really wish people had paid more attention to that
           | operating system.
        
             | nyrikki wrote:
             | The tooling for that exists today in Linux, and it is
             | fairly easy to use with podman etc.
             | 
             | K8s choices clouds that a little, but for vscode
             | completions as an example, I have a pod, that systemd
             | launches on request that starts it.
             | 
             | I have nginx receive the socket from systemd, and it
             | communicates to llama.cpp through a socket on a shared
             | volume. As nginx inherits the socket from systemd it does
             | have internet access either.
             | 
             | If I need a new model I just download it to a shared
             | volume.
             | 
             | Llama.cpp has now internet access at all, and is usable on
             | an old 7700k + 1080ti.
             | 
             | People thinking that the k8s concept of a pod, with shared
             | UTC, net, and IPC namespaces is all a pod can be confuses
             | the issue.
             | 
             | The same unshare command that runc uses is very similar to
             | how clone() drops the parent's IPC etc...
             | 
             | I should probably spin up a blog on how to do this as I
             | think it is the way forward even for long lived services.
             | 
             | The information is out there but scattered.
             | 
             | If it is something people would find useful please leave a
             | comment.
        
               | rafterydj wrote:
               | This sounds very interesting to me. I'd read through that
               | blog post, as I'm working on expanding my K8s skills - as
               | you say knowledge is very scattered!
        
               | naikrovek wrote:
               | You are missing my point, maybe.
               | 
               | Plan9 had this by default in 1995, no third party tools
               | required. You launch a program, it gets its own
               | namespace, by default it is a child namespace of whatever
               | namespace launched the program.
               | 
               | I should not have to read anything to have this.
               | Operating systems should provide it by default. That is
               | my point. We have settled for shitty operating systems
               | because it's easier (at first glance) to add stuff on top
               | than it is to have an OS provide these things. It turns
               | out this isn't easier, and we're just piling shit on top
               | of shit because it _seems_ like the easiest path forward.
               | 
               | Look how many lines of code are in Plan9 then look at how
               | many lines of code are in Docker or Kubernetes. It is
               | probably easier to write operating systems with features
               | you desire than it is to write an application-level
               | operating system like Kubernetes which provide those
               | features on top of the operating system. And _that_ is
               | likely due to application-scope operating systems like
               | Kubernetes needing to comply with the existing reality of
               | the operating system they are running on, while an actual
               | operating system which runs on hardware _gets to define
               | the reality that it provides_ to applications which run
               | atop it.
        
               | nyrikki wrote:
               | You seem to have a misunderstanding of what namespaces
               | accomplished on plan9, or that it was extending Unix
               | concepts and assembling them in another way.
               | 
               | As someone who actually ran plan9 over 30 years ago I
               | ensure that if you go back and look at it, the namespaces
               | were intended to abstract away the hardware limitations
               | of the time, to build distributed execution contexts of a
               | large assembly of limited resources.
               | 
               | And if you have an issue with Unix sockets you would have
               | hated it as it didn't even have stalls and everything was
               | about files.
               | 
               | Today we have a different problem, where machines are so
               | large that we have to abstract them into smaller chunks.
               | 
               | Plan9 was exactly the opposite, when your local system
               | CPU is limited you would run the cpu command and use
               | another host, and guess what, it handed your file
               | descriptors to that other machine.
               | 
               | The goals of plan9 are dramatically different than
               | isolation.
               | 
               | But the OSes you seem to hate so much implemented many of
               | the plan9 ideas, like /proc, union file systems, message
               | passing etc.
               | 
               | Also note I am not talking about k8s in the above, I am
               | talking about containers and namespaces.
               | 
               | K8s is an orchestrater, the kernel functionality may be
               | abstracted by it, but K8s is just a user of those plan9
               | inspired ideas.
               | 
               | Netns, pidns, etc... could be used directly, and you can
               | call unshare(2)[0] directly, or use a cri like crun or
               | use podman.
               | 
               | Heck you could call the ip() command and run your app in
               | an isolated namespace with a single command if you wanted
               | to.
               | 
               | You don't need an api or K8s at all.
               | 
               | [0] https://man7.org/linux/man-pages/man2/unshare.2.html
        
               | ElectricalUnion wrote:
               | The fact that tools like docker, podman and bubblewrap
               | exist and work points out that the OS supports it, but
               | using the OS APIs directly sucks. Otherwise the only
               | "safe" implementations of such features would need a full
               | software VM.
               | 
               | If using software securely was really a priority,
               | everyone would be rustifing everything, and running
               | everything in separated physical machines with
               | restrictive AppArmor, SELinux, TOMOYO and Landlock
               | profiles, with mTLS everywhere.
               | 
               | It turns out that in Security, "availability" is a very
               | important requirement, and "can't run your insecure-by-
               | design system" is a failing grade.
        
           | estimator7292 wrote:
           | Why think about the consequences of your actions when you can
           | use docker?
        
           | metachris wrote:
           | Absolutely, good old VMs can really provide the needed
           | isolation while still having good UX. I just published a post
           | on setting up dev VMs with Lima:
           | https://www.metachris.dev/2025/11/sandbox-your-ai-dev-
           | tools-...
        
         | 2OEH8eoCRo0 wrote:
         | It's funny because techies love to tell people that common
         | sense is the best antivirus, don't click suspicious links, etc.
         | only to download and execute a laundry list of unvetted
         | dependencies with a keystroke.
        
         | jwr wrote:
         | I used to run npm only inside docker containers, and I've been
         | regularly laughed at on these forums. I eventually gave up...
        
           | qubex wrote:
           | "Whenever you find yourself on the side of the majority, it
           | is time to pause and reflect." -- Mark Twain (supposedly)
        
         | philipwhiuk wrote:
         | The lesson surely though is 'don't use web-tech, aimed at
         | solving browser incompatibility issues for local scripting'.
         | 
         | When you're running NPM tooling you're running libraries
         | primarily built for those problems, hence the torrent of
         | otherwise unnecessary complexity of polyfills, that happen to
         | be running on a JS engine that doesn't get a browser attached
         | to it.
        
           | bakkoting wrote:
           | Very few packages published on npm include polyfills,
           | especially packages you'd use when doing local scripting.
        
       | austin-cheney wrote:
       | Are there any good alternatives to ESLint? ESLint is now my only
       | dev dependency with hundreds of dependencies of its own.
        
         | tuzemec wrote:
         | Biome: https://biomejs.dev/
         | 
         | Also the whole ecosystem around OXS looks very promising:
         | https://oxc.rs/
        
           | jackwilsdon wrote:
           | Both of those have over >400 dependencies each [0] [1] but
           | just in Rust instead - there hasn't been a Rust supply chain
           | attack yet but is this any better? [2]
           | 
           | Admittedly you're not normally downloading the dependencies
           | to your machine as you're often using pre-built binaries, but
           | a malicious package could still run if a version was shipped
           | with it.
           | 
           | [0]: https://github.com/biomejs/biome/blob/93182ea8e9d479fd01
           | 87ce...
           | 
           | [1]: https://github.com/oxc-
           | project/oxc/blob/65bd5584bfce0c7da90f...
           | 
           | [2]: https://users.rust-lang.org/t/yet-another-npm-supply-
           | chain-a...
        
             | brabel wrote:
             | Wow that's terrifying.
        
       | xomodo wrote:
       | I think I found some repos here:
       | https://github.com/search?q=in:description+Sha1-Hulud&type=r...
        
       | ksynwa wrote:
       | What are the "sha1-hulud" github repositories for exactly? I see
       | files like secrets.json but the contents seems to not be valid
       | json. Are these encrypted?
        
         | hiccuphippo wrote:
         | I looked at one and it was doubly encoded base64.
        
       | mikkupikku wrote:
       | > _" This creates a dangerous scenario. If GitHub mass-deletes
       | the malware's repositories or npm bulk-revokes compromised
       | tokens, thousands of infected systems could simultaneously
       | destroy user data."_
       | 
       | Pop quiz, hot shot! A terrorist is holding user data hostage, got
       | enough malware strapped to his chest to blow a data center in
       | half. Now what do you do?
       | 
       | Shoot the hostage.
        
         | hsbauauvhabzb wrote:
         | The hostage naively walked past all the police and into the
         | data centre, and you're shooing them in the leg. They'll
         | probably survive, but they knowingly or incompetently made
         | their choice. Sucks to be them.
        
       | hakcermani wrote:
       | pardon the naive question. What i don't get is these injected
       | payload are js files, isn't there some scanning at npm upload
       | level to look for exfiltration behaviour, bash executions of
       | dangerous commands like rm or shred ?
        
       | hresvelgr wrote:
       | While this does appear to be getting worse, I'm in the camp of
       | letting it happen. The Node/JS ecosystem is imho completely
       | unsuitable for serious work and this is merely the natural
       | consequence. Let it burn, and perhaps something better will come
       | from the ashes.
        
       | newsoftheday wrote:
       | As a Java dev, seems like only a matter of time before Maven
       | Nexus repo attacks become commonplace.
        
         | loginatnine wrote:
         | Send them a request to have Trusted publishers support at
         | central-support (at) sonatype.com
         | 
         | I did that a couple of weeks ago and received an acknowledgment
         | "Another request on Trusted Publishing option. Assigning to
         | Product for review and further action." so this is a bit
         | encouraging.
         | 
         | At least Maven dependencies don't execute scripts on install,
         | but Maven plugins could have a big blast radius.
        
         | jonhohle wrote:
         | Over a decade ago at Amazon, all third party dependencies
         | needed to be manually imported. On the one hand, it makes
         | importing new versions or packages slow. On the other hand,
         | there is a very explicit intention and log of every external
         | change that made it into internal projects.
         | 
         | At my previous company, I implemented staged dependencies with
         | artifactory so that production could never get packages that
         | had never gone through CR, or staging environments first. They
         | just were never replicated. That eliminated fuzzy dependency
         | matches that showed up for the first time in production
         | (something that did happen). Because dev to production was
         | about 1 week, it also afforded time to identify packages before
         | they had a chance to be deployed. Obviously it was less robust
         | than manually importing.
         | 
         | Maybe self-hosted package caches support these features now,
         | but 6-7 years ago, that was all manual work.
        
       | bn-l wrote:
       | Oh look, another day and another NPM supply chain attack.
        
       | csutil-com wrote:
       | Can't GitHub just block/make private all
       | https://github.com/search?q=Sha1-Hulud%3A%20The%20Second%20C...
       | repos as a first step?
        
       ___________________________________________________________________
       (page generated 2025-11-28 23:01 UTC)