Skip to content

Harden OCI registry authentication - #1278

Draft
Christof Marti (chrmarti) wants to merge 3 commits into
mainfrom
copilot/secure-oci-auth
Draft

Harden OCI registry authentication#1278
Christof Marti (chrmarti) wants to merge 3 commits into
mainfrom
copilot/secure-oci-auth

Conversation

@chrmarti

@chrmarti Christof Marti (chrmarti) commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Harden OCI Feature and Template authentication against registry-controlled Bearer realms that could trigger SSRF or forward registry credentials to an attacker-selected endpoint.

This builds on the work in #1276 while narrowing the change to the authentication boundary and adding a registry-scoped compatibility escape hatch for legitimate external token services.

Session Context

Key decisions from the development session:

  • Keep registry parsing unchanged: Localhost, private-IP, single-label, IPv6, and custom-port registries are legitimate. The vulnerability is addressed at the secondary token-request boundary instead of adding a broad registry URL policy.
  • Bind compatibility exceptions to both hosts: --allow-cross-origin-auth-host <registry-host>=<auth-host> is repeatable. A bare auth-host allowlist would let any workspace-selected registry invoke that host as a confused deputy.
  • Keep built-ins minimal: Docker Hub and GitLab.com are the verified public cross-origin flows. GHCR, Quay, GCR, public ECR, and normal ACR flows are same-origin and use the default policy.
  • Trust the full mapped exchange: Exact trusted mappings may receive anonymous token requests, Basic credentials, and refresh/identity tokens. The exact HTTPS authority pair is the trust boundary.
  • Fail closed on redirects: Token requests do not follow redirects. Normal registry requests retain existing redirect behavior, and the final response URL is used to validate the challenge origin.
  • Preserve localhost compatibility: Exact-authority http://localhost token realms remain supported for local Feature development; remote HTTP realms remain rejected.

Changes

  • Validate Bearer realms before credential lookup or token endpoint I/O.
  • Permit exact-authority HTTPS realms and exact-authority localhost HTTP realms.
  • Add built-in Docker Hub and GitLab.com registry-to-auth-host mappings.
  • Add repeatable --allow-cross-origin-auth-host <registry-host>=<auth-host> mappings for enterprise registries.
  • Forward registry credentials, including refresh/identity tokens, across explicitly trusted origin mappings.
  • Disable redirects for token acquisition and handle redirect refusal as an authentication failure.
  • Encode service and scope with URL.searchParams.
  • Rebuild anonymous fallback requests without credential headers or refresh-token bodies.
  • Add focused authentication policy and HTTP behavior tests.

Validation

  • 41 focused OCI authentication tests pass.
  • yarn type-check
  • yarn lint
  • yarn package
  • Packaged CLI help exposes the new global option.

Fixes github/codespaces#24328.

Validate registry-provided bearer realms, restrict cross-origin credential forwarding, and add an explicit registry-to-auth-host compatibility option.

Co-authored-by: Kaniska <kaniska244@github.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Hardens OCI registry Bearer-token authentication by validating registry-provided realm URLs, constraining cross-origin auth host usage, disabling token-request redirects, and ensuring service/scope are encoded to prevent SSRF and credential forwarding.

Changes:

  • Add realm admission + credential-forwarding policy with built-in and user-configured registry→auth-host mappings.
  • Disable redirects for token endpoint requests and rebuild anonymous fallback requests to avoid replaying credentials.
  • Add focused tests for realm policy, redirect refusal, and query encoding; wire the new test into CI.
Show a summary per file
File Description
src/spec-configuration/httpOCIRegistry.ts Implements realm validation, cross-origin auth-host policy, credential-forwarding rules, redirect suppression for token requests, and safe URL parameter encoding.
src/spec-utils/httpRequest.ts Adds a no-redirect request helper and returns responseUrl to support validating challenges against the final registry response URL.
src/spec-node/devContainersSpecCLI.ts Introduces the repeatable --allow-cross-origin-auth-host <registry>=<auth> global option and propagates configuration via env.
src/test/httpOCIRegistry.test.ts Adds unit/integration-style tests for realm admission, credential forwarding, redirect refusal, and query encoding behavior.
.github/workflows/dev-containers.yml Adds the new test to the CI matrix and excludes it from the “run all except above” batch to avoid duplicate execution.

Review details

Tip

Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

src/spec-utils/httpRequest.ts:121

  • requestResolveHeadersInternal treats any URL with hostname 'localhost' as plain HTTP, even when the URL scheme is https:. That silently downgrades https://localhost to an http request, which can break requests and can undermine scheme-based security decisions (including for token realms). Consider basing the transport strictly on the parsed protocol (and, if needed, handle localhost TLS separately).
		const plainHTTP = parsed.protocol === 'http:' || parsed.hostname === 'localhost';
		if (plainHTTP) {
			output.write('Sending as plain HTTP request', LogLevel.Warning);
		}
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread src/spec-node/devContainersSpecCLI.ts Outdated
@chrmarti

Copy link
Copy Markdown
Contributor Author

Companion VS Code Dev Containers integration: microsoft/vscode-remote-containers#1235

Propagate cross-origin auth host mappings explicitly through command, resolver, and registry request parameters instead of serializing them through the process environment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chrmarti

Copy link
Copy Markdown
Contributor Author

Follow-up 7b8e496 removes the internal environment-variable bridge. The option now propagates explicitly as typed command/resolver/request state across OCI paths. It also sets yargs nargs: 1 so repeated global mappings cannot consume the command positional, with packaged CLI and request-path regression coverage.

Treat an exact registry-to-auth-host mapping as authorization for the complete token exchange, including Docker identity and refresh tokens.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chrmarti

Copy link
Copy Markdown
Contributor Author

Updated trusted host-pair semantics in 87adb63: an exact HTTPS registry-to-auth-host mapping now authorizes both Basic and refresh/identity-token exchange. Added a real cross-authority Docker identitytoken POST regression test; all 41 focused tests, type-check, and lint pass.

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.

2 participants