Rendered at 06:24:12 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
ravenstine 3 days ago [-]
I wonder why this was flagged. Maybe too controversial an opinion for HN? It is rather unconventional.
Though this isn't directly related to the topic, I do personally believe that too much updating can be a bad thing. We've been fed this narrative to always update because there are so many exploits that need patching all the time. This is certainly not untrue, but it's also not that simple. I think what we almost always ignore is the cost in the churn of both software development (or just patching bugs) and updates being constantly pushed. Every change to code adds the potential for a new exploit, even if a change was intended to fix an existing exploit. The more often you pull updates to a piece of software, the more often you are opening yourself up to either a new exploit or an outright malicious piece of code being snuck in. You also open yourself up to bugs that, while not necessarily exploitable, can cause catastrophic failures or features being broken indefinitely, as we have witnessed time and again with Microslop.
When it comes to developer dependencies specifically, my philosophy is to try and only use libraries that are simple enough that the likelihood they will actually need to be updated is minimal. I also tend to avoid updates for things that I don't truly need, such as a new framework feature. If the current version of a framework I'm using is working totally fine, then I don't necessarily have a reason to update and migrate to a new version just because other developers have introduced a new opinion for how their users should write their applications. Eventually I might do an upgrade, but by not upgrading to every single major, minor, or fix version, the fewer chances there are of bad code ruining my day (or career). Of course I don't treat all software the same. If I'm relying on cryptographic libraries for the purposes of security or privacy, then it makes sense to upgrade rather often.
In my personal life, I rarely update anything like my OS or individual pieces of software. I've had this attitude for over a decade and so far I've yet to have noticed my systems being hacked or my bank accounts being drained. As far as I can tell, the need to always update is massively overrated.
dj_gitmo 3 days ago [-]
IMO the best practice is to leave dependencies unpinned, but use a lock file, and only update the lock file a few times a year.
Upgrade enough that you don’t get stuck, but not often enough to expose yourself to supply chain attacks every time CI runs.
OJFord 3 days ago [-]
That just means that you have whatever % chance of catching an attack on the days you do upgrade, and then in the event you do, stay compromised for a large % of the year until your next bump though?
Constantly upgrading offers more days with that % chance of catching one, but at least means you'll see the fix or release-pull sooner too.
rvz 3 days ago [-]
The industry standard for the best peace of mind is for ALL dependencies to be pinned, both the lockfile and the dependencies.
Upgrades are done manually and all characters such as "^", "*", next to the version are removed for a fixed predictable version to avoid unexpected version bumps or package hijacked in-case if they are compromised.
OptionOfT 3 days ago [-]
The dependency file is more important for a library and less for an application.
For a library, the dependency file (Cargo.toml, package.json, ...) defines the lowest version and its constraints of the library's dependencies when using the library in your project.
It allows for the engine to try to resolve versions of common dependencies.
E.g., in Rust:
You have awesome-lib, and depend on dep-1. Your version constraint is 1.0.4, which allows for >=1.0.4 all the way up to <2.
I use another-lib, which also depends on dep-1, But requires 1.4.2.
The engine will then resolve it to a minimum of 1.4.2.
If another library comes in and requires 2.8.3, then that dependency will be duplicated, and hopefully the API surface in those libraries don't expose the underlying dependency directly, because then you get funny errors like "These things have the same name but are actually different".
bruhFaaahNo 3 days ago [-]
> The industry standard for the best peace of mind
I read about "industry standards" in software and never see them in the wild.
Odd to assume your own direct experience is uniformly distributed belief.
mgrandl 3 days ago [-]
Then you haven’t looked at a lot of open source repos? A ton of them are using renovate/dependabot which are doing exactly that for you. And it is certainly good practice.
bruhFaaahNo 3 days ago [-]
[flagged]
raincole 3 days ago [-]
It's a really weird hill to die on.
bruhFaaahNo 3 days ago [-]
[flagged]
littlecorner 3 days ago [-]
Perhaps upgrade to one a few versions out of date but confirmed to be good?
jmclnx 3 days ago [-]
> The old operating model was indeed fine in a much smaller, simpler tech world,
The thing with the 'old days' that does not happen now is developers would go out of their way to make sure new releases were API backward compatible. Now it seems anything goes. If the API changed, a new function may be created or the old function would use variable arguments to allow the older functionality.
With that said, providing backward compatibility seems to be hard these days due to a BOM (Bill of material/dependencies) that make a BOM of submarine look simple.
That ssh/xz issue kind of highlighted how complex things have gotten.
notepad0x90 3 days ago [-]
you just update them and that's it?
Usually, there are CI/CD pipelines, but also change and testing regimes of some sort. Dev/QA too before prod.
Here is my suggestion though:
- Don't use package repos on the internet, host local caches
- Update your package caches twice a week, not more frequently
- Unpin and update packages in dev as it makes sense, as soon as the package repos update
- QA whenever your team can actually do testing
- Prod, with your next release, no more frequently than 90 days
There is a reason public CVE disclosure is ballpark 90 days per ethical security research and testing norms. That's how long proper testing and release is expected to take.
If you have no specific reason to update a package, and it passes integration tests with more up to date packages, then don't update. Supply chain compromises aside, bugs have a way of creeping. Things get missed with tests. Either you take this careful approach, or you take the other extreme approach where you design everything so well and with so much costly infrastructure and people to manage it, that impact is priced into the availability and threat modeling, which almost no one can pull off except on paper (well.. I said almost...).
0xbadcafebee 3 days ago [-]
It's another startup sales pitch. Their argument is the entire ecosystem is screwed, but it's okay, you can run their uber complicated toolchain in a CI pipeline and that will fix everything, by reviewing all of the code of your dependency updates. (because all the other backdoored code was never reviewed? because you're better at reviewing upstream code than the upstream maintainers?)
My take is the "hot take" nobody likes to hear. I think you should actually follow standard security best practices. Don't update constantly to the latest bleeding edge versions, but do update to the latest security patched versions. Do pin your versions (and SHA hashes of releases). Do keep an artifact repository. Do cryptographic verification of artifacts. Do validate every dependency you add, understand who made it, what it does. Do try to minimize your dependencies. Do review every new dependency and see what it is you're pulling into your application and whitelist the sources and their signed keys. Do use code signing. Do use OAuth, ephemeral keys, MFA, certificates.
Linux distributions have been secure for a long time by following these practices. Even their unstable branches. If they can do it, you can do it.
pdonis 3 days ago [-]
> It's another startup sales pitch.
Exactly. And for bonus points, the first part of the article seems to be arguing for the common sense stuff you describe--but then the article suddenly pivots to "use our new shiny tool instead". Huh?
johnea 3 days ago [-]
All of this is really about web dev, not s/w dev in general.
npm and pip are curses on the planet.
One point right from the beginning of the article: Why would you EVER leave a public port open straight to phpMyAdmin?
This is what SSH tunneling is for...
illusive4080 3 days ago [-]
Did you not run phpMyAdmin in the 90s/2000s? Nobody was that secure back then.
johnea 1 days ago [-]
Yes, I did.
But I've always used SSH port forwarding to access everything except pages intended for public viewing...
zzo38computer 3 days ago [-]
I think a way to do is to reduce how many dependencies are needed.
sixtyj 3 days ago [-]
Yes, every time I get message that some dependency is needed to update, I get anxious what could go wrong not to mention recent situation with malware or robware silent distribution.
It doesn’t matter whether it is Wordpress, Python, Nodejs, PHP, to name a few.
I understand that updates are necessary but we need to change the way we do them.
If I had a solution, I would post it here…
huksley 3 days ago [-]
Agree on how scary it is to do npm upgrade right now.
But I don't understand why Dependabot is bad but Mendral is good. Why Dependabot will be an attack vector and Mendrol will not?
shad42 2 days ago [-]
Dependabot is focused on upgrading dependencies, and nothing else. One of your dep is outdated, here is an update.
Mendral is smarter when updating deps, it looks at newer version, scans for vulnerabilities or upgrade patterns that can put you at risk (eg. the update was published few hours ago, you should update it now).
Though this isn't directly related to the topic, I do personally believe that too much updating can be a bad thing. We've been fed this narrative to always update because there are so many exploits that need patching all the time. This is certainly not untrue, but it's also not that simple. I think what we almost always ignore is the cost in the churn of both software development (or just patching bugs) and updates being constantly pushed. Every change to code adds the potential for a new exploit, even if a change was intended to fix an existing exploit. The more often you pull updates to a piece of software, the more often you are opening yourself up to either a new exploit or an outright malicious piece of code being snuck in. You also open yourself up to bugs that, while not necessarily exploitable, can cause catastrophic failures or features being broken indefinitely, as we have witnessed time and again with Microslop.
When it comes to developer dependencies specifically, my philosophy is to try and only use libraries that are simple enough that the likelihood they will actually need to be updated is minimal. I also tend to avoid updates for things that I don't truly need, such as a new framework feature. If the current version of a framework I'm using is working totally fine, then I don't necessarily have a reason to update and migrate to a new version just because other developers have introduced a new opinion for how their users should write their applications. Eventually I might do an upgrade, but by not upgrading to every single major, minor, or fix version, the fewer chances there are of bad code ruining my day (or career). Of course I don't treat all software the same. If I'm relying on cryptographic libraries for the purposes of security or privacy, then it makes sense to upgrade rather often.
In my personal life, I rarely update anything like my OS or individual pieces of software. I've had this attitude for over a decade and so far I've yet to have noticed my systems being hacked or my bank accounts being drained. As far as I can tell, the need to always update is massively overrated.
Constantly upgrading offers more days with that % chance of catching one, but at least means you'll see the fix or release-pull sooner too.
Upgrades are done manually and all characters such as "^", "*", next to the version are removed for a fixed predictable version to avoid unexpected version bumps or package hijacked in-case if they are compromised.
For a library, the dependency file (Cargo.toml, package.json, ...) defines the lowest version and its constraints of the library's dependencies when using the library in your project.
It allows for the engine to try to resolve versions of common dependencies.
E.g., in Rust:
You have awesome-lib, and depend on dep-1. Your version constraint is 1.0.4, which allows for >=1.0.4 all the way up to <2.
I use another-lib, which also depends on dep-1, But requires 1.4.2.
The engine will then resolve it to a minimum of 1.4.2.
If another library comes in and requires 2.8.3, then that dependency will be duplicated, and hopefully the API surface in those libraries don't expose the underlying dependency directly, because then you get funny errors like "These things have the same name but are actually different".
I read about "industry standards" in software and never see them in the wild.
Odd to assume your own direct experience is uniformly distributed belief.
The thing with the 'old days' that does not happen now is developers would go out of their way to make sure new releases were API backward compatible. Now it seems anything goes. If the API changed, a new function may be created or the old function would use variable arguments to allow the older functionality.
With that said, providing backward compatibility seems to be hard these days due to a BOM (Bill of material/dependencies) that make a BOM of submarine look simple.
That ssh/xz issue kind of highlighted how complex things have gotten.
Usually, there are CI/CD pipelines, but also change and testing regimes of some sort. Dev/QA too before prod.
Here is my suggestion though:
- Don't use package repos on the internet, host local caches - Update your package caches twice a week, not more frequently - Unpin and update packages in dev as it makes sense, as soon as the package repos update - QA whenever your team can actually do testing - Prod, with your next release, no more frequently than 90 days
There is a reason public CVE disclosure is ballpark 90 days per ethical security research and testing norms. That's how long proper testing and release is expected to take.
If you have no specific reason to update a package, and it passes integration tests with more up to date packages, then don't update. Supply chain compromises aside, bugs have a way of creeping. Things get missed with tests. Either you take this careful approach, or you take the other extreme approach where you design everything so well and with so much costly infrastructure and people to manage it, that impact is priced into the availability and threat modeling, which almost no one can pull off except on paper (well.. I said almost...).
My take is the "hot take" nobody likes to hear. I think you should actually follow standard security best practices. Don't update constantly to the latest bleeding edge versions, but do update to the latest security patched versions. Do pin your versions (and SHA hashes of releases). Do keep an artifact repository. Do cryptographic verification of artifacts. Do validate every dependency you add, understand who made it, what it does. Do try to minimize your dependencies. Do review every new dependency and see what it is you're pulling into your application and whitelist the sources and their signed keys. Do use code signing. Do use OAuth, ephemeral keys, MFA, certificates.
Linux distributions have been secure for a long time by following these practices. Even their unstable branches. If they can do it, you can do it.
Exactly. And for bonus points, the first part of the article seems to be arguing for the common sense stuff you describe--but then the article suddenly pivots to "use our new shiny tool instead". Huh?
npm and pip are curses on the planet.
One point right from the beginning of the article: Why would you EVER leave a public port open straight to phpMyAdmin?
This is what SSH tunneling is for...
But I've always used SSH port forwarding to access everything except pages intended for public viewing...
It doesn’t matter whether it is Wordpress, Python, Nodejs, PHP, to name a few.
I understand that updates are necessary but we need to change the way we do them.
If I had a solution, I would post it here…
But I don't understand why Dependabot is bad but Mendral is good. Why Dependabot will be an attack vector and Mendrol will not?
Mendral is smarter when updating deps, it looks at newer version, scans for vulnerabilities or upgrade patterns that can put you at risk (eg. the update was published few hours ago, you should update it now).