mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-31 01:37:24 +00:00
29a7b9c5f5
To harden Renovate from being able to access internal hosts, we can add a level of enforcement on all outgoing requests. We can split this into two types of traffic: - where the response becomes configuration (i.e. `extends`) - where the response does not become configuration (i.e. `customDatasources`) To harden this, we enforce on every outbound HTTP request: - check the resolved URL before anything, including cache lookups, can proceed - catching IP-literal hosts in every spelling the WHATWG URL parser normalizes - blocking known Cloud metadata IPs, too - a `dnsLookup` wrapper validates every address a hostname resolves to, on every new connection, which also defeats DNS rebinding - a `beforeRedirect` hook re-runs the URL check on each redirect target, with the new host getting its own grant lookup rather than inheriting the original host's verdict We default this enforcement to `warn`, to not break existing deployments and instead give them visibility into required configuration before a future major version (major+1) enables `block` by default. We'll also remove allow in a future major version (major+2), to give time for admins to migrate over. When a request is blocked, this degrades like an unreachable registry, so a Renovate run isn't aborted by a blocked request. As part of this, we can also provide a worked example of the different cases that do/do not need allowing via `hostRules`. Requests through an admin-configured proxy resolve DNS at the proxy, so `dnsLookup` never runs for them, so we can resolve the hostname locally and validate every address before the request instead. This doesn't catch everything, especially as the proxy may resolve the name to a different result, and if we can't resolve the name - possible in locked-down corporate environments - we fail open. Child processes aren't currently able to route traffic through Renovate's HTTP layer, so are unrestricted. Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io> Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io> Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
134 lines
4.5 KiB
TypeScript
134 lines
4.5 KiB
TypeScript
// System error
|
|
export const SYSTEM_INSUFFICIENT_DISK_SPACE = 'disk-space';
|
|
export const SYSTEM_INSUFFICIENT_MEMORY = 'out-of-memory';
|
|
|
|
export const SystemErrors = [
|
|
SYSTEM_INSUFFICIENT_DISK_SPACE,
|
|
SYSTEM_INSUFFICIENT_MEMORY,
|
|
] as const;
|
|
|
|
// Platform Error
|
|
export const PLATFORM_AUTHENTICATION_ERROR = 'authentication-error';
|
|
export const PLATFORM_BAD_CREDENTIALS = 'bad-credentials';
|
|
export const PLATFORM_GPG_FAILED = 'gpg-failed';
|
|
export const PLATFORM_INTEGRATION_UNAUTHORIZED = 'integration-unauthorized';
|
|
export const PLATFORM_NOT_FOUND = 'platform-not-found';
|
|
export const PLATFORM_RATE_LIMIT_EXCEEDED = 'rate-limit-exceeded';
|
|
export const PLATFORM_UNKNOWN_ERROR = 'platform-unknown-error';
|
|
|
|
export const PlatformErrors = [
|
|
PLATFORM_AUTHENTICATION_ERROR,
|
|
PLATFORM_BAD_CREDENTIALS,
|
|
PLATFORM_GPG_FAILED,
|
|
PLATFORM_INTEGRATION_UNAUTHORIZED,
|
|
PLATFORM_NOT_FOUND,
|
|
PLATFORM_RATE_LIMIT_EXCEEDED,
|
|
PLATFORM_UNKNOWN_ERROR,
|
|
] as const;
|
|
|
|
// Config Error
|
|
export const CONFIG_VALIDATION = 'config-validation';
|
|
export const CONFIG_PRESETS_INVALID = 'config-presets-invalid';
|
|
export const CONFIG_SECRETS_EXPOSED = 'config-secrets-exposed';
|
|
export const CONFIG_SECRETS_INVALID = 'config-secrets-invalid';
|
|
export const CONFIG_VARIABLES_INVALID = 'config-variables-invalid';
|
|
export const CONFIG_GIT_URL_UNAVAILABLE = 'config-git-url-unavailable';
|
|
export const CONFIG_INHERIT_NOT_FOUND = 'config-inherit-not-found';
|
|
export const CONFIG_INHERIT_PARSE_ERROR = 'config-inherit-parse-error';
|
|
|
|
export const ConfigErrors = [
|
|
CONFIG_VALIDATION,
|
|
CONFIG_PRESETS_INVALID,
|
|
CONFIG_SECRETS_EXPOSED,
|
|
CONFIG_SECRETS_INVALID,
|
|
CONFIG_VARIABLES_INVALID,
|
|
CONFIG_GIT_URL_UNAVAILABLE,
|
|
CONFIG_INHERIT_NOT_FOUND,
|
|
CONFIG_INHERIT_PARSE_ERROR,
|
|
] as const;
|
|
|
|
// Repository Errors - causes repo to be considered as disabled
|
|
export const REPOSITORY_ACCESS_FORBIDDEN = 'forbidden';
|
|
export const REPOSITORY_ARCHIVED = 'archived';
|
|
export const REPOSITORY_BLOCKED = 'blocked';
|
|
export const REPOSITORY_CANNOT_FORK = 'cannot-fork';
|
|
export const REPOSITORY_DISABLED = 'disabled';
|
|
export const REPOSITORY_CLOSED_ONBOARDING = 'disabled-closed-onboarding';
|
|
export const REPOSITORY_DISABLED_BY_CONFIG = 'disabled-by-config';
|
|
export const REPOSITORY_NO_CONFIG = 'disabled-no-config';
|
|
export const REPOSITORY_EMPTY = 'empty';
|
|
export const REPOSITORY_FORK_MISSING = 'fork-missing';
|
|
export const REPOSITORY_FORK_MODE_FORKED = 'fork-mode-forked';
|
|
export const REPOSITORY_FORKED = 'fork';
|
|
export const REPOSITORY_MIRRORED = 'mirror';
|
|
export const REPOSITORY_NOT_FOUND = 'not-found';
|
|
export const REPOSITORY_NO_PACKAGE_FILES = 'no-package-files';
|
|
export const REPOSITORY_RENAMED = 'renamed';
|
|
export const REPOSITORY_UNINITIATED = 'uninitiated';
|
|
|
|
/** cause repo to be considered as disabled */
|
|
export const RepositoryErrors = [
|
|
REPOSITORY_ACCESS_FORBIDDEN,
|
|
REPOSITORY_ARCHIVED,
|
|
REPOSITORY_BLOCKED,
|
|
REPOSITORY_CANNOT_FORK,
|
|
REPOSITORY_DISABLED,
|
|
REPOSITORY_CLOSED_ONBOARDING,
|
|
REPOSITORY_DISABLED_BY_CONFIG,
|
|
REPOSITORY_NO_CONFIG,
|
|
REPOSITORY_EMPTY,
|
|
REPOSITORY_FORK_MISSING,
|
|
REPOSITORY_FORK_MODE_FORKED,
|
|
REPOSITORY_FORKED,
|
|
REPOSITORY_MIRRORED,
|
|
REPOSITORY_NOT_FOUND,
|
|
REPOSITORY_NO_PACKAGE_FILES,
|
|
REPOSITORY_RENAMED,
|
|
REPOSITORY_UNINITIATED,
|
|
] as const;
|
|
|
|
// Temporary Error
|
|
export const REPOSITORY_CHANGED = 'repository-changed';
|
|
export const TEMPORARY_ERROR = 'temporary-error';
|
|
export const NO_VULNERABILITY_ALERTS = 'no-vulnerability-alerts';
|
|
|
|
export const TemporaryErrors = [
|
|
REPOSITORY_CHANGED,
|
|
TEMPORARY_ERROR,
|
|
NO_VULNERABILITY_ALERTS,
|
|
] as const;
|
|
|
|
// Manager Error
|
|
export const MANAGER_LOCKFILE_ERROR = 'lockfile-error';
|
|
export const FILE_ACCESS_VIOLATION_ERROR = 'file-access-violation-error';
|
|
|
|
// Host error
|
|
export const EXTERNAL_HOST_ERROR = 'external-host-error';
|
|
export const IGNORABLE_HOST_ERROR = 'ignorable-host-error';
|
|
export const HOST_BLOCKED = 'host-blocked';
|
|
export const HOST_DISABLED = 'host-disabled';
|
|
|
|
// Worker Error
|
|
export const WORKER_FILE_UPDATE_FAILED = 'update-failure';
|
|
|
|
// PR Error
|
|
export const PR_ALREADY_IN_MERGE_QUEUE = 'pr-already-in-merge-queue';
|
|
|
|
// Bundler Error
|
|
export const BUNDLER_INVALID_CREDENTIALS = 'bundler-credentials';
|
|
|
|
// Unknown Error
|
|
export const UNKNOWN_ERROR = 'unknown-error';
|
|
|
|
// PATH Error
|
|
export const INVALID_PATH = 'invalid-path';
|
|
|
|
// PAGE NOT FOUND
|
|
export const PAGE_NOT_FOUND_ERROR = 'page-not-found';
|
|
|
|
// Missing API required credentials
|
|
export const MISSING_API_CREDENTIALS = 'missing-api-credentials';
|
|
|
|
/** Logger not initialized */
|
|
export const LOGGER_NOT_INITIALIZED = 'logger-not-initialized';
|