From b1ed13a2d758bfca044c88d91cd5b1461dd8168f Mon Sep 17 00:00:00 2001 From: "duanjialing.777" Date: Wed, 9 Sep 2026 16:23:44 +0800 Subject: [PATCH 1/2] fix(scheduler): avoid secret-shaped transport chunks Signed-off-by: duanjialing.777 --- .../scheduler/heartbeat_followup_cli.ts | 2 +- loopx/control_plane/scheduler/scheduler_hint.py | 10 ++-------- ...st_scheduler_host_followup_hint_transport.py | 17 +++++++---------- .../scheduler_heartbeat_followup_cli.test.ts | 3 ++- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/loopx/control_plane/scheduler/heartbeat_followup_cli.ts b/loopx/control_plane/scheduler/heartbeat_followup_cli.ts index 16dde6169f..f198009e77 100644 --- a/loopx/control_plane/scheduler/heartbeat_followup_cli.ts +++ b/loopx/control_plane/scheduler/heartbeat_followup_cli.ts @@ -148,7 +148,7 @@ function decodeSchedulerHostFactsChunks(chunks: string[]): Record MAX_ENCODED_FACTS_CHARS || - !/^[A-Za-z0-9_-]+$/.test(encoded) + !/^[A-Za-z0-9_+\/-]+$/.test(encoded) ) { throw new EffectRuntimeRequestError( "scheduler host facts are missing or exceed the encoded boundary", diff --git a/loopx/control_plane/scheduler/scheduler_hint.py b/loopx/control_plane/scheduler/scheduler_hint.py index d88dc486d3..e3f766e527 100644 --- a/loopx/control_plane/scheduler/scheduler_hint.py +++ b/loopx/control_plane/scheduler/scheduler_hint.py @@ -269,20 +269,14 @@ def _scheduler_host_followup_transport_args( sort_keys=True, separators=(",", ":"), ).encode("utf-8") - encoded = base64.urlsafe_b64encode(zlib.compress(raw, level=9)).decode("ascii") + encoded = base64.b64encode(zlib.compress(raw, level=9)).decode("ascii") encoded = encoded.rstrip("=") if len(encoded) > SCHEDULER_HOST_FACTS_MAX_ENCODED_CHARS: raise ValueError("scheduler host facts exceed the native CLI transport bound") result: list[str] = [] for index in range(0, len(encoded), SCHEDULER_HOST_FACTS_CHUNK_CHARS): chunk = encoded[index : index + SCHEDULER_HOST_FACTS_CHUNK_CHARS] - if chunk.startswith("-"): - # argparse treats a separate value beginning with "-" as another - # option. Bind only that ambiguous chunk with ``=``; retain the - # established two-argument shape for ordinary chunks. - result.append(f"{SCHEDULER_HOST_FACTS_CHUNK_FLAG}={chunk}") - else: - result.extend([SCHEDULER_HOST_FACTS_CHUNK_FLAG, chunk]) + result.extend([SCHEDULER_HOST_FACTS_CHUNK_FLAG, chunk]) return result diff --git a/tests/control_plane/test_scheduler_host_followup_hint_transport.py b/tests/control_plane/test_scheduler_host_followup_hint_transport.py index 518ab5d914..5e815e67a3 100644 --- a/tests/control_plane/test_scheduler_host_followup_hint_transport.py +++ b/tests/control_plane/test_scheduler_host_followup_hint_transport.py @@ -12,6 +12,7 @@ build_codex_app_scheduler_ack_hint, build_codex_app_scheduler_failure_hint, ) +from loopx.control_plane.runtime.public_safety import SECRET_LIKE_SURFACE_PATTERN FACTS_FLAG = "--scheduler-host-facts-chunk" @@ -176,14 +177,13 @@ def test_oversized_native_facts_fail_instead_of_falling_back_to_python() -> None ) -def test_native_facts_bind_dash_prefixed_chunks_as_option_values( +def test_native_facts_chunks_do_not_look_like_credentials( monkeypatch: pytest.MonkeyPatch, ) -> None: - encoded = ("A" * 384 + "-tail").encode("ascii") monkeypatch.setattr( - scheduler_hint.base64, - "urlsafe_b64encode", - lambda _value: encoded, + scheduler_hint.zlib, + "compress", + lambda _value, *, level: base64.urlsafe_b64decode("-ak-"), ) args = scheduler_hint._scheduler_host_followup_transport_args( @@ -192,11 +192,8 @@ def test_native_facts_bind_dash_prefixed_chunks_as_option_values( use_current_hint=True, ) - assert args == [ - FACTS_FLAG, - "A" * 384, - f"{FACTS_FLAG}=-tail", - ] + assert args == [FACTS_FLAG, "+ak+"] + assert SECRET_LIKE_SURFACE_PATTERN.search(args[-1]) is None def test_legacy_hint_builder_without_host_facts_keeps_the_compatibility_route() -> None: diff --git a/tests/control_plane_ts/scheduler_heartbeat_followup_cli.test.ts b/tests/control_plane_ts/scheduler_heartbeat_followup_cli.test.ts index bde24e5295..f1d099c31e 100644 --- a/tests/control_plane_ts/scheduler_heartbeat_followup_cli.test.ts +++ b/tests/control_plane_ts/scheduler_heartbeat_followup_cli.test.ts @@ -75,7 +75,8 @@ function hintPayload(): Record { function chunks(value: unknown): string[] { const encoded = deflateSync(Buffer.from(JSON.stringify(value), "utf8")) - .toString("base64url"); + .toString("base64") + .replace(/=+$/, ""); return encoded.match(/.{1,384}/g) ?? []; } From 4ad1d582ebeeec0737d9d7b164a16f1d92c3e3a0 Mon Sep 17 00:00:00 2001 From: "duanjialing.777" Date: Thu, 10 Sep 2026 13:13:11 +0800 Subject: [PATCH 2/2] fix(coordination): stabilize fence read errors Signed-off-by: duanjialing.777 --- loopx/control_plane/coordination/legacy_writer_fence.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/loopx/control_plane/coordination/legacy_writer_fence.ts b/loopx/control_plane/coordination/legacy_writer_fence.ts index 8a8f4507e1..81af31fbf1 100644 --- a/loopx/control_plane/coordination/legacy_writer_fence.ts +++ b/loopx/control_plane/coordination/legacy_writer_fence.ts @@ -142,10 +142,12 @@ export async function loadLegacyCoordinationWriterFence( return { status: "loaded", fence }; } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return { status: "missing" }; + const path = (error as NodeJS.ErrnoException).path; + const reason = error instanceof Error ? error.message : "legacy writer fence read failed"; return { status: "failed", reason_code: "legacy_writer_fence_read_failed", - reason: error instanceof Error ? error.message : "legacy writer fence read failed", + reason: typeof path === "string" ? reason.replace(` '${path}'`, "") : reason, }; } }