Title is a little bit hyperbolic. I get that it's a real issue that needs fixing, but a GitHub URL is not a secure package identifier, it was never designed this way, and it's an unfortunate hack that it's become a defacto standard.
What we really need is for language-level package managers to support signed immutable packages, and for that to start being taken seriously above the OS-level.
Edit: author changed the title, it used to say something about a "GitHub's security facepalm"
I thought the same with the exaggerating. The author of the article can hardly blame github. But he makes a good point, I never realized how much I rely on github username policy in Go code :).
If golang allows to import from Git URLs over HTTP or SSH, then it is the same problem with DNS as with the github usernames, isn't it? If the domain name, from which you import, will disappear, then someone else can register it and serve malicious code. This is also pretty hyperbolic.
IMO It's simply solvable by refering to a commit hash, like govendor does it (or the gemfile in ruby for that matter). I am actually not sure why it's not possible to add commit hash to a golang import, I thought that $GOPATH/src contains only git repos (but I'm not sure about this).
Call me paranoid, but I've always assumed urls are not permanent. Domains can change, usernames can change, and published things can be taken down.
For example, I may publish something as an online backup or a mirror of my real repositories, without any kind of guarantee whatsoever. ONLY sharing because I want people to be able to see how the things I do were made. I mean, even most FOSS licenses explicitly state that there are no guarantees of any kind.
IMHO I think people should stop with the "if it's on internet, it must retain compatibility" mindset, and instead switch to a "this will break or disappear at any time unless explicitly stated otherwise" mindset.
Hence why it's important to have your own software package repository server and grab internal packages from that rather an external party for any serious infrastructure.
If you don't pin your deps to a commit, what's the difference between the author deleting their account (and being replaced), and the author merging an evil commit?
There is no difference technically, but the point is that as is the author has built up a reputation and trust, and that someone taking their name inherits the trust without the reputation.
It's still a bad idea not to pin your dependencies even if you trust the author.
Say you want to check out some older version of the code for bisecting, and it doesn't even build anymore because it worked with some version of the dependencies that was the latest years ago, good luck figuring out what commit they were all on at the time.
It's trivial to just update your own project to point to the latest upstream SHA-1s and commit that, this is why git's own facility to do this (submodules) pins you at specific upstream commits.
Right, so the author going awol would be a pretty big break off that trust right?
What about the author having their github account compromised? I agree that GitHub account names should not be released so quickly, but if you're seriously worried about that possibility then I'd think it's also wise to be worried about the possibility of upstream being compromised in other ways.
> but a GitHub URL is not a secure package identifier, it was never designed this way, and it's an unfortunate hack that it's become a defacto standard.
Thank you. GitHub shouldn't be the only line of defense between a malicious coder and your software.
> What we really need is for language-level package managers to support signed immutable packages
+1 Emphasis on immutable. Can someone explain why popular package managers like npm don't offer this? During the leftpad fiasco, it boggled my mind that someone could just "liberate" their packages one morning, and transitively break the build for thousands of projects. Immutable packages would have prevented this entire problem.
NPM fixed that situation by no longer allowing packages to be unpublished after 24 hours. NPM does not allow packages to republish new content under a previously-used version number. NPM by default generates a package-lock.json file (separate from package.json) which pins the versions of all dependencies (including transitive ones) and includes the hashes of the dependencies, which would protect users if npm's servers ever became malicious.
> NPM by default generates a package-lock.json file
Thanks for the tidbit, seen it been added May last year to npm5[0]. Hard to keep up if you don't use the tooling activity and only depend on it for other tooling.
I tried to debug Go project once, and the moment I saw that, I was completely shocked that it was importing from github urls, without even tags, or versions as far as I could tell. It seems dangerous to rely on a for-profit host and individual users. If 'network' dependencies are part of the language, it should at least be non-profit, or better Go project managed host. There are many examples, like PyPi, or PECL.
Go doesn't specifically rely on GitHub, but it can pull in dependencies with a simplified URL that points to a git repository hosted on GitHub. This is possible because GitHub renders an HTML meta tag on project pages that the go tool can reference to fetch information about the repository.
Anyone can actually 'reflect' dependencies hosted with various VCS with this method, and gopkg.in does essentially this (while adding version pinning).
> Go doesn't specifically rely on GitHub, but it can pull in dependencies with a simplified URL that points to a git repository hosted on GitHub. This is possible because GitHub renders an HTML meta tag on project pages that the go tool can reference to fetch information about the repository.
Is there somewhere I can read more about this tag? Opened up the source of one of my repos and I couldn't find it.
To my knowledge it hasn’t been tried. It shouldn’t be too difficult to author a tool to do so, which could itself be made go-gettable. With this you’d avoid the mess of shipping an alternate build of the go tool and all that entails.
I read somewhere that big companies use BitTorrent internally to update their codebase.
But yeah, I'd really like for someone to develop a VCS like that (even more if it's in Go, with no Cgo, and under BSD, MIT or Apache license). It'd make distribution, immutability and mirroring so much easier.
It is git, so everything is signed. Just not authenticated. If you don't use head but a release or some tag you should be fine. Also, github supports permanent URL's
I would never use that. It uses SHA1. The problem is the hash, not the signing. A secure package identifier doesn't necessarily need to be signed. Conversely, you must have a decent hash algorithm.
Your mentioned method signs the git commit hash. A signature is only as good as the hash you use, and SHA1 is not suitable.
This situation arises solely from Go's myriad dependency management tools [1], including the latest "official experiment" 'go dep', not having the notion of a package repository. Instead, package identity is tightly bound to package location [2], and doing "package management" on this identity results in HTTP GETs or equivalents to that location. This is documented as a core convention [2] of the Go world, by the designers themselves.
I was always bewildered by this choice [3][4], because many, many other package management systems have independently realized this to be a bad idea -- and that it's valuable to have an extra layer of indirection between package identity and package location to prevent this exact situation. The component that solves this indirection is called a package repository, which can then institute strict rules about immutability, deletions, and naming, if so desired. NPM didn't, for a long time, until they got burned. GitHub is not a package repository, but due to the Go community's guidance, is effectively being used as such in a large volume of Go code in the wild.
> "You can override the location of a package with dep."
As far as I know, this is true [1], and can be done with the 'source' rule in Gopkg.toml. However, the guidance for dep says [1]:
"A source rule can specify an alternate location from which the name'd project should be retrieved. It is primarily useful for temporarily specifying a fork for a repository. source rules are generally brittle and should only be used when there is no other recourse. Using them to try to circumvent network reachability issues is typically an antipattern."
This doesn't sound like a glowing endorsement of this feature.
> "Indirection doesn't solve the problem it just moves it to the centralized repository."
Precisely; we're in agreement. A repository can then choose to institute sensible rules, if they so desire: Maven Central has what I would consider to be sensible rules, while NPM prior to 'left-pad' did not. Without a repository, the community has no place to make this decision point, so everyone's left to fend for themselves.
> "Go designers recommend vendoring packages which solves the problem."
Can you point me to guidance from Go designers which substantiates your point? I have been searching for this and have been unable to find it.
> If you're using an externally supplied package and worry that it might change in unexpected ways, the simplest solution is to copy it to your local repository. (This is the approach Google takes internally.) Store the copy under a new import path that identifies it as a local copy. For example, you might copy "original.com/pkg" to "you.com/external/original.com/pkg". The gomvpkg program is one tool to help automate this process.
I think Google doesn't see the problem because they have internally all their dependencies copied locally. There is no fetching of external sources so for them the problem that some dependency URL is broken simply does not exist.
This is insane. Not that the username was reused, but rather that people are using a direct link to GitHub as their dependency management. At minimum you should manually fork it into a repo you control, but a proper package manager is what is really necessary.
Would you statically link to an ftp server in your code build process? What about to a random website for a piece of code? No, you wouldn't, and this is equally unprofessional.
A package manager would be vulnerable (to package hijacking via reclaimed Github username) only if that package manager is a transparent proxy to Github. Any package manager with its own central package repo, like NPM and RubyGems, would be unaffected by a reclaimed Github username. Even a package repo like crates.io, which uses Github to authenticate, wouldn't be vulnerable because user equivalence is by user ID rather than username.
> A package manager would only be vulnerable if that package manager is a transparent proxy to Github
A central-repository package manager that doesn't either enforce immutability or at least have strong protection against a deleted project being replaced with a same-name project poses the same risk, only with itself rather than GitHub and the target.
There are package managers that are safe against this, but I don't think it is yet the norm.
Agreed that any package manager that allows deletion and replacement is broken. However the OP is referring to Github specifically, which was not designed with the same requirements as a package manager; as much as I think it would be an improvement to prevent Github usernames from being reclaimed, this is a problem with Go encouraging people to depend upon Github URLs directly, not really with Github itself.
As far as I know (and correct me if I'm wrong) but NPM only manages a database of package names, most of which link to Github repos themselves. And NPM at least until recently allowed name reuse.
NPM requires one to log in to NPM before pushing new versions of a package, to which control of a specific Github username has no bearing. And I know of no way to "link" an NPM library to a Github repo, publishing requires a local copy and an explicit action: https://docs.npmjs.com/getting-started/publishing-npm-packag...
And yes, NPM allowed name reuse, and that was bad, but that was a problem on NPM's side, not Github's side, because NPM is supposed to be a robust package repository and Github was just designed to be a lightweight social network for programmers.
No, NPM hosts the tarballs itself. A project is not linked to a Github repo at all. It's just taken for granted that the repository on the tin (if there is one) is what you're getting when you npm install.
For f*s sake, the Java ecosystem is horrible and yet even they managed to get this right.
Maven Central doesn't allow deletion (except in very rare cases, and in those the packages were available in other repos), as result you can always rely on those packages staying available. You can import, and be done. Every dependency you declare has an explicit version as well.
The go and JS dependency management solutions are pure madness
Oh, what a low move. Whatever you consider the Java ecosystem to be, it's used by most large companies, millions of developers and has been one of the most successful, scandal-free ecosystems in the programming world... if you think that's horrible, you must explain yourself, otherwise you're just being a dick.
Isn’t this the developer’s or Go’s security issue first before it’s a GH facepalm? GH doesn’t make any representations about the provenance or the safety of the code on their site. It is the user and toolchain that’s making those potentially dangerous assumption, no? Doesn’t blocking id reuse open them up to a kind of ID squatting and DOS?
I am definitely against this nonsense. Don't depend on some third party for your solutions who never said that their urls are here to stay. Quite the contrary!
Huh. Someone once offered to buy my github username from me... I had no idea that was explicitly against their policy. (Not that I said yes, or had any interest in selling)
Many people appear to be accusing the author of being hyperbolic, saying "well, you shouldn't be relying on github urls being real." This is true, but it misses the point: whether they should have or not, people ARE using the technology in this way. GitHub can either take an ideological stand and continue allowing people to be unknowingly exposed to an attack surface, or they can make a reasonable effort to defend against malicious usage of their service. Perhaps there are material reasons why it would be wrong or prohibitively difficult for them to change their username policy, but if it isn't, I don't think it's unreasonable to request this of them while simultaneously admonishing people who assuming data from github will always be accurate.
Put another way, I would _also_ upvote an article that said "The Go package manager is insecure because it assumes github URLs never change owners."
The malicious use here is treating GitHub as a package repository. GitHub should not do anything about this other than explicitly stating that GitHub is not a package repository and they cannot be held accountable for using GitHub in a really dumb way.
Using GitHub HEAD is one of many ways it can be used. It’s not a very popular approach. People with important projects that often use other ways, such as vendoring via a tool like dep.
Even projects using dep continue this pattern of pulling things from github master. I just browed through the top projects on Github for go and pretty much all of them that contained a gopkg.toml pulled in one or more things from github directly from master
Literally the first example of the Go tour [1] tells you to run "go get". "dep" is not (yet) an official part of Go's tooling. So when the only official tool fetches HEAD and calls it a day, I think it's perfectly fine to say "Go does that".
The 'go get' tool is just a small convenience wrapper around git/hg/svn. Its intended for use by developers, for quickly taking a look at some source code. The tour use case you cited is also a good fit for 'go get'.
It was never intended to be a part of your production build process. If you push its outputs directly to production, you're holding it wrong.
It's pretty annoying. Most of the time I want to build a stable version not HEAD which could break in many ways. Using HEAD as a dep is pretty much insane. Stop publishing for several months and the code would most likely fail to build.
Ah, the new hotness is dep (as opposed to godep, as opposed to govendor). I love Go, but man if it doesn't have a bit of JavaScript's reïmplement-the-world problem.
The funny thing to me is that this was always pointed to as a problem of Lisps: Lisp is so powerful that a student can implement an object system as homework, and the issue is that every student will. It looks like this problem isn't limited to Lisp: any sufficiently-powerful language enables programmers to reïnvent the wheel rather than forcing them to collaborate (e.g. as with C, where doing anything is so incredibly difficult that it's easier to pitch in with someone else's project than start your own).
go dep hilarious fails to work with private repos. It just hangs whenever I try running it. Looking through its source code it looks like it's actually just a fork of glide.
If security is a concern, the entire premise behind package managers and blindly trusting code pulled from a remote server is flawed regardless of where it comes from.
Even then, the consumer of the package is still dependent on the security practices of the holder of the key. It's more secure, but still not something you can depend on universally as a consumer.
"I promise you can trust me" is not something you can trust.
No one (absolutely no one) should be trusting a human being to be 100% infallible when it comes to security. That's what I'd propose, without even going into the topic of the fallibility of software.
If you're interested in the topic, there are many good papers and studies on how we can't even trust ourselves when it comes to basic things like memory and honesty (with ourselves).
Don't blame GitHub for Go's clearly broken dependency solutions. What everybody should have learned after so many incidents like this is this: an artifact should only be deletable by nuclear fire
GitHub has a name squatting policy for a reason. I have multiple "names" because some guy's repo who abandoned GitHub years ago was released and I was able to reuse it for my own brand.
This is like saying if I buy a domain it should be mine for eternity even if it is no longer useful for me.
This seems akin to a new server receiving an existing IP address. If I ssh to that IP address after the change, it tells me the server's fingerprint has changed and I have to make an explicit choice to trust the new server. It seems like this could be made to work similarly.
And this explicit choice is not some Y/N decision that can be easily overlooked but it's editing known hosts, so that the user understands the seriousness.
This reasoning is wrong to me. I see this very much as a problem with using usernames to refer to repositories in the first place, not with username reuse. For heaven's sake, let me just refer to a repo by a unique ID of its own. There's no reason for the username to be in the repository URL.
So, a sha1 commit hash, which gives you an exact filesystem snapshot, and can't be faked with identical content if someone gets their hands on someone's account?
The real issue is Go just pointing to "whatever is the current HEAD" which is insane.
No, a commit hash points to a commit. This is for when we want to point to a repo, i.e. For exactly the same situations where we currently use URLs with usernames.
The original problem was Go rather stupidlt pointing to a repo, instead of a specific commit on a repo. Normal github use at the very least would be to point to tags. Someone deleted their account, all those tags (which are empty commits) become invalid.
Because you're not building a list of just username and repo names for software dependent purposes, right? That would be a massive security failing on your part.
Instead, I have to build something external from git, including "commit hash", in order to have a secure identifier for a commit. I would have a one off solution that isn't adopted widely.
It's not a concern for Linus, but maybe it should be? If SHA1's security properties don't matter, why was SHA1 chosen and not something faster? What about signing commits? This is affected by SHA1 collisions.
Would you mind elaborating on this? What scenario are you envisioning where this is an issue? I'd caveat that with "in practice", but I'm willing to set that aside to avoid derailing the conversation into what's practical or not.
People use the SHA1 hash when signing commits. If you can create collisions you can create repositories with arbitrary code without breaking the signature. See Github's blog post on the mitigations for more details: https://github.com/blog/2338-sha-1-collision-detection-on-gi...
> What scenario are you envisioning where this is an issue?
Not the parent, but the problem specifically with using github repos with a hash to identify a specific commit is that if someone can make a collision, they can make the code anything they want.
Linus doesn't consider this a problem, because he doesn't use untrusted repositories.
The hash is based on the content of the repo (and its history), is it not? Or am I misunderstanding? It's not that they can make a repo with arbitrary code of their choice cause a collision, correct? The chance of the collision be something meaningful in the context of the code at hand is vanishingly small, isn't it? Is it the concern that this can happen at all?
> The hash is based on the content of the repo (and its history), is it not? Or am I misunderstanding?
That is correct. The hash of a commit is based on the parent commit's hash, the hash of the tree (file state), and commit message (and maybe more, I don't remember).
>It's not that they can make a repo with arbitrary code of their choice cause a collision, correct?
They can make a repo with arbitrary code, but they need to change make specific (potentially wierd) commits to get a specific hash.
> The chance of the collision be something meaningful in the context of the code at hand is vanishingly small, isn't it? Is it the concern that this can happen at all?
The chance by normal users is really small. But someone malicious could intentionally try to manipulate it. This could be done by varying commit messages.
So if you trust such a person does not have control over the repo (Linus's position)its fine, but if a hash isn't cryptographically strong, malicious actors can make repos with commits pointing to arbitrary code with a specified hash.
Thanks for confirming. Getting back to the issue of using Github as a source of truth for deployment, that's got a host of issues besides reliance on SHA1, but I appreciate the reasoned response to the issues surrounding the hash itself as well. Appreciated!
Oh come on, this is not a justification, it's just complete laziness. Just spend the extra 5 seconds copying the repo URL from GitHub. It's not like you can avoid that the first time around when you don't know the username anyway (or on subsequent times for that matter, unless the username is pretty memorable), and you'll have a robust URL afterwards without security holes. And plus, then people can change their usernames without breaking links. The cost/benefit ratio is extremely low.
The security facepalm is the fact that you're pulling source code without signature verification. It's not github's responsibility to manage usernames. The blame and responsibility is on Go and whoever thought it's a good idea to pull in code this way.
There are so many scenarios were you can end up cloning malicious code when you're simply relying on cloning alone. What if someone hacked the author's github account and committed malicious code? And why do you trust that the author has no plans in the future to inject malicious code?
Did you just say it's not github's responsibility to manage usernames on their own site? You're aware that attacks on similar names (not even exact ones) are a very common form of security attack, right?
What signature verification would one have when accessing a public repo? If I tell somebody there's a really great tool at fakename/faketool, they are screwed.
Github has the right to "manage usernames" however they see fit. The problem is that a third party is making assumptions about these usernames and basing their entire security mechanism on it, even though that assumption is incorrect, and now they're blaming Github for it.
Not quite: his/her point is that it's on the user to validate the author as opposed to the location. If you care about security, you should pull from a repo, then check a against a signature.
Your https connection confirms you got something from github, but you have the ability to prove the thing you got from github was from the same individual.
I understand the "omg sha1" frenzy, but 1) you still need an incredible amount of compute power to generate a collision (you read your linked article, right?) and 2) even if you make something that collides, it still has to compile into the project.
Perhaps nation states can do this today. If that's your concern then, well, you've already lost because they've likely found other ways to compromise you with much less effort. For everyone else, sha1 for commits is still not _that_ bad.
>"incredible amount of compute power to generate a collision"
That article sets the "best case", not the worse, and that article is "old". The GPU/ASIC industry is bananas, and we have no idea what other breaks there are. MD5 is a great example of how quickly these things become dangerous.
SHA1 was a terrible choice when git was made, it's a horrific one now. SHA1 cannot be used for anything security sensitive. That domain is always larger than what we may first suspect.
>the alternative is... do nothing?
No, the alternative is to use gpg with a secure hash over and above anything git provides. This is a bad choice because there is no standardized git infrastructure built around anything secure.
This fragments the industry (like Go building their own, again) where git could instead continue to unify, making an interface that has a lot of eyeballs, visibility, and a secure, universal implementation. Instead, fragmentation remains the solution. Git could have easily taken care of this by simply listening to people back in ~2005 saying, "gee, maybe we shouldn't use a hash that's already on its deathbed". https://www.schneier.com/blog/archives/2005/02/cryptanalysis...
It would be nice just have used SHA-256. I hope Snowden didn't show us nothing.
In short: "My toolchain chose to do a thing that is insecure given your (publicly-known) approach to managing your usernames. Now I am exposed to a security vulnerability and it's your fault!"
No! This is the go ecosystem's fault! It was knowable that GitHub managed usernames this way and yet they still chose to introduce this security risk.
(Context: I'm here late into the conversation and after the title was changed)
When you consider github.com/foo/bar you see that foo has established a reputation by developing code for third party use. Can foo break upstream builds that rely on HEAD? Absolutely. However, given that foo has a reputation for high quality content is it likely for them, barring an exceptional event, to insert malicious code? Probably not.
The issue I have with github allowing username reuse in a broader context is that the reputation from a trusted user is transferred to a third party. That third party could be neutral, well meaning, or malicious. All the same, they should not be able to take the reputation developed by that user. In this example, if foo decides to become a bespoke tailor and deletes their github, someone should not be able to use their reputation.
In the context of go using urls as canonical locations for code, is it smelly? Oh yeah. Does that mean that username reuse isn't a problem? No. A lot of people here are pointing at either go developers or github. You can blame both and eventually get a robust solution from both.
When I did a large organization rename (GitHub helped us reclaim a name from a long-since disused account), we were extremely cautious because of this exact problem. Our GitHub organization was named XYZ, being renamed to ABC. We had GitHub rename a separate user, DEF, to ABC. We then picked a low risk time and had browser windows open when we initiated the swap of our new shiny ABC to ABC-old to immediately grab the name and then immediately grab the old name on a new account.
uh, did you read what the OP wrote? he said a long since disused account. i.e. how long a grace period do you desire they have?
github's general policy is that if an account has been dormant for a year (which might mean not just means commits, but also fetches from it) its can be recycled. This is because they dont want to enable username squatting.
How does this work with third party login? For instance I can use my github accout to log in to gitlab. Seems like a security risk for even dormant accounts.
I was not clear, github works as an identity provider. I am not talking about api access to github, I am talking about using github to log into other services.
They should only be reused if manually requested. Sometimes usernames had nothing on them (thus a manual enable is ok) and freeing up the username after a couple years of seeing no traffic seems fine too.
But really I kinda shudder to think of how much stuff is hackable just by stealing the right laptop and phone while someone is on vacation.
This reminds me about the whole `left-pad` fiasco and npm allowing same-name packages to be re-published. For a while I thought that the packages were hijacked [1].
GitHub should definitely not allow username reuse, but most prominently it's a Go issue, where they use GitHub as a package manager.
Had a conversation in 2015 with someone who was... a bit of an irritant. Future people tagging him in like 2017... ended up dragging in a completely innocent bystander. Because the guy in question had changed his account name, someone else has registered his old one, and GitHub, cluelessly, attached all of his comments to the new user.
The more I read about some issues with Go, the more I realise that it's beautiful and elegant because of the ties with Plan9 and the uncomplicated thinking that comes with it, but it suffers greatly because it won't consider how the world has changed since. So you get a very particular way of doing things (`GOPATH`, `gofmt`) and you're kind of out of luck when the abstraction leaks (`interface {}`).
Point in case: treat GitHub as part of the filesystem, so you don't need to host a package manager. I suspect that the end game is the opposite of Java (com.example/package/whatever) and in the long run you're expected to publish your source to a domain you control. Starting with GitHub and services like gopkg.in just gets people acquainted with the idea but in the enterprise you'll be importing `enterprise.com/factory/builder` or some such.
The article raises a good point, but I just wanted to take the time to praise GitHub's support, who've been repeatedly super helpful in helping me get inactive handles (including my own @andreis). It's definitely a far cry from other services like Twitter.
Where does it concern GitHub's security model? This is a serious question, I am not a GitHub user myself.
The only thing I get from the article is "people treat URLs as eternal, even if the site does not provide strong guarantees for that."
But that is not news and moot to debate, as a site's policy can change anytime and then you are still screwed. And nothing of this is specific to GitHub.
Using nixpkgs, this isn't a problem because the source hashes will mismatch if somebody tries to spoof a username with a malicious repository. We should all be using Nix more often.
I'm glad they allow reuse. I signed up very early on github, but my username was already taken... By someone who didn't contribute anything at all to anything, ever; and probably never used the account again.
One day, after many years, I emailed the github guys to know if I possibly get it, and they immediately, and very kindly agreed and renamed me.
I like the way gitlab approaches this. On gitlab if you change your username, the old username can't be used by anyone again.
I have faced this problem with github. I changed my username. The very next day, someone created an account with my old username and now all my resume, old profiles etc. were pointing to an empty github account. :(
This is not exactly an obscure scenario. If I was a better I would bet >10:1 odds they had already thought through this scenario and dismissed it for whatever reason (maybe equating it with having an irresponsible or malicious package author), i.e. reporting it wouldn't have done anything.
True, but we don't know for sure. If we're making guesses, I'd guess that someone made the decision about username re-use years ago-- before package management systems began relying on GitHub directly. If that is the case, then this issue could not have even been considered.
I don't make a lot of comments on HN, so I could use some constructive criticism on how to improve. My intent was to highlight content relevant to my point. Any suggestions on how I could do this better (maybe better formatting)?
What we really need is for language-level package managers to support signed immutable packages, and for that to start being taken seriously above the OS-level.
Edit: author changed the title, it used to say something about a "GitHub's security facepalm"