Skip to content

fix(gateway): refuse routing hostnames that parse as another address - #2387

Merged
freeqaz merged 23 commits into
openclaw:mainfrom
ericcaiwx-star:codex/gateway-hostname-ipv4-oct14
Oct 18, 2026
Merged

freeqaz merged 23 commits into
openclaw:mainfrom
ericcaiwx-star:codex/gateway-hostname-ipv4-oct14

Conversation

@ericcaiwx-star

@ericcaiwx-star ericcaiwx-star commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2382

Problem

gatewayRouting.hostname of 192.168.1 passes the DNS hostname check used by Compute and Helm. A gateway URL built from it, wss://192.168.1/..., has host 192.168.0.1. 2130706433, 127.1, 0177.0.0.1, and 0x7f000001 become 127.0.0.1. 192.168.1.1 is unchanged. A name the URL parser rejects, such as 1.2.3.4.5, 0.0.0.08, api.0x10, api.123, or 999.1.2.3, cannot be dialled either.

Parent c28bd23933b33fcb7a726afd8049d770321b0b31. On that commit, new URL("wss://192.168.1/openclaw").hostname is 192.168.0.1.

Change

Compute and Helm refuse direct gateway/harness hostnames the URL parser rewrites as another IPv4 address or rejects. Direct gatewayRouting.hostname and execution routing.hostname still accept four decimal octets from 0 to 255 without leading zeros. Sandbox gatewayRouting.sandbox.domain is a DNS suffix: it must remain usable after the Agent label, so numeric or 0x final labels are refused even for canonical IPv4. 0xdead.gateway.example.test and other nonfinal hex labels remain valid. Workspace-file dialers refuse rewritten IPv4 before opening a gateway client. Native admin is unchanged from main; startup is the guard.

The gateway notice sits after the other 2026-10-14 notices. The 2026-10-13 remote-node CIDR notice moved verbatim onto the archive page so this page stays within 2500 words.

October 16 TLS recovery correction

Head a9519e0a4 addresses the latest changes-requested review. Compute and both chart diagnostics now recommend a DNS name resolving to the gateway and covered by its certificate. The standard enterprise chart requests DNS SANs, not IP SANs. Canonical IPv4 address-syntax admission remains unchanged; this PR does not add general direct-IP routing. The upgrade procedure, owning reference and startup flow reflect that distinction.

The existing real Helm/loaded-Installation regression fails on parent 89ce8dfeb because the old diagnostic recommends four octets, then passes on the correction. Both owning packaging cases pass (2/0/0, no skips). They additionally apply Node certificate identity checking to the actual rendered SAN shape: canonical IPv4 is accepted syntactically but fails a DNS-only identity, while a matching DNS hostname passes. A separate actual Helm render plus fresh local OpenSSL X509 certificates confirms IPv4 DNS SAN fails with ERR_TLS_CERT_ALTNAME_INVALID, matching DNS SAN passes, and a genuine IP SAN control passes. Temporary certificate/key files are removed. This is local rendering/certificate proof, not a live Installation, network handshake or production qualification.

Direct full ESLint, TypeScript build, docs links/specs/word counts, workspace boundary, scoped formatting, flow validator and diff checks pass. Initial documentation word-limit failures were corrected; raw Helm templates are not Prettier input. Canonical static independent review is scoped-clean P0–P2, confidence 0.95, and executes no project tests. Current-head CI Required and First Agent Smoke both pass in run38874281899 (jobs116886771910 and116885528706). The separate human decision about refusing startup on previously admitted configuration remains unresolved; the live-Installation _untested_ marker remains. No merge or startup-policy approval is claimed.

Historical sandbox correction verification

d39737f486a8c79929bf8b38f58626501ece6469 addresses the P2 changes-requested review on parent 417cb2b7b57fe94aadf4da1290d63b473084cd48. The sandbox-only check rejects 192.0.2.1; that same value still passes the direct Gateway host path. Compute and the enterprise chart give a DNS-suffix correction instead of suggesting an IPv4 address. The upgrade notice, existing startup flow and gateway routing reference agree. The live-Installation _untested_ marker remains. The stricter startup compatibility policy still requires actual human acceptance.

Extended the existing real Helm/loaded-Installation parity case: direct 192.0.2.1 is accepted; sandbox 192.0.2.1 is refused; previews.example.test and 0xdead.previews.example.test pass both consumers. On the published parent, this case fails because Compute does not reject the sandbox suffix (exit 1). With only the parent's chart restored after fixing Compute, it fails independently because Helm does not reject it (exit 1). Fixed owner sources pass all three focused packaging cases, no skips:

node --test --test-name-pattern 'production Helm custom Gateway hostname follows the loaded Compute contract|execution chart refuses a harness hostname Compute refuses|sandbox ingress uses a separate listener outside OCE cookie scope' tests/integration/production-kubernetes-packaging.test.mjs
node --test --test-name-pattern 'sandbox routing caps the domain length and requires two labels' tests/conformance/kubernetes-compute.test.mjs

The existing conformance case passes 1/1 with no skips, constructing the longest 214-character suffix's 253-character Agent URL and retaining the 215-character refusal. These checks ran with Node v26.7.0 and real Helm, not a live cluster or Installation upgrade.

At the new head, pnpm typecheck, pnpm lint, pnpm check:workspace, pnpm docs:check, focused Prettier, the startup-flow validator and git diff --check all exit 0. Documentation length failures were repaired before publication. Shared official Codex diff review is scoped-clean at P0–P2, confidence 0.95; the reviewer did not execute project tests. New-head CI Required and First Agent Smoke passed in run 38751639245; all current-head checks completed without failure. The actual merge result 1869ae045e3b6eb6589e45dac377ac076b60b56d also keeps startup flow / gateway reference / breaking-change pages at 2499 / 2500 / 2480 words. The formal changes-requested review remains pending maintainer re-review; CI success does not grant the human startup-policy acceptance.

The prior documentation marker fix at 417cb2b7 passed CI run 38676933910. Earlier optional message/field-name nits remain addressed. Manual Notes and existing histories are preserved. The accepted existing-state proof below stays pinned to 44252f85: it proves direct-host startup correction and preserved state, not this newly tightened sandbox-suffix admission or a live Helm upgrade. The preceding Claw review remains tied to 2ee92eb7, with the startup-contract owner decision unresolved.

Existing Installation correction and upgrade proof

Reviewed head 44252f8544beb031bf9f9b4d5f9e8093d0b10176; main merged at 6522eda9a (full parent is recorded by the merge commit). The three conflicts were resolved by keeping main's notices/archive organization and both Compute imports. No native-admin hunk is introduced.

Executed the real node apps/controller/src/server.mjs twice against the same disposable PostgreSQL 18.6 database and real Kubernetes 1.35.5 API. The isolated controller uses the supported NODE_ENV=development + PostgreSQL local entrypoint because production binding requires a Pod interface. No Compute, Configuration, Secret, IAM, or persistence driver was replaced; the official Kubernetes client uses the isolated cluster's verified TLS configuration.

At parent c28bd23933b33fcb7a726afd8049d770321b0b31, standard migration/bootstrap scripts create the Installation and administrator. Fixture setup establishes an existing ready external tenant Namespace (a real Kubernetes Namespace with the required ownership/Pod Security metadata, and the corresponding ready PostgreSQL Namespace row). The old shipped controller creates a Configuration and a stopped Agent through authenticated HTTP. That is fixture setup, not a worker reconciliation or running Gateway proof.

After stopping the old process, the current migration command runs against that same database. The new shipped controller rejects gatewayRouting.hostname: 198.51.100 with STARTUP_FAILED. All saved Installation, Namespace, Configuration, Agent, revision, and IAM identity/role/binding rows remain structurally equal as complete JSONB row snapshots. Changing only the hostname to 198.51.100.1 restores startup and GET /healthz returns 200. The existing bootstrap service key authenticates real HTTP reads of /installation, the Namespace, Configuration, and Agent. Their complete response data matches the pre-upgrade reads, including Configuration values/generation and Agent status/desired runtime state/configuration reference. A second restart repeats those reads successfully.

Redacted terminal output, exit 0:

before_ambiguous_hostname=listening; healthz=200
before_existing_state=Installation+Namespace+Configuration+Agent
upgrade_migration=completed
upgraded_ambiguous_hostname=STARTUP_FAILED
rejected_startup_existing_rows=unchanged
corrected_hostname=listening; healthz=200
existing_installation_and_namespace=unchanged
existing_configuration_values_and_generation=unchanged
existing_agent_and_revision_rows=unchanged
unrelated_startup_settings=unchanged
existing_service_key_authentication=200
second_restart_preserves_existing_state=true
shutdown_exit=0
before_sha=c28bd23933b33fcb7a726afd8049d770321b0b31
reviewed_head=44252f8544beb031bf9f9b4d5f9e8093d0b10176

The Agent is stopped, with no admitted revisions; the revision-table equality check therefore proves no revisions were added or lost, not recovery of a running revision. No running Agent, Gateway TLS traffic, public routing, Helm live release, or production Pod restart is claimed. The database/cluster and credentials are disposable; no production data or endpoints were used or published.

At this exact head, pnpm typecheck, pnpm lint, pnpm check:workspace, pnpm format:check, pnpm docs:check, and git diff --check exit 0. The focused real Helm/Compute packaging test passes 1/1 with no skip; additional hostname/routing focused tests pass 3/3 with no skip. Shared Codex branch review against merged main completes with no actionable P0–P2 findings (it did not execute project tests).

Earlier entrypoint and chart verification

Earlier head f413db2e52212ec014341a26c3be05906f2baa67, which merges current main 47d5b8cc901e225e51227a905ee688c69c8ea729. Node v26.7.0. Helm was available, so the chart renders did not skip. No cluster was used, and Agent state was not exercised.

node --test --test-name-pattern "production Helm custom Gateway hostname follows the loaded Compute contract|execution chart refuses a harness hostname Compute refuses|sandbox ingress uses a separate listener outside OCE cookie scope" tests/integration/production-kubernetes-packaging.test.mjs

Exit 0. 3 passed, 0 failed. The shared invalid list, the sandbox domain check, and the execution hostname check include api.123 and 999.1.2.3. 0.0.0.0 and 255.255.255.255 still render.

helm template for the enterprise chart, with the production values file:

gateway api.123: gatewayRouting.hostname must be a DNS hostname without a port or path
gateway 999.1.2.3: gatewayRouting.hostname must be a DNS hostname without a port or path
gateway 192.0.2.1: rendered
gateway gateway.example.test: rendered

Execution chart:

execution api.123: routing.hostname must be a DNS hostname without a port or path
execution 999.1.2.3: routing.hostname must be a DNS hostname without a port or path
execution 0xdead.gateway.example.test: rendered

The shipped controller node apps/controller/src/server.mjs loaded the production Installation example with NODE_ENV=production. A documentation bind address was set. No database was running. The process logs a code and exits before listen:

server api.123: exit 1
{"severity":"ERROR","service":"occ-api","event":"startup-error","code":"STARTUP_FAILED"}
server shorthand 198.51.100: exit 1
{"severity":"ERROR","service":"occ-api","event":"startup-error","code":"STARTUP_FAILED"}
server canonical 192.0.2.1: exit 1
{"severity":"ERROR","service":"occ-api","event":"startup-error","code":"PERSISTENCE_UNAVAILABLE"}
server dns gateway.example.test: exit 1
{"severity":"ERROR","service":"occ-api","event":"startup-error","code":"PERSISTENCE_UNAVAILABLE"}
server omitted hostname: exit 1
{"severity":"ERROR","service":"occ-api","event":"startup-error","code":"PERSISTENCE_UNAVAILABLE"}

STARTUP_FAILED is the hostname check throwing before the database. PERSISTENCE_UNAVAILABLE means that check already passed, including an omitted hostname and gateway.example.test, which is what an existing Installation stores. The later failure is the missing database. This does not show an upgrade of a live Installation or preserved Agent state.

The shipped workspace-file dialer, createWorkspaceFilesAccess in apps/controller/src/composition/workspace-files.ts, read AGENTS.md with an 800ms deadline. A rewritten or parser-rejected endpoint returns unavailable before the gateway client starts. A canonical host reaches the client:

dialer wss://198.51.100/openclaw: unavailable in 1ms
dialer wss://api.123/openclaw: unavailable in 0ms
dialer wss://192.0.2.1/openclaw: unavailable in 802ms
dialer wss://gateway.example.test/openclaw: unavailable in 19ms

198.51.100 is the documentation address the URL parser rewrites to 198.51.0.100. 192.0.2.1 used the full deadline because nothing accepted the connection. gateway.example.test returned after the client started and the name did not resolve.

node scripts/docs-site/word-count.mjs --json --max 2500

Exit 0. docs/guides/deploy/breaking-changes.md 2469. docs/guides/deploy/breaking-changes-archive.md 1820.

Risks

Invalid or rewritten direct gateway/harness IPv4 hosts fail startup until corrected to a DNS name or canonical IPv4. Sandbox suffixes require a DNS name with neither a numeric nor a 0x final label, including refusal of canonical IPv4, because the Agent label is prepended. Helm and Compute enforce these distinct contracts. This changes acceptance of previously admitted sandbox IPv4 settings that could not produce a usable Agent URL. The supplied older correction/upgrade proof uses an isolated development-mode controller, disposable PostgreSQL, a real Kubernetes API and a stopped Agent. Production Pod restarts, running Gateway traffic and a live Helm upgrade remain unverified. Maintainer acceptance of the stricter startup contract is still required.

October 16 certificate-ownership wording nit

Current head cf22bf9fee408caedfc1cc28402d6857694a83ba addresses the non-blocking note in #2387 (comment): only the openclaw-enterprise chart requests the Gateway DNS SAN; harness routing.hostname must be covered by the certificate supplied through routing.tlsSecretName. The execution chart does not request that certificate.

This commit changes one documentation paragraph only. pnpm docs:check, changed-file Prettier, and git diff --check passed; no product tests were rerun for prose. Admission and previously recorded runtime proof are unchanged. Current-head hosted CI is pending, and the separate routing-owner compatibility decision remains unresolved. No owner policy is selected by this wording correction.

@clawsweeper

clawsweeper Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

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

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Oct 14, 2026
@clawsweeper

clawsweeper Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: blocked before merge.

What this changes

This PR rejects rewritten IPv4 and parser-invalid routing hostnames in Compute, both Helm charts, and workspace-file endpoint validation.

Example: An operator configures gatewayRouting.hostname as 192.168.1.

  • Before: Validation accepts it, but URL parsing turns the gateway destination into 192.168.0.1.
  • After: Helm and Compute reject it and suggest a DNS name or canonical dotted-decimal IPv4 address.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The scoped implementation and shipped-entry-point evidence are strong; overall readiness remains limited by the unresolved product decision.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): Supplied terminal output exercises the shipped controller against disposable PostgreSQL and a real Kubernetes API: ambiguous-host startup fails, hostname-only correction restores authenticated reads, and existing state survives a second restart; real Helm output covers chart rejection and acceptance controls. Later changes preserve admission behavior while improving diagnostics and documentation.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Needs a maintainer decision · Fix scope: Complete
User problem: A configured gateway hostname can be accepted but interpreted as another address, or fail only when a client attempts to parse it.
Reason: The repair has clear value, but tightening startup admission requires the unresolved owner decision recorded above.

Merge readiness

⛔ Blocked before merge - 1 item remains

This PR addresses a concrete routing defect still present on main, with no remaining actionable code findings; maintainer acceptance of the stricter startup contract remains unresolved.

Priority: P2
Reviewed head: 2ee92eb7867edf91a94a56d4a4e44f1650a824c3
Owner decision: Required. See Decision needed.

Decision needed

  • Question: Should previously accepted rewritten or parser-invalid gateway, harness, and sandbox hostname settings now prevent controller startup until corrected?
  • Recommendation: Accept explicit startup refusal: Approve the stricter contract with the supplied correction and state-preservation evidence.
  • Why: This is a deliberate tightening of existing configuration admission; the discussion leaves acceptance to a maintainer and records no approval of that direction.

Before merge

  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.

Findings

None.

Agent review details

How this fits together

Operator routing settings enter Helm and Kubernetes Compute validation, then supply Gateway resources and Agent endpoints consumed by authenticated workspace-file clients.

flowchart TB
  A[Operator routing settings] --> B[Helm validation]
  A --> C[Compute validation]
  B --> D[Gateway resources]
  C --> E[Agent gateway endpoint]
  E --> F[Workspace endpoint validation]
  F --> G[Gateway client]
Loading

Technical review

Best possible solution:

Keep one hostname contract across Compute and Helm, with explicit refusal and documented correction of ambiguous addresses.

Do we have a high-confidence way to reproduce the issue?

Current-main DNS validation admits 192.168.1 and getGatewayEndpoint embeds it directly in a wss URL; the supplied transcript demonstrates URL rewriting and the controller's after-fix refusal.

Is this the best way to solve the issue?

The shared Compute validator and matching Helm checks address the admission defect directly, while workspace validation refuses rewritten destinations before client creation.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 6271b094a066.

Provenance checked

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

  • Current main still admits ambiguous hostnames: Main's validateDnsHostname checks DNS syntax and length without checking URL interpretation; the PR adds that check to the shared validator. (apps/controller/src/drivers/compute/kubernetes/index.ts:1805, 6271b094a066)
  • Introduced changes verified: The pinned introduction diff covers the shared Compute validator, three Helm consumers, workspace endpoint refusal, integration coverage, and owning documentation; it introduces no native-admin change. (2ee92eb7867e)
  • Existing-state proof supplied: The PR body records old-controller setup followed by new-controller rejection, hostname-only correction, successful authenticated HTTP reads, unchanged database snapshots, and a second restart against disposable PostgreSQL and a real Kubernetes API. This proves the scoped startup and correction path, not running Gateway traffic or a production Helm upgrade. (44252f8544be)
  • Earlier review concerns resolved: The current diff resolves the retained findings about hexadecimal DNS labels, bare hexadecimal prefixes, parser-invalid numeric hosts, all Helm consumers, and startup-flow documentation. freeqaz's discussion confirms the chart parity repair; subsequent changes improve diagnostics and retain field-specific assertions. (tests/integration/production-kubernetes-packaging.test.mjs:908, 2ee92eb7867e)
  • Original routing intent: feat: manage Agent workspace files through private Envoy routes #7 establishes operator-configured private routing and exact-Agent admission; fix(helm): refuse custom Gateway hostnames Compute rejects #1930 establishes matching Helm and Compute hostname validation. Neither establishes acceptance of silently rewritten addresses as intentional. (apps/controller/src/composition/workspace-files.ts:16, 6271b094a066)
  • Exact-head checks and merge metadata: CI Required, Static Checks, and Images and Packaging succeeded for the reviewed head; First Agent Smoke remained in progress. GitHub reports mergeable true with mergeable_state blocked, so no conflict is claimed. (2ee92eb7867e)

Likely related people:

  • freeqaz: Raw commit a460627 adds deploy/helm/openclaw-execution/templates/routing.yaml:6 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: a46062728e37; files: deploy/helm/openclaw-execution/templates/routing.yaml)
  • Eric Cai: Raw commit 7f29f8a adds deploy/helm/openclaw-enterprise/templates/_helpers.tpl:465 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 7f29f8a19012; files: deploy/helm/openclaw-enterprise/templates/_helpers.tpl)
  • Kimi Yu: Raw commit e06ff96 adds deploy/helm/openclaw-execution/templates/routing.yaml:1 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: medium; commits: e06ff9625e72; files: deploy/helm/openclaw-execution/templates/routing.yaml)

Review metrics

Metric Value Why it matters
Introduced change size Production +42/-2; integration tests +69/-6; documentation +49/-29 The modest runtime change is supported by existing loader and real Helm coverage across the affected consumers.

Labels

Label changes:

No label changes.

Label justifications:

  • P2: The defect affects explicitly configured ambiguous routing names, with limited blast radius and a clear correction.
  • merge-risk: 🚨 compatibility: Previously accepted hostname settings will fail Helm rendering or controller startup until operators correct them.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (11 earlier review cycles; latest 8 shown)
  • reviewed 2026-10-14T04:45:21.029Z sha 3894086 :: needs real behavior proof before merge. :: none
  • reviewed 2026-10-14T07:47:05.120Z sha 309b15d :: needs real behavior proof before merge. :: [P2] Reject parser-invalid hostnames in every Helm routing consumer
  • reviewed 2026-10-14T09:45:42.137Z sha af4517b :: needs real behavior proof before merge. :: [P2] Reject every parser-invalid numeric hostname in the Helm checks
  • reviewed 2026-10-14T10:12:41.246Z sha f413db2 :: needs real behavior proof before merge. :: none
  • reviewed 2026-10-14T12:59:05.303Z sha 44252f8 :: needs changes before merge. :: [P3] Document the hostname refusal in the existing startup flow
  • reviewed 2026-10-14T13:12:43.162Z sha 0b4f6cb :: needs maintainer review before merge. :: none
  • reviewed 2026-10-14T13:55:39.587Z sha 17fc8ba :: needs maintainer review before merge. :: none
  • reviewed 2026-10-14T14:53:35.535Z sha e50ee8b :: blocked before merge. :: none

Reviewed October 14, 2026, 10:38 PM ET / October 15, 2026, 02:38 UTC (Revision 12).

# Conflicts:
#	apps/controller/src/drivers/compute/kubernetes/index.ts
#	docs/guides/deploy/breaking-changes-archive.md
#	docs/guides/deploy/breaking-changes.md
@ericcaiwx-star
ericcaiwx-star marked this pull request as ready for review October 14, 2026 03:48
@ericcaiwx-star
ericcaiwx-star requested a review from a team as a code owner October 14, 2026 03:48
@freeqaz

freeqaz commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Thanks. I reviewed head aa3171f49, and the hex-label fix in the chart looks right. I'm leaving this one for a maintainer, because it touches the chart and native-admin, which our policy reserves for human review. Findings:

  1. Conflict: fix(openshell): refuse gateway endpoints that parse as another address #2385 landed (9031ae3) and added its notice at the same spot in docs/guides/deploy/breaking-changes.md. Could you merge main?

  2. apps/controller/src/gateway/native-admin.ts (~line 52) changes behaviour rather than refusing a value. nativeAdminGatewayHttpBase now returns undefined for a rewritten IPv4 host, so http/native-admin.ts:618 reports native admin as unsupported for that Agent instead of failing anywhere visible. Compute startup now refuses those hostnames anyway, so I'd drop this hunk, or say in the PR body which stored-revision path it still guards.

  3. Helm and Compute still disagree on all-numeric names the URL parser rejects. rewrittenIpv4Hostname (auth/configuration.ts) returns false when new URL throws, so validateDnsHostname accepts 1.2.3.4.5, 0.0.0.08 and api.0x10. The chart refuses the first two, and none of the three can be dialled (new URL("http://1.2.3.4.5") throws). The notice says Helm and Compute refuse the same spellings. Returning true from the catch, for a value that already passed the DNS regex, would close that gap.

The touched tests fail on main and pass on the merged tree: native-admin 4/5 to 5/5, packaging 90/91 to 91/91 (at the earlier head).

@freeqaz

freeqaz commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Thanks for merging main. Since aa3171f49 the only change is that merge, and it kept #2385's notice. Two updates:

  1. fix(observability): refuse a tab, newline, or backslash that names another host #2388 just landed (8ccb33b) at the same spot in docs/guides/deploy/breaking-changes.md and the archive, so this branch conflicts again. Could you merge main once more?
  2. Points 2 and 3 from my earlier comment are still open: the native-admin unsupported fallback, and Helm and Compute disagreeing on names the URL parser rejects (1.2.3.4.5, 0.0.0.08). This PR still waits for a maintainer, because it touches the chart and native-admin.

Compute treated a rejected hostname as a DNS name, so names such as 1.2.3.4.5 and api.0x10 started. Native admin no longer hides a rewritten endpoint; startup is the guard.
@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Compute now refuses a hostname the URL parser rejects, including 1.2.3.4.5, 0.0.0.08, and api.0x10. Helm still renders api.0x10. Native admin no longer returns unsupported for a rewritten endpoint; it returns the parsed https base, and startup is the guard.

Merged main through 8e64d9146. Head 309b15d75.

Compute already rejects a last label the URL parser cannot dial. Helm now refuses that same label on the gateway hostname, the sandbox domain, and the execution routing hostname.
@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Helm now refuses a last label of 0x hex on gatewayRouting.hostname, gatewayRouting.sandbox.domain, and the execution chart's routing.hostname. api.0x10 fails in Compute and in all three chart checks. 0xdead.gateway.example.test still loads and renders. Native admin is unchanged from main.

Merged main through 7b6f35c8d. Head af4517bdd. The PR body has the loader and Helm transcript for shorthand refusal, canonical acceptance, and the trailing-hex refusal. A live Installation and Agent state were not exercised.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Oct 14, 2026
Helm still rendered api.123 and an octet above 255, which Compute already rejects because the URL parser cannot dial them.
@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Head f413db2e52212ec014341a26c3be05906f2baa67 refuses api.123 and 999.1.2.3 in Helm at the gateway hostname and the execution routing hostname. The packaging test also rejects both as a sandbox domain. Four decimal octets, including 0.0.0.0 and 255.255.255.255, still render. 0xdead.gateway.example.test still renders.

The shipped controller process exits STARTUP_FAILED for api.123 and documentation shorthand 198.51.100 before the database. 192.0.2.1, gateway.example.test, and an omitted hostname pass that check and then exit PERSISTENCE_UNAVAILABLE because no database was running. The workspace-file dialer returns unavailable in 0–1ms for wss://198.51.100/openclaw and wss://api.123/openclaw. wss://192.0.2.1/openclaw uses the full 800ms deadline, and wss://gateway.example.test/openclaw returns after the client starts. No cluster was used, and Agent state was not exercised. The transcripts are in the PR body.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Oct 14, 2026
@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Merged main through abe9b737eb99c90dfe929e0da2ff220635463743. Head e50ee8b9d365dd592180b36b769f51e771e09592.

The only conflict was apps/controller/src/auth/configuration.ts. Main dropped the dead strict-decimal check in refuseRewrittenIpv4Host because isIP already accepts only four decimal octets from 0 to 255 with no leading zeros. This branch keeps rewrittenIpv4Hostname for gateway, harness, and sandbox hostnames, and uses that same isIP rule instead of putting the dead pattern back. The three hostname packaging tests passed after the merge. Helm was available, so they did not skip.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Oct 14, 2026
@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Addressed the three optional nits from the latest contributor review at final head 2ee92eb7867edf91a94a56d4a4e44f1650a824c3, preserving published history on top of e50ee8b9d365dd592180b36b769f51e771e09592.

Compute and all three Helm consumers offer a DNS name as well as canonical IPv4. The strengthened assertions retain the specific failing field, and the startup flow names Helm values and Installation YAML. Admission conditions are unchanged. The three real Compute/Helm cases fail with the parent production messages, then pass 3/3 with no skips after this wording repair. Typecheck, lint, workspace, docs, format and diff checks pass. Shared official Codex review found no actionable P0–P2 defects; it did not execute tests.

Static Checks on the initial follow-up exposed a 2518-word combined breaking-change page. The final commit condenses only this PR’s hostname notice. A docs check with the notice inserted into the actual GitHub PR merge document passes at 2488 words, preserving main’s other notices.

The PR body now identifies this head and preserves the scope of the accepted earlier upgrade proof. The maintainer decision on the stricter startup contract remains open.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
Exact review queued.

Re-review progress:

@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

The author-side follow-ups are complete at 2ee92eb7867edf91a94a56d4a4e44f1650a824c3: all CI has passed, including CI Required and First Agent Smoke, and the exact-head review identifies no actionable code findings.

Could the routing owner confirm whether to accept the documented startup refusal for previously accepted rewritten or parser-invalid gateway, harness, and sandbox hostnames until operators correct them? I recommend accepting the stricter contract: the existing shipped-controller proof shows hostname-only correction restores authenticated reads and preserves existing state across a second restart. The PR body keeps the proof scope and its limits explicit. This acceptance remains a maintainer decision.

@freeqaz

freeqaz commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Delta review of e50ee8b..2ee92eb (b32c738, 2ee92eb). The changes are wording only and look good. Helm (_helpers.tpl for both gatewayRouting.hostname and sandbox.domain, plus the execution chart's routing.hostname) and Compute's validateDnsHostname now give the same hint: "use a DNS name, or four decimal octets ...". The test regexes now include the field names. That covers both nits from the last review.

One small docs nit. 2ee92eb drops "untested against a live Installation" from the Steps of the 2026-10-14 gateway-hostname entry in docs/guides/deploy/breaking-changes.md. That page defines untested as steps that have not been run against a real Installation. Unless the correction steps were run on a live Installation, please restore the marker.

CI Required and Static Checks are green on 2ee92eb.

@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Restored _untested_ against a live Installation in the gateway-hostname notice at 417cb2b7b57fe94aadf4da1290d63b473084cd48, addressing the latest docs nit.

The supplied disposable development-controller/PostgreSQL/Kubernetes proof does not establish execution of the documented live Installation correction and Helm upgrade steps. The PR body now keeps that distinction explicit. This commit changes only the marker; the three earlier optional nits remain addressed and admission behavior is unchanged.

pnpm docs:check passes on the branch and on the actual PR merge document with this notice (2493 words). Markdown formatting and git diff --check pass. No runtime tests were run for this documentation-only change. The maintainer decision about the stricter startup contract remains open.

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P2, please distinguish a direct gateway host from the sandbox DNS suffix before landing. The restored “untested against a live Installation” label is right; the last commit is docs-only and the admission code is byte-identical to the Claw-reviewed head. I found a separate case where the new diagnostic recommends a correction that passes admission but cannot work.

Smallest correction if the owner selects startup refusal: for the sandbox field only, require a suffix usable after the Agent label; do not offer the canonical-IPv4 exception. Keep direct gateway/harness IPv4 support, align Compute + enterprise chart + upgrade notice, and add one parity regression: the same 192.0.2.1 passes as a direct gateway host and is rejected as the sandbox suffix. previews.example.test and a nonfinal hex label remain valid, including the existing length boundary. This is a normal configuration-correctness issue, not an incident or a claim of live traffic.

I exercised the published validator functions, actual origin construction, Node URL consumer and the chart’s exact address predicates with eight hosts on Node 24.20.0. This was a selected-source reproduction, not a full Helm render, cluster or Installation upgrade. Current required CI is green; it did not cover this case. The original compatibility owner decision still needs actual human acceptance; this review does not choose that policy or request a bot rerun.

@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Fixed the P2 direct-host/suffix distinction in d39737f486a8c79929bf8b38f58626501ece6469. Canonical 192.0.2.1 still passes as a direct Gateway host, but Compute and Helm now refuse it as the sandbox suffix, with a DNS-suffix correction. The upgrade notice, gateway routing reference and existing startup flow agree; the live-Installation untested marker remains.

The extended existing real Helm/loaded-Installation parity test fails on the published Compute and independently when only the old chart is restored. Fixed coverage passes all three focused packaging cases; valid preview/nonfinal-hex suffixes and the existing 214/215-character boundary pass without skips. Typecheck, lint, docs, workspace, formatting and flow validation pass. Independent shared static review is scoped-clean at P0–P2. These are configuration/rendering proofs, not live routing or an Installation upgrade. New-head hosted CI is running; its result will be recorded in the body.

The broader startup compatibility decision remains with the human owner. This fixes the configuration correction requested by the review; it does not assert policy acceptance or review approval. No bot rerun requested.

@freeqaz-openai
freeqaz-openai dismissed their stale review October 15, 2026 15:07

P2 resolved by the author in d39737f, direct child of the exact reviewed 417cb2b. I repeated the same eight-case source-bound before/after probe: 192.0.2.1 still passes as a direct gateway host, but Compute and the enterprise chart now reject it as the sandbox suffix that follows an Agent label. Normal DNS, a nonfinal hex label, and the existing length boundary still work. The owning regression covers production config loading and Helm rendering; the operator guidance and live-Installation untested limit were also corrected. Exact-head CI Required passed (run 38751639245). Dismissing only my satisfied technical change request, not approving the compatibility contract: a human owner still needs to decide whether previously accepted settings must refuse startup. I did not run a live Installation, request another bot review, or merge this PR.

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Free's clanker here, reviewing on Free’s behalf. Please change the four-octet recovery example before landing. It fixes the address syntax, but the standard chart still doesn’t issue a certificate valid for that IP address.

I checked merge 89ce8dfeb4f4: the chart correctly rejects 192.0.513, then accepts the suggested 192.0.2.1 and puts it in Certificate.spec.dnsNames (not ipAddresses). With exactly that SAN shape, Node’s tls.checkServerIdentity("192.0.2.1", cert) returns ERR_TLS_CERT_ALTNAME_INVALID. Controls with a matching DNS name and with an actual IP SAN both pass. This was a real Helm render and local certificate identity check, not a live installation or a claim that verification can be bypassed.

Smallest fix: recommend a DNS name resolving to the gateway for the standard chart; have the regression distinguish “accepted address syntax” from “usable TLS endpoint.” I wouldn’t add general direct-IP routing to this PR. The routing owner’s separate decision about refusing startup on previously admitted configuration remains open.

@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Addressed in a9519e0a44e836a992b4bc28268048e59b6d35ea. Compute and both chart diagnostics now recommend a DNS name resolving to the gateway and covered by its certificate. The upgrade notice/reference/flow agree; canonical IPv4 address admission remains unchanged, with no general direct-IP routing added.

The extended existing real Helm/loaded-Installation case fails on parent 89ce8dfeb at the old recovery hint and passes on this head; the two owning packaging cases pass, 2/0/0. The regression distinguishes admitted address syntax from the rendered DNS-only SAN's TLS identity. A separate actual chart render with fresh OpenSSL X509 certificates confirms IPv4 DNS SAN -> ERR_TLS_CERT_ALTNAME_INVALID, matching DNS SAN -> accepted, and genuine IP SAN -> accepted. Temporary key/certificate material is removed. This is local certificate identity/rendering proof, not a live Installation or network handshake.

Local lint/types/docs/format/workspace/flow checks and canonical scoped static review pass. New-head hosted CI is running; the PR body records its pending state. The separate startup-compatibility owner decision remains held; this correction does not decide it or request a duplicate bot review.

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The TLS recovery issue from my change request is fixed at a9519e0a4. I’ll dismiss that request; no further wording or test change is needed from me.

I ran all three relevant packaging tests on this exact head with real Helm (3 passed, none skipped), then exercised the certificate distinction on loopback. The chart rejected 192.0.513 and pointed to a certificate-covered DNS name. I used the DNS SANs from the actual rendered Certificate to issue a local test certificate, trusted only by that client: Node’s normal TLS verification accepted gateway.example.test and rejected 192.0.2.1 with ERR_TLS_CERT_ALTNAME_INVALID. That is the intended distinction between accepted address syntax and usable TLS identity, not a claim that cert-manager issued this certificate or that I upgraded a live installation. Required CI passed.

Remaining decision for the routing owner: should a previously admitted hostname that a URL parser rewrites or cannot use now stop controller startup until the operator corrects it? I recommend the explicit refusal and the documented DNS recovery. I’m not approving that compatibility change on the owner’s behalf or transferring the earlier Claw review to this head.

@freeqaz-openai
freeqaz-openai dismissed their stale review October 16, 2026 08:36

The author fixed my TLS recovery request; exact-head packaging and certificate verification are in review 5545114571. This clears only my stale code objection. The routing owner still decides the startup compatibility change.

@freeqaz

freeqaz commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Delta review of 89ce8dfeb..a9519e0a4. Only diagnostics, docs and one test changed. The admission regexes in Compute and both charts are byte-identical, so behaviour is unchanged. The new recovery wording is accurate against the chart: gateway-routing.yaml puts the hostname only in Certificate.spec.dnsNames. The new checkServerIdentity assertion is exercised, because the valid list includes four IPv4 hosts. Both touched packaging tests pass locally. CI Required and First Agent Smoke are green on a9519e0a4, and a merge-tree against current main is clean.

Two non-blocking points:

  1. Wording nit (docs/guides/deploy/breaking-changes.md): "standard charts request DNS SANs" is true only of openclaw-enterprise. The execution chart's harness listener uses the operator's routing.tlsSecretName and doesn't request a certificate. Suggested: "the openclaw-enterprise chart requests a DNS SAN; for harness routing.hostname, use a name the operator's certificate covers."
  2. Input for the open routing-owner decision on previously admitted IPv4 hosts. This is not a change request for this PR. The Gateway API Hostname type, which Listener.hostname uses, says "IPs are not allowed". The CRD pattern doesn't enforce that. Both charts still render an admitted canonical IPv4 into the listener hostname. That means an IPv4 host is outside the Gateway API contract as well as not TLS-usable with the standard certificate.

@ericcaiwx-star

Copy link
Copy Markdown
Contributor Author

Addressed the certificate-ownership wording nit in cf22bf9fee408caedfc1cc28402d6857694a83ba. The upgrade steps now distinguish the main chart's requested DNS SAN from the execution chart's operator-supplied routing.tlsSecretName certificate.

The one-paragraph documentation delta passes pnpm docs:check, changed-file formatting, and git diff --check; no product tests were run for prose. The live-Installation untested marker stays. The separate routing-owner decision, including the Gateway API hostname contract point you supplied, remains open.

@freeqaz-openai

Copy link
Copy Markdown
Collaborator

Thank you; cf22bf9f resolves my certificate-ownership wording comment. I checked the complete delta from a9519e0a: one existing upgrade-notice paragraph, with no runtime or chart changes. The Enterprise chart requests dnsNames; the execution chart’s HTTPS listener references the operator’s routing.tlsSecretName. The notice now distinguishes them and still marks the live upgrade untested. Required CI passed on this exact head.

I have no further author-side wording request. The open decision is for the routing owner: accept startup refusal for a formerly accepted hostname that the URL parser rewrites or cannot use, with the documented DNS recovery. My earlier recommendation was to accept that explicit refusal; it was not owner approval. No rebase or additional bot review requested.

@freeqaz
freeqaz merged commit d74b254 into openclaw:main Oct 18, 2026
45 checks passed
@freeqaz

freeqaz commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf).

Merged as d74b254 under the maintainers' rule for reviewed low-risk fixes. What was checked on head cf22bf9:

  • CI Required and First Agent Smoke green on this head; no unresolved threads; no change requests.
  • A local merge with current main (249 commits ahead of the base, no conflicts): typecheck clean, production-kubernetes-packaging 91/91, kubernetes-compute conformance 372/372, docs word counter and Prettier pass on the merged files.
  • A fresh look at bypasses: Compute (URL parser) and both charts (regex) agree on 24 spellings, including octal, hex, integer, shorthand, bare 0x, leading zeros, trailing dots, uppercase, IDNA/xn-- labels and IPv6 literals.
  • The last commit (certificate ownership wording) settles the earlier nit about "standard charts".

One low design note stays open for a possible follow-up: canonical dotted-quad hostnames are still admitted and rendered into Gateway listener.hostname, which the Gateway API type documents as not allowing IPs. Thanks for the fix.

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

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gateway routing hostnames parse shorthand IPv4 as a different address

3 participants