Skip to content

CIMD client metadata URL must be HTTPS with no loopback exemption, so CIMD cannot be driven against a local fixture #2305

Description

@cliffhall

The problem

getCimdClientMetadataUrlError (core/client/config-parse.ts) rejects any CIMD client metadata URL that is not HTTPS:

if (url.protocol !== "https:") {
  return CIMD_METADATA_URL_HTTPS_ERROR;
}

There is no loopback exemption. The check is applied to the settings form and, through refineCimdMetadataUrlCimdConfigSchema, to client.json as it comes off disk — so it cannot be worked around by hand-editing the file either.

The consequence is that CIMD cannot be exercised against anything served locally. Every test server in this repo speaks plain HTTP, so a CIMD metadata document hosted by one of them is not a legal clientMetadataUrl, and the whole registration path is unreachable in local development.

Why this is worth fixing rather than documenting

This is the same shape as #2280 / #1944, from the other side. There, the SDK's over-narrow loopback allow-list for token endpoints made a legitimate local setup fail, and we treated it as a real defect worth explaining carefully. This is our own over-narrow allow-list doing the same thing to our own testing story.

Concretely, it is why #2242 shipped verified by unit and integration tests alone: the v2.6.0 release smoke recorded it as the one row with an observable UI surface that could not be reached. Driving it required standing up a self-signed HTTPS listener purely to hold a JSON document, plus NODE_TLS_REJECT_UNAUTHORIZED=0 in the test server's environment so its own fetch of that document would succeed. That worked — Connection Info read Client registration — Client ID Metadata (CIMD) with the client id equal to the metadata URL — but it is not a reproduction anyone will run casually.

The security question, stated honestly

The HTTPS requirement is not arbitrary: a CIMD client id is a URL an authorization server dereferences, and over plain HTTP its contents are attacker-modifiable in transit. SEP-991 is right to expect HTTPS in production.

But loopback is the documented exception to exactly this reasoning everywhere else in the stack — it is why the SDK exempts localhost, 127.0.0.1 and ::1 from its own token-endpoint TLS assertion, and why core/auth/cimd.ts already says in a comment that an already-stored client_id may be an http:// URL "used by local dev/test metadata servers". So the runtime is willing to use one; only the config validation refuses to accept one.

Options

  1. Exempt the three loopback literals, matching the SDK's token-endpoint exemption and this repo's own comment. Narrowest change, and consistent with what the runtime already tolerates.
  2. Keep the check and add optional TLS to the composable test server, so a fixture can serve the document over HTTPS with a self-signed cert. Heavier, and pushes a cert into the repo or a generation step into the harness.
  3. Gate the exemption behind an explicit dev flag.

Option 1 is the one that matches existing precedent; recording the others because the trade is a real one and the security reasoning above deserves a decision rather than a default.

Acceptance

  • A loopback http:// CIMD metadata URL is accepted (whatever mechanism is chosen), or a decision is recorded against this issue explaining why it should not be
  • test-servers/configs/oauth-cimd-http.json can be driven end to end from the web client with no self-signed HTTPS listener
  • The non-loopback HTTPS requirement is unchanged, with a test asserting a plain http:// public host is still rejected
  • docs/test-servers.md's CIMD section updated to drop the workaround

Context

Found while building the CIMD fixture during the v2.6.0 release smoke, to clear the one finding the ledger recorded as unreachable.

Activity

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingv2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions