1. pytorch publishes their nightly package on their repo which depends on a custom triton build provided on their repo, but using a package name they don't own in pypi. This has been mitigated by them by renaming the dependency from torchtriton to pytorch-triton, reserving pytorch-triton package in pypi, and changing the dependency name on the newer nightly builds 20221231 forward to point to pytorch-triton package instead.
2. pytorch installation instruction for nightly using pip in (https://pytorch.org/get-started/locally/#start-locally), make use of the --extra-index-url option. This is a known vector of dependency confusion attacks, and is an inherently insecure method of installing packages from private repositories. The recommended approach of distributing wheels in private repositories is by using a repository server that allows proxying/redirecting the public pypi packages to pypi, and users should be using a single --index-url pointed to that private repository (assuming the maintainer of that private repository is to be trusted). --extra-index-url is meant to provide mirror urls (serving the same set of packages as the main one), rather than to combine repos with different sets of packages.
Alternatively, keep a separate requirements_private.txt around for private dependencies and add a line --index-url <my private repository>.
Do we want all those packages or do we want the functionality of them? Dependency hell happens for reasons of deficient first-party support. Notably, languages that lack a sufficient standard library and a blessed toolchain should be considered a pre-existing condition to this decease.
I get that language maintainers have legit reasons to exclude something like HTTP from std, but there has to be some middle ground here. For instance, Golang provides experimental packages that have high quality but a lower level of support. To me, this is a win. It centers the community in a common direction, and delivers real world value in the meantime, with minimal maintenance upkeep compared to the 100s of packages we see in some ecosystems like JS and to a lesser extent Rust.
It still contains only a tiny fraction of the functionality needed by any large project. The world is just too complex for a standard library to ever realistically cover a meaningful portion of the problem space.
We all need tensor algebra, video decoding, cutting-edge network protocols, compression, cryptography, dozens of data exchange formats, syscall bindings for three or more platforms, fuzzing, containers, and I don't know what else. This isn't going to all fit into a standard library. "Dependency hell" is here to stay.
Libraries refuse to shift away from this culture thing, and decided to just blacklist the known exploit path while keeping the vulnerability intact. It's not that they do this for backward-compatibility, it's new libraries still being designed this way.
The log4j 2 bug is slightly different, but IMO as a design issue it has root in the same culture thing described above.
Log4j 2 refused to shift away from it since they are paid to add that kind of bloat, yes this wasn't an accident caused by a bad culture, this was a feature someone requested. As far as I understood they are completely separate from the original log4j and it is just another, mostly compatible logging implementation.
> Java is unique as the culture encourages doing magic convention over configuration by reflection AND it-just-works serialization
As opposed to what? Python? The language that culturally refuses to fix the GIL and as workaround provides multiprocessing, which requires that everything is serialized?
Also I may not have seen many Python code bases, but from what I have seen ClassLoader/Import abuse is alive in both languages.
Python at least does not pretend their it-just-works serialization is secure. The documentation [1] actively discourages deserializing untrusted data and suggests to use pure data format (e.g. JSON) as possible.
In contrast, the documentation on ObjectInputStream before Java 11 does not warn about this at all. Even then [2], it suggests to implement blacklist/whitelist filters, and it is pretty hard to get right. The same filtering can also be done for pickle, but the usual consensus in Python developers seems to be "don't do this even if it's possible".
> but from what I have seen ClassLoader/Import abuse is alive in both languages.
Yeah, should have said that my rant is mainly against endless deserialization/OGNL injection/whatever-popular-expression-language injection bugs in frameworks, not abusing ClassLoader. These features, just like log4j2's code-execution-disguised-as-string-interpolation feature [3], shouldn't exist.
[1] https://docs.python.org/3/library/pickle.html
[2] https://docs.oracle.com/en/java/javase/11/docs/api/java.base...
[3] I'd argue that's the real bug, instead of the obvious JNDI class loader blah blah stuff. Luckily log4j didn't refuse to fix it and completely removed "message lookup".
In my opinion, Java’s standard library is good, but not as good as the one in Python and then Golang. I also prefer the one in C#.
There is a size limit for standard libraries?
I think Java introduced modules and its dependency model so you could package only what your software needed.
There is a size limit to what language curators are able to maintain, yes.
The idea of the standard library is that it will select components that are general enough to cover a wide range of use cases; therefore the language builders ned time to review every new proposal, and their time is limited.
You may dump everything under the sun in the standard library, but then it won't be better than what you get from a library marketplace.
There are thousands, if not tens of thousands, of packages available to install via apt or yum. But most of those packages are packaged by a dedicated maintainer - not any rando. The bar isn't much higher, but there _is_ a bar. Python's (well, pip) practice of letting any vermin with no prior vetting publish is root of the problem in my opinion.
Which leads me to wonder: do we really always want the very latest version or the packages? Any slightly older version will be immune to dependency-poisoning, thanks of the scrutiny of users over several weeks.
Not really, but then someone needs to decide what version to use and when/how this version is updated. For every single dependency. I agree that keeping track of your dependencies and actually managing them may be better engineering but it's a lot of work not many people want to do
We show alerts in GitHub pull requests, or the CLI, if you add a dependency with a supply chain risk.
I don't do any heavy computations except for running test suites of various kinds, and these seem to perform the same on raw hardware as they do in the Kernel-based VMs.
With such container, we can catch the compromised supply-chain attach easily, right?
Does anyone know such container exist?
But, say you had such a container, there’s an important distinction between “you captured a log showing the smoking gun evidence of the supply chain attack”, and “you successfully picked that log out of all of the log data you generated and classified it with high confidence as an attack”.
Speaking from experience, the second problem is the hard problem for a multitude of reasons. So while you would have the data, you’d probably have trouble getting good precision/recall on when to actually sound the alarms vs. when it’s some SRE who needed to troubleshoot some network connectivity issues.
The suspect application doesn't need the privileges, so I'm not sure how much of a problem that is?
> there’s an important distinction between “you captured a log showing the smoking gun evidence of the supply chain attack”, and “you successfully picked that log out of all of the log data you generated and classified it with high confidence as an attack”.
Assuming that you're talking about the signal:noise problem, that's hard in the general case but I feel like you could easily pick off really obvious cases like trying to access private SSH/GPG keys and still get a lot of value.
Probably. I’d agree that it’s worth trying at the very least. I’ve run into enough “should be easy” cases that turn out to be not that easy that my default is to get the data and see if the hypothesis really pans out.
1. https://github.com/ossillate-inc/packj
It DOES NOT require a VM/Container; uses strace. It shows you a preview of file system changes that installation will make and can also block arbitrary network communication during installation (uses an allow-list).
Also a Little Snitch-like host-based firewall, which would request explicit permission to connect.
Generally a VM jail is preferable - firecracker or cloud-hypervisor(virtiofs & gpu passthrough) recommended.
A proper namespace jail (eg. bwrap) is sufficient for 99.9% of cases. To break out of a properly configured namespace jail you would need to sacrifice a 0day.
This is an oversimplification, there may be other protocols that are passed through or utilized, they would add to the surface.
My recollection is that Java libraries were larger, higher-quality, more stable, and better-maintained, and you didn't need as many of them. A Java jar was not a "package" but contained dozens of "packages" developed together. Jars tended to be self-contained or mostly self-contained; small dependencies would shipped inside. The idea of making npm packages as small as possible, like practically putting each file in a separate git repo, and publishing it as a separate artifact, emerged shortly after NPM itself, and it was radical, and not really particularly good. Java also has a much larger standard library, and between the packages that come with Java itself, the packages that aren't technically part of the standard library but were written by Sun/Oracle, and well-known third-party utilities, you didn't need a lot of third-party packages. And if you needed something tiny like left-pad and didn't have it, you'd probably just copy and paste it.
Maven doesn't allow execution of arbitrary code at install-time, which curbs a large number of potential supply-chain attacks.
Because of the JVM and JARs being mostly self-contained Maven doesn't really need to worry about system or runtime dependencies (unless you're using Scala...). This allows Maven to be a 'dumb' package manager that relies on simple semantics (no hidden specially-generated indices, for example) and be fairly successful. Of course, there's an internal battle of whether Gradle or Maven is superior, but they both rely on the same distribution and packaging specifications.
I have many gripes with Sonatype but Maven Central isn't really one of them. The fact you can publish a packages to the likes of PyPI, npm Registry, or Docker Hub with 0 friction makes those places very attractive to spammers and bad actors. Maven Central having a higher barrier of entry is a feature.
IIRC Brian Fox, the CTO of Sonatype, was actively involved with Maven in the early days and was part of the decision for Maven packages to use domains for namespaces. Namespaces are another valuable feature of Maven that makes supply-chain attacks like typo-squatting harder to pull off.
At the same time, some people genuinely shit on Maven Central and think that it's inferior to other registries.
I think golang has the best answer for this, where it's easy to impersonate but it has to be explicit.
I think Go's approach is interesting, though it does rely on some magic that isn't immediately obvious. I agree that being explicit is a tremendous benefit: it avoids the attack used here, and makes it less likely for typo-squatting to succeed (e.g., `npm install axiod`).
He was able to steal packages names for Python (PyPi), JS (npm), Ruby (Gem), where these various companies have their own private package repositories with private modules where they don't control the package names in the default repositories.
The main requirements for this attack are
1. Having private repositories, where the package names in the default repositories is not owned by the owner of the package.
2. Package manager allows downloading packages from multiple repositories (the default and private repositories) without being able to pin specific package to only be downloaded from the private repositories.
What's notable on his findings is the omission of Facebook and Google, which I believe due to their usage of Buck/Bazel and monorepos for their internal codes. Another thing to note was that Alex mainly target companies internal private packages, while this particular instance affects an open source project which was providing package on their own repository and make use of a package (which I was not able to find any bug bounty program for).
There's another post by Kjäll et.al [2] that explains how this particular vulnerabilities affects other package managers (PHP, Java, .Net, ObjC/Swift, Docker), in what conditions it's vulnerable, and how to mitigate the risk. Two notable language package managers that were not affected are
1. Rust, mainly because you have to explicitly select the private registry for each private packages.
2. Go, mentioned as unlikely, due to the use of FQDNs in the package names and hash verification by default.
I think anyone adding non default package repositories or providing one (their own private repo in enterprise setup, or 3rd party provided repositories), need to be aware of this particular class of vulnerability, and implement policy to mitigate it. I would say, individual devs installing on their dev machines or CI/CD systems based on shell commands (rather than secured package manager setup) would be the main area of attacks mainly due to the relative difficulty of auditing those scenarios.
[1]. https://medium.com/@alex.birsan/dependency-confusion-4a5d60f...
[2]. https://schibsted.com/blog/dependency-confusion-how-we-prote...
And from the engineering blog, "[...] PyTorch 1.0, the next version of our open source AI framework."[1] (emphasis mine)
[0] https://www.facebook.com/whitehat/
[1] https://engineering.fb.com/2018/05/02/ai-research/announcing...
However Meta has since ditched it[2], and a careful keyword search of pytorch.org, linuxfoundation.org, suggests there is not any current official bug bounties for PyTorch.
I couldn’t bring myself to use a wildcard for a long time. I always specified the exact version and incremented manually to feel like I was at least trying to maintain control.
I still think it’s an insane practice, but with software engineering ever increasingly being the art of composing dependencies with bits of glue code, I get it.
PyPI probably needs a vetting system for new contributors of some kind.
I suspect a prime reason is the absence of package management on Windows which a lot of developers (and users) use, and secondly the desire by developers to always use cutting edge library features when writing code, but nobody wanting to upgrade any dependencies after. There used to be a lot discipline about being compatible with many libraries versions IMO, nowadays people just specify the latest version of each library in their requirements.txt file (or equivalent in other languages).
Yet, every main Linux distribution has its own packaging format (deb, rpm, etc) , package naming convention, dependency resolver, package release strategy (rolling, fixed, etc) , package build & deployment system (source, binary, per arch binary, etc), and package install peculiarities (custom, upstream focused, system wide, in a chroot, in a snap, etc), reproducibility constraints, etc...
So it's not like it's a _solved_ problem for Linux distributions.
Not to mention that most distribution package managers are system wide, while language package managers are often environment based.
> Yet, every main Linux distribution has its own packaging format (deb, rpm, etc) , package naming convention, dependency resolver, package release strategy (rolling, fixed, etc) , package build & deployment system (source, binary, per arch binary, etc), and package install peculiarities (custom, upstream focused, system wide, in a chroot, in a snap, etc), reproducibility constraints, etc...
> So it's not like it's a _solved_ problem for Linux distributions.
Just because someone reinvents the wheel does not mean it wasn't invented (solved before hand. I would also argue each distro package manager is miles ahead of any language one.
> Not to mention that most distribution package managers are system wide, while language package managers are often environment based.
That's the thing I was alluding to in the second part of my post, if developers would be more careful about backwards compatibility we wouldn't have to use environments. I do admit that packages for apps are more of an issue, it would be nice to upgrade those without having to upgrade the rest of the system.
Certainly not. A recent example: I wanted to try a KDE distribution, so I installed Neon which has three dependency updaters by default: pkcon, apt, and snap. If I use Python or Node, then I usually need to use their distribution management systems as well.
Dependency management is one area that completely fragments Linux into different distro universes.
I am not saying Windows is better (it isn’t) but if Linux had solved the problem, then most of us would share one solution.
The state of linux software distribution is completely abyssimal and ridiculous
Thousands.
Zero, essentially. State actors profit massively from such systemic weaknesses, so it is not in their interest to eliminate them for the population at large (they do of course want to eliminate them for themselves, but they already have extremely strict supply chain policies so that's mostly a solved problem).
Hell, we have state-sponsored institutions working hard to actively create vulnerabilities in software that previously didn't have them. Security vulnerabilities are a tool through which power is exercised. They're not going away as long as governments have any say in it.