mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-26 23:39:13 +00:00
28ed2ee25e
When determining whether a Go module is public - which infers whether to cache it - we had previously miscategorised authenticated traffic to Go module proxies, as we only looked for `GOPROXY`, `GONOPROXY` and `GOPRIVATE`. Instead, we should treat a package as private if there is an authenticated Host Rule that matches the Go module. We can do this by checking for `hostType: go`, to catch only Go module specific authentication, and to avoid catching i.e. auth to `github.com`. If any credentials (`token`, `password` or `httpsPrivateKey`) are found, we treat this as credentialed. Co-authored-by: Claude Opus 5.5 <jamie.tanna+claude-code@mend.io>
93 lines
3.5 KiB
TypeScript
93 lines
3.5 KiB
TypeScript
import { isNonEmptyString } from '@sindresorhus/is';
|
|
import { getSourceUrl as githubSourceUrl } from '../../../util/github/url.ts';
|
|
import { getSourceUrl as gitlabSourceUrl } from '../../../util/gitlab/url.ts';
|
|
import * as hostRules from '../../../util/host-rules.ts';
|
|
import { trimTrailingSlash } from '../../../util/url.ts';
|
|
import { BitbucketTagsDatasource } from '../bitbucket-tags/index.ts';
|
|
import { ForgejoTagsDatasource } from '../forgejo-tags/index.ts';
|
|
import { GiteaTagsDatasource } from '../gitea-tags/index.ts';
|
|
import { GithubTagsDatasource } from '../github-tags/index.ts';
|
|
import { GitlabTagsDatasource } from '../gitlab-tags/index.ts';
|
|
|
|
import { parseGoproxy, parseNoproxy } from './goproxy-parser.ts';
|
|
import type { DataSource, GoproxyItem } from './types.ts';
|
|
|
|
/**
|
|
* The Go module proxy which serves public modules only, and which the Go toolchain uses by default.
|
|
*
|
|
* @see https://go.dev/ref/mod#module-proxy
|
|
*/
|
|
export const publicGoproxyUrl = 'https://proxy.golang.org';
|
|
|
|
/**
|
|
* Whether a module's data may be written to a package cache which is shared with others.
|
|
*
|
|
* `GOPRIVATE`/`GONOPROXY` is how the user declares which modules are private, and `GOPROXY` decides who serves the rest: whatever the public proxy serves is public by definition, whereas a self-hosted proxy may serve modules which are not.
|
|
*
|
|
* `direct` only counts as public alongside the public proxy, which is how Go's own default `GOPROXY` is written: there, it is the fallback for what the public proxy doesn't have. On its own it means every module comes from its source, which tells us nothing about who may read it.
|
|
*
|
|
* An unset `GOPROXY` is the default, so it is public too.
|
|
*
|
|
* A `hostType: go` host rule with credentials for the module's host is also a declaration that the module is private, as it can't be read without them.
|
|
*
|
|
* @see https://go.dev/ref/mod#private-modules
|
|
*/
|
|
function isPublicProxy({ url }: GoproxyItem): boolean {
|
|
return trimTrailingSlash(url) === publicGoproxyUrl;
|
|
}
|
|
|
|
function hasGoHostRuleCredentials(packageName: string): boolean {
|
|
const url = `https://${packageName}`;
|
|
return hostRules
|
|
.findAll({ hostType: 'go' })
|
|
.some(
|
|
(rule) =>
|
|
(!rule.matchHost || hostRules.matchesHost(url, rule.matchHost)) &&
|
|
[rule.token, rule.password, rule.httpsPrivateKey].some(
|
|
isNonEmptyString,
|
|
),
|
|
);
|
|
}
|
|
|
|
export function isPublicGoPackage(packageName: string): boolean {
|
|
if (parseNoproxy()?.test(packageName)) {
|
|
return false;
|
|
}
|
|
|
|
if (hasGoHostRuleCredentials(packageName)) {
|
|
return false;
|
|
}
|
|
|
|
const proxies = parseGoproxy();
|
|
|
|
return proxies.every(
|
|
(proxy) =>
|
|
proxy.url === 'off' ||
|
|
isPublicProxy(proxy) ||
|
|
(proxy.url === 'direct' && proxies.some(isPublicProxy)),
|
|
);
|
|
}
|
|
|
|
export function getSourceUrl(
|
|
dataSource?: DataSource | null,
|
|
): string | undefined {
|
|
if (dataSource) {
|
|
const { datasource, registryUrl, packageName } = dataSource;
|
|
|
|
switch (datasource) {
|
|
case ForgejoTagsDatasource.id:
|
|
return ForgejoTagsDatasource.getSourceUrl(packageName, registryUrl);
|
|
case GiteaTagsDatasource.id:
|
|
return GiteaTagsDatasource.getSourceUrl(packageName, registryUrl);
|
|
case GithubTagsDatasource.id:
|
|
return githubSourceUrl(packageName, registryUrl);
|
|
case GitlabTagsDatasource.id:
|
|
return gitlabSourceUrl(packageName, registryUrl);
|
|
case BitbucketTagsDatasource.id:
|
|
return BitbucketTagsDatasource.getSourceUrl(packageName, registryUrl);
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|