Skip to content

fix(profiles): refuse an @ before url hosts and uppercase image repository paths - #2358

Merged
freeqaz merged 4 commits into
mainfrom
fix-1267-1268
Oct 13, 2026
Merged

freeqaz merged 4 commits into
mainfrom
fix-1267-1268

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Two profile refusals still passed preflight and then failed or misbehaved at deploy time.

  • An @ before a URL host. Node drops an empty user info, so https://@host and https://:@host parse as https://host/. Preflight and the API accepted both. Helm 3.19.2 keeps the user info: helm template refused https://:@host and rendered https://@host with the @ still in it. The observability URL (fix(profiles): refuse observability URLs that parse as another host #2329) also dropped the @ without saying so (http://@192.0.2.10:3000/d).
  • An uppercase image repository path. The control-plane image rule (controlPlaneDigestImage) and the runtime rule (digestImage) accepted registry.example.invalid/Team/controller@sha256:.... Kubernetes refuses to pull that image (InvalidImageName), because only the registry host and the tag may use uppercase.

Change

  • scripts/render-installation-profile.mjs
    • New writtenUserinfo. Like URL parsing, it drops tabs and newlines and skips any slashes or backslashes after the scheme. It then reports any @ before the host.
    • httpOrigin (controlPlane.authBaseUrl) and parsedObservabilityUrl (controlPlane.observabilityUrl) refuse any value where it finds one.
    • Every caller now refuses user info before ipv4HostKept and the written-host percent checks run. That made the regexes' userinfo-skip group dead code, so it is removed (mutants H26 and I8).
    • New lowercaseImageRepository check for controlPlane.controllerImage, runtime.image and repository.image. It refuses uppercase in the repository path and allows it only in the registry host (the first component, when a / follows) and in the tag. This matches how kubelet splits the registry host from the path.
  • Chart (_helpers.tpl). auth.baseUrl refuses any @. The [?#] check is now [?#@]; the path, query and fragment are already refused there.
  • API and bootstrap Job. New refuseWrittenUserinfo in auth/configuration.ts, called on the raw OCC_AUTH_BASE_URL in server.mjs and in bootstrap-installation.mjs. Both refuse the value as AUTH_BASE_URL_INVALID.
  • Docs. One breaking-changes entry. Preflight now refuses uppercase paths that Kubernetes used to refuse only at pull time. It also refuses https://@host, which used to render. The profiles guide gets one sentence on each rule.

The chart still renders an uppercase repository path. Its image rule is shared with prepare-bootstrap-volume and the upgrade tooling, so the change stays in preflight, and a test documents the gap.

Verification

  • New rows:
    • profile-preflight-chart-parity: auth base URLs https://@console.example.com, https://:@console.example.com and https://@192.0.2.10 are refused by preflight and Helm 3.19.2. A new test refuses 4 uppercase-path images in each of the 3 image fields, and checks that Helm still renders the controller image. Accepted rows were added for an uppercase registry host or tag.
    • profile-renderer: 5 observability URLs with an @ before the host get the generic refusal, not the IPv4 one.
    • sign-in-chart-parity: the API, the bootstrap Job and the chart refuse https://@, https://:@ and https:@, and the real entrypoint refuses https://@console....
  • Each new row fails on main (abf6647):
    • parity on https://@192.0.2.10 and on Controller
    • the renderer observability test
    • sign-in (the import does not exist on main)
  • Mutants of the fix: 14 of 14 killed. Each one drops one call site (renderer origin, renderer observability, chart, server.mjs, bootstrap, each image field), narrows the slash skip or tab stripping, or drops or widens a branch of the image regex.
  • Re-adding the removed userinfo-skip group (H26, I8) is now equivalent: user info is refused before that regex runs.
  • 20/20 pinned runs (taskset -c 20,21, load 3-7) of each touched test file: profile-preflight-chart-parity 21-23 s, profile-renderer 36-39 s and sign-in-chart-parity 61-65 s.
  • profile-preflight-chart-parity, profile-renderer, sign-in-chart-parity, configuration-startup and bootstrap-volume pass locally.
  • tsc --build, eslint and prettier --check pass on the touched files. Prettier was first shown to fail on a badly formatted file.
  • Open PRs touching these files (Support custom Installation profiles and readable Preset starters #2253, feat(deploy): configure hosted Codex discovery egress with profiles #1782, feat(dev): expose first-agent Control UI with OpenShell #1750, feat(auth): sign people in to occ with a device code (rfc-0019) #1619): git merge-tree shows the same conflicted files and hunk counts against this head as against main.

Risks

  • Low. A profile, values file or OCC_AUTH_BASE_URL with https://@host used to render and start; it is now refused, as the breaking-changes entry says. An uppercase image repository path never pulled.
  • Controller startup still accepts an empty user info in observability.url (it stores the host alone); only preflight refuses it.

…itory paths

Preflight, the chart and the API refuse any @ before the auth base URL host
(Node drops an empty user info such as https://@host or https://:@host, which
Helm keeps); preflight refuses it in observability URLs too. Preflight refuses
an uppercase repository path in controller, runtime and repository images,
which Kubernetes refuses to pull; an uppercase registry host or tag stays valid.
@freeqaz
freeqaz requested a review from a team as a code owner October 13, 2026 19:52
@clawsweeper

clawsweeper Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review blocked

Automated review did not run, so no review verdict was produced.

Reason: The input-safety check rejected material in this revision. No detected value, path, or scanner output is reproduced here.

Automatic review is on hold, including after source changes. Request a fresh re-review after resolving the failure; maintainers can also release the hold through an intentional scanner-policy update.

Next step: If this is a genuine credential, remove and rotate it. If it is an intentional test fixture, a maintainer must review and qualify it.

View the workflow run.

@freeqaz
freeqaz temporarily deployed to integration-qa-pr October 13, 2026 20:01 — with GitHub Actions Inactive
@freeqaz
freeqaz temporarily deployed to integration-qa-pr October 13, 2026 20:01 — with GitHub Actions Inactive
@freeqaz
freeqaz merged commit bdc3949 into main Oct 13, 2026
45 checks passed
@freeqaz
freeqaz deleted the fix-1267-1268 branch October 13, 2026 20:34
freeqaz added a commit that referenced this pull request Oct 13, 2026
…ls (#2362)

The chart, the image tools and Compute refuse an uppercase image repository path, and startup refuses any @ before the observability.url host, matching the profile preflight rules from #2358.

This branch was previously deployed

1 inactive deployment
integration-qa-pr — bf8f525b Deployed Oct 13, 2026 by freeqaz via QA advisory (kubernetes) #715
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.

1 participant