6 ms·
Discussing "what is a lockfile" is a bit of a headache because different languages have different files which do different things. Generally speaking, there's s
by klodolph 5y ago
Discussing "what is a lockfile" is a bit of a headache because different languages have different files which do different things. Generally speaking, there's some file which specifies the dependency versions and some file with cryptographic checksums of the all transitive dependencies.
In Go it's go.mod / go.sum. In NPM, it's package.json / package-lock.json. In Rust it's Cargo.toml / Cargo.lock.
Diving into the exact details of what the author is saying is a bit outside my headspace at the moment. I think the author of the article may not actually understand the scenario where Go's package system differs. (I'm not sure I do, either.)
Suppose you have your project, projectA, and its direct dependency, libB. Then libB has a dependency on libC.
If projectA has a lockfile, you get exactly the same versions of libA and libB. This is true for Go, NPM, and Cargo. However, suppose projectA is a new project. You just created it. In Go, the version of libB that makes it into the lockfile will be the minimum version that libA requires, which means that any new, poisoned version of libB will not transitively affect anything that depends on libA, such as projectA. With NPM, you get the latest version of libB which is compatible with libA--this version may be poisoned.
- munificent 5y ago> any new, poisoned version of libB Conversely, you will get any old security-buggy version of libB instead. Most package managers when adding a new dependency assume newer versions are "better" than older versions. Go's minimum version system assumes older is better than newer. I don't think there's any clear argument you can make on first principles for which of those is actually the case. You'd probably have to do an empirical analysis of how often mailicious packages get published versus how often security bug fix versions get published. If the former is more common than the latter, then min version is likely a net positive for security. If the latter is more common than the former, then max version is probably better. You'd probably also have to evaluate the relative harm of malicious versions versus unintended security bugs.
- philosopher1234 5y agoGo just expects you to manually trigger the updates. Thats all. It still is in favor of updating to take security fixes, so i think your argument is wrong.
- munificent 5y agoLet's say my_app uses package foo which uses package bar. It turns out there is a security bug in bar. The bar maintainers release a patch version that fixes it. In most package managers, users of my_app can and will get that fix with no work on the part of the author of foo. I'm not very familiar with Go's approach but I thought that unless foo's author puts out a version of foo that bumps its minimum version dependency on bar, my_app won't get the fix. Version solving will continue to select the old buggy version of bar because that's the minimum version the current version of foo permits.
- geodel 5y agoYou keep harping on old buggy version where Go has been very clear that it is operator's explicit responsibility to have correct/updated/fixed versions of dependency running. It specially does not look good in your case considering you work for Google on a different programing language. If you have a clear point to make then compare it with your approach. Instead of making neutral sounding arguments when they are not.
- adamc 5y agoDon't drag in ad-hominem attacks. If you want to defend Go's approach, explain why having it be the "operator's explicit responsibility" is a good policy, likely to make apps (in general) more secure. The obvious implication of the example given is that, on average, it will be a mess.
- coder543 5y ago> I thought that unless foo's author puts out a version of foo that bumps its minimum version dependency on bar, my_app won't get the fix. Version solving will continue to select the old buggy version of bar because that's the minimum version the current version of foo permits. That is incorrect. The application's go.mod defines all dependencies, even indirect ones. Raise the version there, and you raise it for all dependencies. You cannot have one more than one minor version of a dependency in the dependency graph.
- klodolph 5y ago> I don't think there's any clear argument you can make on first principles for which of those is actually the case. I don't understand why someone would try to argue from first principles here, it just seems like such a bizarre approach. Anyway, it's not just a security issue. Malicious packages and security fixes are only part of the picture. Other issues: - Despite a team's promise to use semantic versioning, point releases & "bugfix" releases will break downstream users - Other systems for determining the versions to use are much more unpredictable and hard to understand than estimated (look at Dart and Cargo) https://github.com/dart-lang/pub/blob/master/doc/solver.md https://github.com/dart-lang/pub/blob/master/doc/solver.md https://github.com/rust-lang/cargo/blob/1ef1e0a12723ce9548d7da2b63119de9002bead8/src/cargo/core/resolver/mod.rs https://github.com/rust-lang/cargo/blob/1ef1e0a12723ce9548d7...
- munificent 5y ago> Other systems for determining the versions to use are much more unpredictable and hard to understand than estimated (look at Dart and Cargo) I'm one of the co-authors of Dart's package manager. :) Yes, it is complex. Code reuse is hard and there's no silver bullet.
- klodolph 5y agoNice! I hope I wasn't coming across as critical of Dart's package manager, or Cargo for that matter.
- munificent 5y agoIt's OK. There are always valid criticisms of all possible package managers. It's just a hard area with gnarly trade-offs.
- zeeboo 5y agoEvery change that fixes a security issue implies the existence of a change that introduced the security issue in the first place. Why is bumping a version more likely to remove security issues instead of introduce them? The reason why older is better than newer has more to do with the fact that the author has actually tested their software with that specific version, and so there's more of a chance that it actually works as they intended.
- woojoo666 5y agoSecurity issues aren't introduced intentionally, oftentimes they are found much later on in code that was assumed to be secure. Like the SSL heartbleed vulnerability. Once a vulnerability like that is discovered, you _want_ every developer to update their deps to the most secure version
- zeeboo 5y agoMy statement had nothing to do with intent. Conversely, once a vulnerability is introduced (intentionally or not), you don't want every developer to update their deps to the newly insecure version.
- woojoo666 5y agoExactly, so it's a trade-off, do you want to encourage updates at the risk of malicious updates (like with node-ipc). Or do you want to add friction to updates and thus risk security vulnerabilities persisting for longer. Node chooses one approach, Go chooses the other.
- zeeboo 5y agoAgain, it's not just malicious updates. Normal updates can also introduce security vulnerabilities. For example, I have a dependency at v1.0 and v1.0.1 introduces a security bug unintentionally. It is eventually fixed in v1.1. If I wait to update until v1.1, then I am not vulnerable to that bug whereas an automatic update to v1.0.1 would be vulnerable. My point is that in expectation, updating your dependency could be just as likely to remove a security vulnerability as it is to add one.
- riwsky 5y agoThe code itself isn’t the only risk factor; it’s weighted by others, like discoverability, which are asymmetric in time. If the white hats fix an issue in version n+1, they’re going to make sure people know. If black hats (or normal devs making a mistake) introduce an issue, no one will tell you about it. I.e. even if both strategies win just as often, min-version pulls ahead by taking less of a hit from losses.