deepseek-ai/deepseek-harness · error

client-connection: trustedHosts entry ${JSON.stringify(entry

Error message

client-connection: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority

What it means

assertTrustedAuthority backs the client-connection trust fence against DNS rebinding and cross-site requests. Each trustedHosts entry must be a bare host or host:port authority whose canonical WHATWG URL parse equals the entry itself (case aside), so anything parsing would silently rewrite — schemes, paths, userinfo, whitespace, dangling or zero-padded ports, and non-canonical host spellings (hex IPs, percent-encoding, unbracketed IPv6, non-punycode IDN) — fails the plugin load instead of quietly broadening the grant.

Source

Thrown at packages/client/connection/src/api-request-trust.ts:57

/**
 * Assert one configured `trustedHosts` entry is a bare authority (`host` or
 * `host:port`) in canonical form: it must survive WHATWG parsing unchanged
 * (case aside). Anything parsing would silently rewrite is refused as a typo
 * that must fail the load loudly instead of being ignored until requests 403
 * or quietly changing the grant: URL parts beyond the authority
 * (`harness.internal/path`, `user@harness.internal` — which would authorize
 * the embedded hostname), stripped whitespace, a dangling colon or
 * zero-padded port (which would broaden an intended exact-port grant to every
 * port), and non-canonical host spellings (`0x7f.0.0.1`, percent-encoding,
 * unbracketed IPv6; IDN hosts are declared in punycode, the form the wire
 * carries).
 * @param entry - the configured value, verbatim.
 */
export function assertTrustedAuthority(entry: string): void {
  const entryUrl = parseAuthority(entry)
  if (entryUrl !== undefined && canonicalAuthority(entry, entryUrl) === entry.toLowerCase()) return
  throw new Error(`client-connection: trustedHosts entry ${JSON.stringify(entry)} is not a bare host[:port] authority`)
}

/**
 * Canonical form of a parsed authority: `hostname` when no port was written,
 * else `hostname:port`. The port is judged from URL parses under both special
 * schemes (their default ports differ, so `:80` and `:443` still count as
 * explicit), never from the raw string, where WHATWG trimming would misread
 * shapes like `host:port ` as port-less.
 */
function canonicalAuthority(entry: string, entryUrl: URL): string {
  // An authority that parsed under http cannot fail under https.
  const port = entryUrl.port !== '' ? entryUrl.port : new URL(`https://${entry}`).port
  return port === '' ? entryUrl.hostname : `${entryUrl.hostname}:${port}`
}

/**
 * Whether the request authority matches a `trustedHosts` entry. An entry with
 * an explicit port matches that exact authority; a port-less entry matches the

View on GitHub (pinned to b150a551b8)

Solutions

  1. Write entries as bare lowercase host or host:port — harness.example.com:8080, 192.168.1.10
  2. Encode IDN names in punycode (xn--mnchen-3ya.example) and bracket IPv6 literals ([::1])
  3. Drop schemes, paths, userinfo, surrounding whitespace, and leading zeros in ports; a port-less entry matches every port on that host

Example fix

# before
client-connection:
  trustedHosts:
    - https://harness.example.com:8080/
    - MÜNCHEN.example
    - 0x7f.0.0.1

# after
client-connection:
  trustedHosts:
    - harness.example.com:8080
    - xn--mnchen-3ya.example
    - 127.0.0.1
Defensive patterns

Strategy: validation

Validate before calling

// Validate entries with the shipped guard before the plugin loads:
import { assertTrustedAuthority } from '@deepseek-ai/dsh-client-connection'

for (const entry of config.trustedHosts ?? []) assertTrustedAuthority(entry)

Type guard

function isBareAuthority(entry: string): boolean {
  try {
    const u = new URL(`http://${entry}`)
    const port = u.port !== '' ? u.port : new URL(`https://${entry}`).port
    const canonical = port === '' ? u.hostname : `${u.hostname}:${port}`
    return canonical === entry.toLowerCase()
  } catch {
    return false
  }
}

Prevention

When it happens

Trigger: Loading the client-connection plugin with trustedHosts values such as https://host:8080, host.internal/path, user@host.internal, host:08080, host:, 0x7f.0.0.1, an unbracketed IPv6 literal, or a unicode IDN name.

Common situations: Pasting a full origin URL from the browser into cordis.yml; writing an IDN domain in unicode instead of punycode; leaving a trailing slash or colon; unbracketed IPv6 literals.

Related errors


AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24). Data as JSON: /api/errors/238e29b388021613. Report an issue: GitHub.