import { env } from '@4runr/shared';
const PRIVATE_IP_RANGES = [
    /^127\./,
    /^10\./,
    /^172\.(1[6-9]|2[0-9]|3[01])\./,
    /^192\.168\./,
    /^169\.254\./,
    /^\[?::1\]?$/,
    /^\[?fe80:/i,
    /^\[?fc00:/i,
    /^\[?fd00:/i,
];
const BLOCKED_HOSTS = new Set([
    '169.254.169.254',
    'metadata.google.internal',
    'metadata',
]);
function isProductionNode() {
    return (process.env['NODE_ENV'] ?? env.NODE_ENV) === 'production';
}
function isAllowInternalFetch() {
    return process.env['TOOL_PROXY_HTTP_FETCH_ALLOW_INTERNAL'] === 'true';
}
function isPrivateOrLoopbackHost(host) {
    const h = host.toLowerCase();
    if (h === 'localhost' || h === '0.0.0.0')
        return true;
    for (const range of PRIVATE_IP_RANGES) {
        if (range.test(host))
            return true;
    }
    return false;
}
export function assertSafeToolProxyHttpUrl(rawUrl) {
    let url;
    try {
        url = new URL(rawUrl);
    }
    catch {
        throw new Error('Invalid URL');
    }
    if (isProductionNode()) {
        if (url.protocol !== 'https:') {
            throw new Error('Only HTTPS URLs are allowed in production');
        }
    }
    else if (url.protocol !== 'http:' && url.protocol !== 'https:') {
        throw new Error('Only HTTP and HTTPS URLs are allowed');
    }
    if (url.username || url.password) {
        throw new Error('URL must not contain embedded credentials');
    }
    const host = url.hostname.toLowerCase();
    if (!host) {
        throw new Error('URL must include a hostname');
    }
    if (BLOCKED_HOSTS.has(host)) {
        throw new Error('Host is not allowed');
    }
    if (!isAllowInternalFetch() && isPrivateOrLoopbackHost(host)) {
        throw new Error('Private or loopback hosts are not allowed for this fetch');
    }
    return url;
}
//# sourceMappingURL=outbound-url.js.map