Files
renovate/lib/config/presets/http/index.ts
Jamie Tanna acb46bc706 fix(config): surface blocked hosts more clearly when resolving config
With the new hardening on blocking internal hosts with outbound HTTP
calls, we should build on top of this to ensure that the UX is better
when a preset is blocked.

We can do this by making sure that when `HOST_BLOCKED`, we report a more
targeted config validation error.

We can also make sure to pass around our `internalGrants`, similar to
how we currently allow an admin's `headers` are handled.

Co-authored-by: Claude Fable 5 <jamie.tanna+claude-code@mend.io>
Co-authored-by: Claude Opus 5 <jamie.tanna+claude-code@mend.io>
2026-09-10 14:52:01 +01:00

43 lines
1.6 KiB
TypeScript

import { HOST_BLOCKED } from '../../../constants/error-messages.ts';
import { logger } from '../../../logger/index.ts';
import { ExternalHostError } from '../../../types/errors/external-host-error.ts';
import { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';
import { Http } from '../../../util/http/index.ts';
import type { HttpResponse } from '../../../util/http/types.ts';
import { parseUrl } from '../../../util/url.ts';
import type { Preset, PresetConfig } from '../types.ts';
import { PRESET_DEP_NOT_FOUND, parsePreset } from '../util.ts';
// every response this instance fetches becomes Renovate configuration, so an internal host needs a deliberately-scoped `allowInternal` grant
const http = new Http('preset', { responseBecomesConfig: true });
export async function getPreset({
repo: url,
}: PresetConfig): Promise<Preset | null | undefined> {
const parsedUrl = parseUrl(url);
let response: HttpResponse;
if (!parsedUrl) {
logger.debug(`Preset URL ${url} is malformed`);
throw new Error(PRESET_DEP_NOT_FOUND);
}
try {
response = await http.getText(url, { cacheProvider: memCacheProvider });
} catch (err) {
if (err instanceof ExternalHostError) {
throw err;
}
// keep the block distinguishable from a plain 404, so it surfaces as its own config validation error
if (err.message === HOST_BLOCKED) {
throw err;
}
logger.debug(`Preset file ${url} not found: ${err.message}`);
throw new Error(PRESET_DEP_NOT_FOUND);
}
return parsePreset(response.body, parsedUrl.pathname);
}