yamadashy/repomix · error · RepomixError

Refusing to access ${host}: it is a cloud instance metadata

Error message

Refusing to access ${host}: it is a cloud instance metadata endpoint, not a git host.

What it means

Repomix refuses to operate on a git remote whose hostname resolves to a cloud instance metadata endpoint (e.g. 169.254.169.254 on AWS/GCP/Azure). Accessing such endpoints is a well-known SSRF vector, so assertNotMetadataEndpoint throws a RepomixError before any network call is made. It is a deliberate security guard, not a transient failure.

Source

Thrown at src/core/git/gitMetadataEndpoint.ts:124

    // git splits host from path at the FIRST colon (so neither user nor host may
    // contain one), and ssh treats everything before the LAST @ as the user, so
    // the host is matched after a greedy colon-free user part. It can be a
    // bracketed IPv6 literal (user@[fd00:ec2::254]:path), so match a bracketed
    // group before falling back to a plain host.
    const scpMatch = remoteValue.match(/^[^/:]+@(\[[^\]]+\]|[^/:@]+):/);
    return scpMatch ? normalizeHost(scpMatch[1]) : null;
  }
};

export const isMetadataEndpoint = (host: string): boolean => BLOCKED_HOSTS.has(host) || LINK_LOCAL_IPV4_RE.test(host);

/**
 * Throws when a remote value points at a cloud metadata endpoint.
 */
export const assertNotMetadataEndpoint = (remoteValue: string): void => {
  const host = extractRemoteHost(remoteValue);
  if (host !== null && isMetadataEndpoint(host)) {
    throw new RepomixError(`Refusing to access ${host}: it is a cloud instance metadata endpoint, not a git host.`);
  }
};

View on GitHub (pinned to f465ad9093)

Solutions

  1. Replace the remote value with a real git host URL (github.com, gitlab.com, self-hosted instance).
  2. Check where the remote string is generated — fix templating/env substitution that injected the metadata host.
  3. If you control an air-gapped environment and intentionally use such a host, change the hostname mapping; the guard is intentionally not bypassable.
  4. Verify with a guard before calling: extract the host yourself and reject metadata endpoints early.

Example fix

// before
repomix --remote http://169.254.169.254/latest/meta-data
// after
repomix --remote https://github.com/user/repo
Defensive patterns

Strategy: validation

Validate before calling

import { extractRemoteHost } from './src/core/git/gitRemoteUrl.js';
const host = extractRemoteHost(remoteValue);
if (host === null || /(^|\.)(169\.254\.169\.254|metadata\.google\.internal)$/.test(host)) {
  throw new Error(`Refusing non-git or metadata host: ${host}`);
}

Type guard

const isGitHost = (remoteValue: string): boolean =>
  /^(https?:\/\/|git@)[^\s/]+\/[^\s/]+\/[^\s/]+/.test(remoteValue) &&
  !/169\.254\.169\.254|metadata\.google\.internal/.test(remoteValue);

Try / catch

try {
  await runRepomix({ remote: remoteValue });
} catch (e) {
  if (e instanceof RepomixError && e.message.includes('cloud instance metadata endpoint')) {
    console.error('Remote URL points at a metadata endpoint; supply a real git host URL.');
  }
}

Prevention

When it happens

Trigger: assertNotMetadataEndpoint(remoteValue) is called with a remote URL/string whose extracted host matches a known metadata IP/hostname such as 169.254.169.254 or metadata.google.internal; typically via cloning or fetching a remote value that was passed as --remote or read from a config.

Common situations: Malicious or misconfigured repository URLs in CI (SSRF probing); typos or templating bugs where an environment variable like an instance metadata URL is substituted into a git URL; fuzzing/security testing of the remote handling.

Related errors


AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29). Data as JSON: /api/errors/6ea002da270294c9. Report an issue: GitHub.