musistudio/claude-code-router · error

Artifact origin is not the configured CCR gateway.

Error message

Artifact origin is not the configured CCR gateway.

What it means

validateCodexMediaArtifactUrl enforces that a media artifact URL is a plain http URL whose origin exactly matches the configured CCR gateway endpoint. If the protocol is not http: or url.origin differs from the endpoint's origin, it throws this — an SSRF-style guard ensuring artifacts are only fetched from the trusted gateway.

Source

Thrown at packages/core/src/agents/codex/media-preview-bridge.ts:276

      if (target) return target;
    } catch (error) {
      lastError = error;
    }
    await sleep(codexMediaPreviewPollIntervalMs);
  }
  throw new Error(`Codex App CDP page target was not available${lastError ? `: ${redactBridgeError(lastError)}` : "."}`);
}

function isCodexAppPageTarget(target: DevToolsTarget): boolean {
  if (target.type !== "page" || !target.webSocketDebuggerUrl) return false;
  const url = target.url || "";
  return url.startsWith("app://codex") || url.startsWith("app://chatgpt") || /\b(codex|chatgpt)\b/i.test(target.title || "");
}

function validateCodexMediaArtifactUrl(value: string, endpoint: string): ValidatedArtifactUrl {
  const expected = new URL(endpoint);
  const url = new URL(value);
  if (url.protocol !== "http:" || url.origin !== expected.origin) throw new Error("Artifact origin is not the configured CCR gateway.");
  if (url.username || url.password || url.hash) throw new Error("Artifact URL contains unsupported credentials or fragments.");
  if (!url.pathname.startsWith(MEDIA_ARTIFACT_PATH_PREFIX)) throw new Error("Artifact URL does not use the CCR media artifact path.");
  const encodedId = url.pathname.slice(MEDIA_ARTIFACT_PATH_PREFIX.length);
  if (!encodedId || encodedId.includes("/")) throw new Error("Artifact URL contains an invalid identifier.");
  const artifactId = decodeURIComponent(encodedId);
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(artifactId)) {
    throw new Error("Artifact URL contains an invalid identifier.");
  }
  const keys = [...url.searchParams.keys()];
  const token = url.searchParams.get("token") || "";
  if (keys.length !== 1 || keys[0] !== "token" || !/^[A-Za-z0-9_-]{32}$/.test(token)) {
    throw new Error("Artifact URL contains an invalid access token.");
  }
  return { artifactId, url };
}

async function loadCodexMediaArtifact(validated: ValidatedArtifactUrl, signal: AbortSignal): Promise<LoadedMediaArtifact> {
  let response: Response;

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Make the configured gateway endpoint origin exactly match the artifact URL origin (same scheme, host, port)
  2. Regenerate artifact URLs from the same gateway endpoint string used in configuration
  3. Normalize host aliases (localhost vs 127.0.0.1) on both sides before validating

Example fix

// before
validateCodexMediaArtifactUrl(artifactUrl, "http://127.0.0.1:8080"); // artifactUrl is http://localhost:8080/...
// after
validateCodexMediaArtifactUrl(artifactUrl, "http://localhost:8080"); // origins now match
Defensive patterns

Strategy: validation

Validate before calling

function sameOrigin(artifactUrl: string, endpoint: string): boolean {
  try { return new URL(artifactUrl).origin === new URL(endpoint).origin; }
  catch { return false; }
}
if (!sameOrigin(url, ccrEndpoint)) throw new Error('skipping artifact from untrusted origin');

Type guard

function isTrustedArtifactOrigin(value: string, endpoint: string): boolean {
  try { const u = new URL(value); return u.protocol === 'http:' && u.origin === new URL(endpoint).origin; } catch { return false; }
}

Prevention

When it happens

Trigger: Passing an artifact URL whose host/port/scheme differs from the configured gateway endpoint: https vs http, a different hostname or port, localhost vs 127.0.0.1, or a fully external URL.

Common situations: Gateway endpoint config says http://127.0.0.1:PORT but artifact URLs were generated with http://localhost:PORT (or the machine's LAN IP); endpoint configured behind an https proxy while artifacts use http; a crafted/misrouted URL from an untrusted message payload.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/e1f02dce7f46c21d. Report an issue: GitHub.