-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proxy.golang.org: don't cache /@latest for modules that no longer exist at the upstream head revision #39007
Comments
Sorry, but I don't understand what the actual feature request here is. My best guess is: module In this situation, you're saying that we should assume that If that's wrong please be very specific about the proposal. I can't imagine a version of this that I think is a good idea so I'm struggling to understand the suggestion. |
fyi - #32239 is related. We tried this as another way to address this type of issue, but we had to give it up because of noticeable performance degradation. |
Behaviorally, yes. But I would phrase the causality of it a bit differently:
Since τ₃ > τ₁ and τ₄ > τ₂, we can infer that the state of the repo probably changed at some point between τ₂ and τ₃, and thus the The next time
|
We can't tell whether a module version is on the default branch, so we would have to invalidate I think this is a very specific workaround to a very specific problem that has better solutions and causes some amount of collateral damage. It certainly increases complexity. I would rather not do it. |
I agree that this seems like a lot of complexity for a pretty niche situation. I definitely empathize with @bcmills' point that we don't want users to have to a special workaround for this, but the tradeoff of this could harm other users (who then may also need a workaround, etc etc). I'm also not confident that I know every single side effect of this change. If this becomes a bigger problem that more people experience, then let's re-visit this. For now, a reasonable solution is to use gomodule/redigo#440 (comment) as a guideline if anyone else enounters this. Maybe documenting it if that issue isn't good enough. This also relates back to #30134, where we could do more here if we had more information from the error message (like @heschik alluded to). It's difficult to make the right decision about whether or not to drop one of our cache entries if there was a |
Could a user exploit this to break a repo simply by putting in a PR that is then cached in this way? |
@stevenh, no: the |
Yes, that's true.
It would not break any existing users, since they are all requesting explicit versions. It could indeed break new users of the module, but a module author can already break new users of the module in all sorts of ways (such as by pushing a |
A similar approach that would reduce overall complexity would be to apply the same TTL for That would have fixed To me the source of complexity here is the desire to treat |
The reason that proxy is treating |
It's not even that. As far as I recall this is exactly the same behavior everything else gets. If a module goes from existing to failing to download, we'll continue to serve it for as long as we can. That goes for branches, tags, pseudoversions, everything. |
That seems like a major problem. What happens if the branch is, say, (CC @FiloSottile) |
The “mirror's promise” is that existing users will be able to continue to use the dependency versions that they were already using. It does not promise that the As noted in #39007 (comment), it is already possible for a module author to break
Expiring the cache entry for |
One of the primary goals of the proxy is to protect users from flaky upstreams, in particular outages. Since the go command gives us no way to distinguish outages from deliberate actions, we are required to be conservative and not try to infer intent. Adding new dependencies is not a trivial use case and it is not acceptable for the ecosystem to break the next time some origin server goes down for a day. I don't think that's negotiable but if you would like to argue that case, this is probably not the place to do it. If the fix for #24031 isn't sufficient to cover the security use case that sounds like a critical problem with it. The vast majority of people are presumably not going to be tracking a branch. I don't think this discussion is going anywhere and I think this issue should be closed. |
Here's another poor interaction from caching
In the current release of the parent module ( It is possible for the module author to fix the problem by restoring the |
In gomodule/redigo#440, a nested
github.com/gomodule/redigo/redis
module was created and subsequently removed from thegithub.com/gomodule/redigo
repository: today, the nested module does not exist at the head revision of that repo, and also does not exist in the latest tagged release of the parent module (github.com/gomodule/redigo
).In gomodule/redigo#440 (comment) and gomodule/redigo#440 (comment), I noted that
proxy.golang.org
was still serving an old commit for/@latest
for the nested module over an hour later, even thoughGOPROXY=direct
correctly reported that there was nolatest
version of that module, and even thoughproxy.golang.org
did know about a higher (and later) pseudo-version of that module.As a workaround, the owners of the repo had to tag an explicit release of the nested module, even though they did not intend for anyone to actually use that release.
I don't think that workaround should have been necessary: I think
proxy.golang.org
should not serve known-stale contents for the/@latest
endpoint. That endpoint should be invalidated whenever a newer version of the named module is successfully fetched, even if that version is not itselflatest
(as interpreted by thego
command).That may mean that
/@latest
transitions from advertising a version of the module to no longer advertising any such version, but that behavior is no worse than what would happen if the repo owner took some other drastic action to remove the module — such as publishing a commit on the default branch with all of the source code deleted, or publishing a commit with themodule
line declaring some other path. Regardless of the reason,proxy.golang.org
should view the affirmative non-existence of a module as a valid “latest” state for that module, and not get stuck advertising “the last version that did exist”.This only really matters for modules that never explicitly tagged any release or pre-release version, since the
go
command does not consult the/@latest
endpoint unless the list of release and pre-release versions is empty.(Note that, even if the
/@latest
endpoint itself does not advertise any version, the proxy should continue to serve all previously-fetched versions of any module with a suitable license. I am not proposing that we evict any explicit versions from the cache — only the/@latest
endpoint itself.)CC @jayconrod @matloob @katiehockman @heschik @hyangah @stevenh
The text was updated successfully, but these errors were encountered: