Skip to content

fix(kosong): forward full host headers only to first-party endpoints - #2581

Open
he-yufeng wants to merge 1 commit into
MoonshotAI:mainfrom
he-yufeng:fix/host-headers-first-party-only
Open

fix(kosong): forward full host headers only to first-party endpoints#2581
he-yufeng wants to merge 1 commit into
MoonshotAI:mainfrom
he-yufeng:fix/host-headers-first-party-only

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

Related Issue

Resolve #2576

Problem

See linked issue. A provider with type = "kimi" and a third-party base_url (a Kimi-compatible proxy or gateway) received the complete X-Msh-* host identity set, device id included, because resolveOutboundHeaders looked at the vendor definition alone and never at the resolved endpoint.

What changed

The full header forwarding now also requires the resolved base URL to be a first-party Moonshot host (api.moonshot.ai / api.moonshot.cn). Third-party endpoints fall back to the User-Agent only, same as vendors without a hostHeaders: 'full' declaration. The vendor definition still decides the header contract; the endpoint decides whether that contract applies.

Tests cover both directions: the existing dialect-path case (kimi type on api.example.test) now asserts User-Agent only, and a new case confirms an explicit first-party base_url keeps the full set. The default catalog test is unchanged.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

resolveOutboundHeaders decided solely on the provider type, so a
kimi-typed provider pointed at a third-party base_url received the
complete X-Msh-* identity set, device id included. Gate the full
forwarding on the resolved endpoint being a first-party Moonshot host;
everything else gets the User-Agent only.
@changeset-bot

changeset-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7e6a1c5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Aug 3, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@7e6a1c5
npx https://pkg.pr.new/@moonshot-ai/kimi-code@7e6a1c5

commit: 7e6a1c5

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e6a1c5d6e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return { ...parseKimiCodeCustomHeaders(), ...hostLayer, ...customHeaders };
}

const FIRST_PARTY_HOSTS = new Set(['api.moonshot.ai', 'api.moonshot.cn']);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include the managed Kimi Code host in the allowlist

Include api.kimi.com here: the default managed endpoint is https://api.kimi.com/coding/v1 (packages/oauth/src/managed-usage.ts:29), and login provisions it as a type: 'kimi' provider (packages/oauth/src/managed-kimi-code.ts:590-594). With the current allowlist, every default managed/OAuth model request loses all X-Msh-* identity headers even though createKimiDefaultHeaders defines them for managed endpoints, so the primary logged-in flow no longer reports its platform and device identity.

Useful? React with 👍 / 👎.

return true;
}
try {
return FIRST_PARTY_HOSTS.has(new URL(baseUrl).hostname);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require HTTPS before forwarding device identity

Require url.protocol === 'https:' as well as an allowed hostname. With a configured URL such as http://api.moonshot.ai/v1, this hostname-only check forwards the device ID and the rest of the identity set over cleartext HTTP; Node's outbound client does not apply browser HSTS before the initial request, so an on-path party can observe the headers even if the server later redirects.

Useful? React with 👍 / 👎.

Comment on lines 568 to +571
const forwardsAll =
providerType !== undefined &&
getProviderDefinition(providerType)?.hostHeaders === 'full';
getProviderDefinition(providerType)?.hostHeaders === 'full' &&
isFirstPartyBaseUrl(baseUrl);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep inspection header provenance aligned with filtering

Pass the endpoint decision through to attributeHeaders as well. For a type: 'kimi' provider on a foreign base URL, this new condition emits only User-Agent, but inspection.ts:479-495 still computes forwardsAll solely from the provider definition and labels that surviving header as coming from the full host-header set. Consequently catalog.inspect() reports provenance inconsistent with the exact resolution pass used by get().

AGENTS.md reference: AGENTS.md:L20-L20

Useful? React with 👍 / 👎.

Comment on lines +565 to +567
// A vendor's `hostHeaders: 'full'` contract is meant for the vendor's own
// endpoint. A provider that speaks the same protocol but points elsewhere
// must not receive the host identity set (device id included).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move the inline explanation into the module header

Move or incorporate this explanation into the existing top-of-file responsibility header rather than placing it beside the statement; the scoped guide requires comments in this package to live solely in the top /** */ block and explicitly forbids comments beside functions or statements. The newly added explanatory comment in catalog.test.ts:215-216 should be removed or handled consistently as part of the same cleanup.

AGENTS.md reference: packages/agent-core-v2/AGENTS.md:L15-L19

Useful? React with 👍 / 👎.

@he-yufeng

Copy link
Copy Markdown
Contributor Author

CI note on the red shard: the failure is workspaceDirs.test.ts > refreshes live session views when another process edits local.toml timing out on a watch-driven reload, a filesystem-watch timing issue in workspace code. This PR touches only kosong/model/catalogService.ts and its catalog tests, so it cannot affect that watcher; the related suites pass locally (catalog 52/52, composition 66/66, tsc clean). A rerun of shard 2 should clear it whenever convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Device identity headers are forwarded to kimi-typed providers on third-party base URLs

1 participant