Before wrapping up my internship, I wanted to preserve a set of revalidated findings without opening a burst of individual issues. These began as agent-identified candidates and were individually investigated against current main and existing GitHub work under my guidance. None requires private disclosure.
I worked on fixes for some of the original findings but was unable to complete everything. I am sharing the remaining list as a handoff for maintainers or external contributors who may find it useful. This is a record of my local notes, not a request to prioritize or fix everything. Please close, defer, combine, or split items however best fits the roadmap.
How to read this report
- The list contains 21 current findings. Older findings that were fixed or not substantiated are omitted.
- Impact and likelihood are intentionally separated. Some items have meaningful worst-case impact but narrow prerequisites or low expected frequency.
- Nothing below is presented as a release blocker.
- The security-adjacent items were reviewed against
SECURITY.md. They are suitable for public handling and do not require a private advisory based on the supported threat model currently documented.
- File locations were checked against
main on August 7, 2026, but line numbers may drift.
- Related open work is called out to reduce duplication. Some pull requests address only part of a finding.
Summary
| ID |
Finding |
Impact if triggered |
Trigger or scope |
Existing work |
Suggested disposition |
| NODE-1 |
Recording contracts disagree with implementation |
Truncated or mislabeled recordings and high process memory pressure |
An authorized screen or camera recording call |
PR #1007 fixed cancellation only |
Align the contract, validate formats, encode incrementally, and bound concurrency |
| NODE-2 |
MXC timeout cleanup can hang indefinitely |
One invocation slot can remain stuck; repeated hangs can exhaust all node slots |
An approved MXC command plus failed termination or inherited output handles |
PR #816 bounds the probe path only |
Bound termination and output-drain grace periods; add an MXC regression test |
| NODE-3 |
Fragmented WebSocket UTF-8 is decoded per receive chunk |
Silent Unicode corruption in operator or node JSON strings |
A multibyte code point split across receive-buffer boundaries |
PRs #1095 and #1120 do not fix decoding |
Accumulate bytes through end-of-message or use a stateful decoder |
| NODE-4 |
Full command text enters persistent logs |
Arbitrary positional secrets can persist locally and survive diagnostics sanitization |
system.run approval logs or system.run.prepare |
PR #1051 replaced legacy ownership but retained canonical logging |
Log executable, count, outcome, duration, and correlation metadata without argument values |
| NODE-5 |
Align WSL setup configuration with the safer script-delivery path |
Setup configuration passes through more process layers than necessary |
Clean local gateway setup inside the trusted appliance |
PR #659 established the preferred script-delivery pattern elsewhere |
Reuse the stdin-based path and add focused regression coverage |
| CONN-1 |
Scope repository-only CLI identity state to the selected gateway |
CLI behavior can differ from explicit endpoint and override expectations |
Narrow manual use of unshipped source tooling with persisted profile state |
CLI is not shipped; repository validation calls are stale |
Use gateway-scoped identity resolution and consistent override precedence |
| CONN-2 |
Legacy migration drops one of two valid credentials |
Shared-token-dependent features and later recovery can fail after upgrade |
Legacy profile contains both shared and bootstrap tokens |
No direct fix found |
Migrate both fields independently and add a combined-credential test |
| CONN-3 |
Gateway registry recovery is unsafe |
Saved gateways can disappear for a run; later writes may overwrite the only corrupt copy; startup can remain partial |
Malformed JSON or read-side I/O failure |
PR #948 hardened writes, not recovery reads |
Quarantine/preserve input, expose degraded state, and continue startup safely |
| CONN-4 |
Shared-token replacement reports success before authentication |
A healthy connection can be severed and invalid state persisted |
Trusted local UI or authenticated local MCP replacement with a bad token |
PR #1076 partially addresses WinUI flows, not the manager/MCP path |
Validate or await terminal state, then commit; otherwise roll back |
| CONN-5 |
Runtime settings writes are non-atomic |
Local preferences and capability posture can be lost after interruption |
Crash, power loss, disk-full, or I/O failure during save |
SetupEngine has a separate atomic writer |
Use same-directory temp write, durable replace, backup, and recovery |
| CHAT-1 |
Image preview cache collides and grows indefinitely |
Older rows can show newer images; memory remains retained until process exit |
Reused filenames or repeated local image sends |
PR #1119 fixes identity/isolation but not eviction |
Use immutable keys plus bounded eviction and lifecycle cleanup |
| CHAT-2 |
Chat Stop can render a queued final assistant frame |
Post-cancel content can render, complete the turn, and reach TTS |
Abort response is processed before a late runless final |
PR #1096 preserves the early-clear behavior |
Retain suppression until a new turn or carry run identity on chat frames |
| UI-1 |
Channels linking and recovery copy bypasses localization |
Significant setup and recovery flows remain English-only |
Non-English locale using channel linking/recovery |
PR #988 improved recovery but did not localize it |
Add runtime resource keys and replace English code-behind literals |
| UI-2 |
Skills mutation failures are success-shaped, and the icon action lacks an accessible name |
UI can show a change that was rejected; screen readers may get an unnamed action |
Skill enable/disable plus dynamic skill cards |
Existing accessibility scan does not render the card action |
Split into response-aware mutation handling and accessibility fixes |
| UI-3 |
Cron mutations discard failures |
Create/edit input can disappear, and remove/toggle state can be misleading |
Gateway rejection, disconnect, or send failure |
cron.run is response-aware; other mutations are not |
Add response-aware mutation APIs and update UI only after acceptance |
| UI-4 |
Settings-only hotkey registration can survive Unregister() |
Disabled hotkeys can continue reserving and invoking the Settings chord |
Voice registration fails while Settings registration succeeds |
PR #1088 preserves the service behavior |
Track registration state per hotkey and test partial registration |
| TOOL-1 |
SetupEngine tests are omitted from the root solution |
Root dotnet test misses an active suite despite documentation |
Local developer uses the documented root command |
CI runs the suite explicitly |
Add the project to the solution or correct the documentation |
| TOOL-2 |
Installer validator searches obsolete artifact names |
Default validation explicitly skips and provides no install/uninstall proof |
Running the legacy packaging validator without an explicit path |
Draft PR #1116 does not fix the locator |
Update or replace the legacy validator and decide whether to add a runtime lane |
| TOOL-3 |
GitVersion remains split between local/build and CI |
Future version-engine divergence can fail builds or releases |
A graph or tag on which 6.4.x and 6.8.2 differ |
Documentation now records the split; checks fail closed |
Align CI when practical; retain the cross-version guards until then |
| TOOL-4 |
OpenClaw.Cli lacks a dedicated CI lane |
Parser and credential regressions can escape focused coverage |
Changes to repository-only CLI source |
PR #1065 added indirect compilation and two process tests |
Add direct parser/credential tests or formally retire the CLI |
| TOOL-5 |
Piper extraction waits before draining stderr |
Optional voice installation can hang indefinitely |
Verbose extraction failure caused by abnormal destination state |
No direct fix found |
Drain stderr concurrently and add a high-volume child-process regression test |
Detailed notes
NODE-1: Recording contracts disagree with implementation
Current behavior
- MCP and
winnode documentation advertise screen.record WebM, maxWidth, a monitor alias, a 30 FPS default, and up to 300 seconds.
- The capability rejects non-MP4 formats, ignores
maxWidth and the monitor alias, defaults to 10 FPS, and the backend silently reclamps duration to 60 seconds.
ScreenRecordingService retains raw BGRA frames before encoding. At 1080p it can retain about 506 MiB within seconds, then truncate early.
camera.clip always creates MP4 but can report the arbitrary requested format and ignores advertised maxWidth.
- The earlier broad claim that camera still capture ignores width/quality is not current.
camera.snap applies those values.
Current locations
src/OpenClaw.Shared/Mcp/McpToolBridge.cs:245-268,327-338
src/OpenClaw.Shared/Capabilities/ScreenCapability.cs:137-171,195,233-240
src/OpenClaw.Shared/Capabilities/CameraCapability.cs:135-162,208-214
src/OpenClaw.Tray.WinUI/Services/ScreenRecordingService.cs:27-215
src/OpenClaw.Tray.WinUI/Services/CameraCaptureService.cs:192-331,685-763
Possible direction
Align the advertised contract with supported codecs and defaults, validate unsupported values, apply scaling consistently, encode incrementally rather than retaining raw frames, and serialize or cap concurrent recording memory.
NODE-2: MXC timeout cleanup can hang indefinitely
Current behavior
After cancellation, MxcExecutor attempts process-tree termination and then performs unbounded exit and output-drain waits. A failed kill or descendant retaining redirected handles can defeat the host timeout indefinitely. Each stuck call retains one of eight node invocation slots.
Current locations
src/OpenClaw.Shared/Mxc/DirectAppContainerExecutor.cs:103-129
src/OpenClaw.Shared/Mxc/MxcExecutor.cs:132-168
src/OpenClaw.Shared/Mxc/MxcAvailability.cs:367-405
src/OpenClaw.Shared/LocalCommandRunner.cs:92-165
Related evidence
Issue #28 and PR #38 fixed the analogous inherited-output-handle problem in the host runner. PR #816 applied a bounded drain to the MXC availability probe but not execution.
Possible direction
Use a bounded termination and drain grace period, abandon remaining handles safely, and add an MXC-specific timeout test. This is public availability hardening; a reliable slot-exhaustion harness should not be necessary in the issue.
NODE-3: Fragmented WebSocket UTF-8 is decoded per chunk
Current behavior
WebSocketClientBase calls Encoding.UTF8.GetChars independently for each receive chunk. UTF-8 permits a code point to span frame or receive-buffer boundaries, so valid text can become replacement characters before JSON parsing. Both operator and Windows node clients use this base.
Current location
src/OpenClaw.Shared/WebSocketClientBase.cs:256-312
Possible direction
Accumulate bounded raw bytes through EndOfMessage and decode once, or maintain a per-message Decoder. Add a test that splits a multibyte character across receives.
NODE-4: Full command text enters persistent logs
Current behavior
V2 exec approval logs include the canonical full argv, and system.run.prepare logs raw or fully formatted command text. Pattern sanitization cannot identify arbitrary positional secrets. Logs persist locally and may be included in an explicitly generated diagnostics bundle after another pass through the same sanitizer.
Current locations
src/OpenClaw.Shared/ExecApprovals/ExecApprovalV2NormalizationStep.cs:42-44
src/OpenClaw.Shared/ExecApprovals/ExecApprovalsCoordinator.cs:142-145,282-285,472-503
src/OpenClaw.Shared/Capabilities/SystemCapability.cs:193-225
src/OpenClaw.Tray.WinUI/Services/Logger.cs:23-59,90-158
Possible direction
Persist executable identity, argument count, decision, outcome, duration, and correlation identifiers without argument values. Keep any full-command diagnostic channel explicit and nonpersistent.
NODE-5: Align WSL setup configuration with the safer script-delivery path
Current behavior and scope
One gateway-configuration step still uses the direct process-argument path rather than the repository's stdin-based WSL script-delivery mode.
Revalidation found no supported untrusted observer during clean setup. The managed distro is a single-purpose trusted appliance at this point: the gateway is not yet running, no operator/node is paired, no agent or MCP service is active, and supported setup creates no second untrusted executable principal. This is defense-in-depth, not a supported-boundary vulnerability.
Current area
- SetupEngine gateway configuration and WSL command-runner paths
Possible direction
Use the existing stdin-based script transport and, where practical, a downstream configuration interface that does not place configuration values in command arguments. Add regression tests using synthetic values.
CONN-1: Scope repository-only CLI identity state to the selected gateway
Current behavior and practical scope
The source-only gateway validation CLI combines endpoint overrides with profile-level identity state. Under narrow persisted-state conditions, inherited identity precedence can differ from the override behavior described by CLI help and output.
The CLI remains current source tooling but is not included in installers, portable ZIPs, or release assets. The repository validation script's CLI calls are stale, fail argument parsing, omit the now-required token, and normally use isolated profile state. Practical exposure therefore requires narrow manual contributor use.
Current area
OpenClaw.Cli endpoint, credential, and identity selection
- Shared gateway-client credential precedence
Possible direction
Resolve known endpoints through GatewayRegistry and use only the selected gateway's identity directory. Give unknown endpoints isolated identity state, make explicit overrides authoritative unless the user opts into stored identity, and repair or retire the stale validation script.
CONN-2: Dual-token legacy migration loses the shared token
Current behavior
When both legacy Token and BootstrapToken are present, migration stores bootstrap but drops the shared token. URL deduplication then prevents later backfill. This conflicts with the documented independent migration contract.
Current locations
src/OpenClaw.Tray.WinUI/Services/SettingsManager.cs:361-370
src/OpenClaw.Tray.WinUI/App.xaml.cs:2047-2075
src/OpenClaw.Connection/GatewayRegistry.cs:332-410
Possible direction
Persist both fields independently and add a migration test with both nonempty values.
CONN-3: Gateway registry recovery is unsafe
Current behavior
Malformed JSON produces an empty startup registry without a quarantine copy or explicit degraded state. The original file remains initially, but later migration or registry writes can replace it. Read-side I/O exceptions abort the remaining guarded startup sequence, leaving a partially initialized tray.
Current locations
src/OpenClaw.Connection/GatewayRegistry.cs:144-206,384-408
src/OpenClaw.Tray.WinUI/App.xaml.cs:516-522,712-727,1691-1717
src/OpenClaw.Shared/AsyncEventHandlerGuard.cs:19-37
Possible direction
Preserve or quarantine unreadable input, return a typed load/degraded result, prevent overwrite until recovery is acknowledged, and allow unrelated startup services to continue safely.
CONN-4: Shared-token replacement reports success before authentication
Current behavior
Shared-token-only and new records skip pre-mutation handshake validation. The manager persists and activates the supplied token, disconnects the old client, starts connection asynchronously, and returns success before authentication. Later failure does not restore the prior record or connection.
The affected manager-backed capability is local-MCP-only and authenticated. This is transactional correctness, not an authorization bypass.
Current locations
src/OpenClaw.Connection/GatewayConnectionManager.cs:555-573,1125-1219,1363-1416
src/OpenClaw.Tray.WinUI/App.CapabilityHandlers.cs:285-297
src/OpenClaw.Shared/Capabilities/AppConnectionCapability.cs:92-103
Related work
Open PR #1076 introduces terminal-state waiting and rollback for direct WinUI connection transactions, but the manager/MCP path remains success-shaped.
CONN-5: Runtime settings writes are non-atomic
Current behavior
SettingsManager.Save() directly overwrites settings.json. Interruption can leave empty or partial JSON, and load silently retains defaults with no last-known-good recovery. Active gateway credentials now live elsewhere, reducing the blast radius, but general settings and capability preferences can still be lost.
Current locations
src/OpenClaw.Tray.WinUI/Services/SettingsManager.cs:198-223,434-462
src/OpenClaw.Shared/SettingsData.cs:225-236
Possible direction
Use a same-directory temporary file, flush and atomic replace, preserve a backup, and recover explicitly from invalid primary content.
CHAT-1: Image preview cache collides and grows indefinitely
Current behavior
A process-wide filename-keyed cache lets a later local image with the same basename replace the bytes shown by older timeline rows. Raw bytes and decoded bitmap resources remain retained without a capacity or lifecycle policy.
Current locations
src/OpenClaw.Tray.WinUI/Chat/OpenClawChatDataProvider.cs:80-88,362-385,2201-2237
src/OpenClaw.Tray.WinUI/Chat/ReactorChatTimeline.cs:610-719,1026-1029
Related work
Open PR #1119 adds opaque per-image keys and origin isolation, fixing collision and historical mutation. It does not add eviction or cleanup, so lifetime growth remains.
CHAT-2: Chat Stop can render a queued final frame
Current behavior
After a successful abort acknowledgement, the provider immediately clears thread suppression. Chat frames carry no run ID, so a later final frame can pass, render, complete the turn, and reach automatic TTS. This is a local cancellation and transcript-integrity race, not a server-side abort or command-approval bypass.
Current locations
src/OpenClaw.Tray.WinUI/Chat/OpenClawChatDataProvider.cs:403-420,911-1000,2574-3053
src/OpenClaw.Shared/OpenClawGatewayClient.cs:426-438,3526-3727
Possible direction
Keep thread suppression until the next user-turn boundary, or carry run identity through chat events and filter aborted runs.
UI-1: Channels linking and recovery copy bypasses localization
Current behavior
QR linking, gateway/provider recovery, progress and error states, QR decode messages, plugin installation guidance, and unlink dialogs are still built from English literals in code-behind despite existing runtime localization infrastructure.
Current location
src/OpenClaw.Tray.WinUI/Pages/ChannelsPage.xaml.cs:1650-2055,2098-2225
Possible direction
Add format-capable ChannelsPage_* resources, route runtime text through LocalizationHelper, and update source contract tests to assert resource use rather than fixed English sentences.
UI-2: Skills mutation failures and accessibility
Current behavior
The enable/disable UI treats a transport-oriented Boolean as gateway acceptance, optimistically changes its cached state, and provides no user-visible rollback for later rejection. The dynamic icon-only action has a tooltip but no explicit automation name.
Current locations
src/OpenClaw.Tray.WinUI/Pages/SkillsPage.xaml.cs:97-126,283-294
src/OpenClaw.Shared/OpenClawGatewayClient.cs:1207-1210,1881-1909,2140-2145,2341-2348
Possible direction
Add a response-aware mutation result and surface rejection without committing local state. Give the button a localized automation name and add deterministic dynamic-card accessibility coverage.
UI-3: Cron mutations discard failures
Current behavior
Create/edit closes and clears the form unconditionally. Remove and enable/disable update local UI without rollback. The existing Task<bool> reports local send behavior, not gateway acceptance, so merely awaiting it would not handle server rejection.
Current locations
src/OpenClaw.Tray.WinUI/Pages/CronPage.xaml.cs:129-168,266-290,378-512
src/OpenClaw.Shared/OpenClawGatewayClient.cs:1168-1182,1881-1909,2140-2144,2290-2337
Possible direction
Model add/update/remove responses the way detailed cron.run is modeled, preserve the form on failure, and reconcile remove/toggle state only after acceptance.
UI-4: Settings-only hotkey registration can survive Unregister
Current behavior
Registration state is stored only from the Voice hotkey result. If Voice registration fails while the Settings chord succeeds, _registered remains false and public Unregister() returns before posting native unregister work.
Current locations
src/OpenClaw.Tray.WinUI/Services/GlobalHotkeyService.cs:108-120,227-355
src/OpenClaw.Tray.WinUI/App.xaml.cs:3469-3553,4321-4324
Possible direction
Track each hotkey independently and test all partial-registration combinations.
TOOL-1: SetupEngine tests are omitted from the root solution
Current behavior
OpenClaw.SetupEngine.Tests remains absent from openclaw-windows-node.slnx, while docs/TEST_COVERAGE.md says root dotnet test runs all local-development tests except E2E. CI explicitly builds and runs the suite, so this is developer test discovery and documentation correctness, not a release coverage gap.
Current locations
openclaw-windows-node.slnx:31-45
docs/TEST_COVERAGE.md:20-32,84-99
.github/workflows/ci.yml:139-149,258-269
TOOL-2: Installer validation searches obsolete artifact names
Current behavior
The Inno installer emits OpenClawCompanion-Setup-*, while the legacy uninstall-ordering test auto-discovers only OpenClawTray-Setup-*. Default invocation explicitly skips with exit code 2. The script also describes obsolete [UninstallRun] behavior, while current cleanup runs through [Code]. CI does not invoke this runtime validator.
Current locations
installer.iss:43-57
tests/PackagingTests/Test-InnoUninstallOrdering.ps1:89-114,230-256,384-397
tests/OpenClaw.Tray.Tests/InstallerIssAssertionTests.cs:43-52,69-122
Possible direction
Either modernize the locator and assertions or retire the legacy script in favor of an installed-app smoke lane. Avoid treating the current skip as a silent pass or a security issue.
TOOL-3: GitVersion remains split between local/build and CI
Current behavior
The repository-local tool and GitVersion.MsBuild are pinned to 6.8.2, while CI computes workflow outputs with 6.4.x. Documentation now records the split. Tag and assembly comparisons fail closed, so this is latent build/release reliability debt rather than silent artifact corruption.
Current locations
.config/dotnet-tools.json:5-10
src/Directory.Build.props:17-20
.github/workflows/ci.yml:100-117,512-523,751-812
docs/VERSIONING.md:18-24
TOOL-4: OpenClaw.Cli lacks a dedicated CI lane
Current behavior
CI has no explicit OpenClaw.Cli step, but Shared tests now reference and compile it and run two corrupt-identity process cases. Parser matrices, credential precedence, unknown URL behavior, and profile/per-gateway identity selection remain uncovered.
Current locations
.github/workflows/ci.yml:123-199
tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj:3-10
tests/OpenClaw.Shared.Tests/DeviceIdentityFailClosedTests.cs:381-423,472-495
Possible direction
Add a small dedicated test project/lane if the CLI remains supported, or retire the stale CLI and validation-script surface explicitly.
TOOL-5: Piper extraction can deadlock on redirected stderr
Current behavior
ExtractTarBz2 redirects stderr, waits synchronously for process exit, and only then reads stderr. The normal pinned archive is quiet, but sufficiently verbose extraction failures can fill the pipe and block both processes. This was reproduced with a synthetic abnormal destination state.
Current locations
src/OpenClaw.Shared/Audio/PiperVoiceManager.cs:161-238,338-371
src/OpenClaw.Tray.WinUI/Pages/VoiceSettingsPage.xaml.cs:646-720
Possible direction
Drain stderr concurrently before awaiting exit and add a regression child process that emits more than the pipe capacity. Keep reproduction isolated from real profile data.
Suggested maintainer handling
I deliberately did not open one issue per row. If any item is useful, please feel free to:
- split it into a focused issue;
- associate it with existing work;
- mark it help-wanted for an external contributor;
- defer it to the backlog; or
- close it if the current behavior is intentional or the cost is not justified.
I am happy for this consolidated report itself to remain only as an audit record rather than an active roadmap checklist.
Before wrapping up my internship, I wanted to preserve a set of revalidated findings without opening a burst of individual issues. These began as agent-identified candidates and were individually investigated against current
mainand existing GitHub work under my guidance. None requires private disclosure.I worked on fixes for some of the original findings but was unable to complete everything. I am sharing the remaining list as a handoff for maintainers or external contributors who may find it useful. This is a record of my local notes, not a request to prioritize or fix everything. Please close, defer, combine, or split items however best fits the roadmap.
How to read this report
SECURITY.md. They are suitable for public handling and do not require a private advisory based on the supported threat model currently documented.mainon August 7, 2026, but line numbers may drift.Summary
system.runapproval logs orsystem.run.preparecron.runis response-aware; other mutations are notUnregister()dotnet testmisses an active suite despite documentationOpenClaw.Clilacks a dedicated CI laneDetailed notes
NODE-1: Recording contracts disagree with implementation
Current behavior
winnodedocumentation advertisescreen.recordWebM,maxWidth, amonitoralias, a 30 FPS default, and up to 300 seconds.maxWidthand themonitoralias, defaults to 10 FPS, and the backend silently reclamps duration to 60 seconds.ScreenRecordingServiceretains raw BGRA frames before encoding. At 1080p it can retain about 506 MiB within seconds, then truncate early.camera.clipalways creates MP4 but can report the arbitrary requested format and ignores advertisedmaxWidth.camera.snapapplies those values.Current locations
src/OpenClaw.Shared/Mcp/McpToolBridge.cs:245-268,327-338src/OpenClaw.Shared/Capabilities/ScreenCapability.cs:137-171,195,233-240src/OpenClaw.Shared/Capabilities/CameraCapability.cs:135-162,208-214src/OpenClaw.Tray.WinUI/Services/ScreenRecordingService.cs:27-215src/OpenClaw.Tray.WinUI/Services/CameraCaptureService.cs:192-331,685-763Possible direction
Align the advertised contract with supported codecs and defaults, validate unsupported values, apply scaling consistently, encode incrementally rather than retaining raw frames, and serialize or cap concurrent recording memory.
NODE-2: MXC timeout cleanup can hang indefinitely
Current behavior
After cancellation,
MxcExecutorattempts process-tree termination and then performs unbounded exit and output-drain waits. A failed kill or descendant retaining redirected handles can defeat the host timeout indefinitely. Each stuck call retains one of eight node invocation slots.Current locations
src/OpenClaw.Shared/Mxc/DirectAppContainerExecutor.cs:103-129src/OpenClaw.Shared/Mxc/MxcExecutor.cs:132-168src/OpenClaw.Shared/Mxc/MxcAvailability.cs:367-405src/OpenClaw.Shared/LocalCommandRunner.cs:92-165Related evidence
Issue #28 and PR #38 fixed the analogous inherited-output-handle problem in the host runner. PR #816 applied a bounded drain to the MXC availability probe but not execution.
Possible direction
Use a bounded termination and drain grace period, abandon remaining handles safely, and add an MXC-specific timeout test. This is public availability hardening; a reliable slot-exhaustion harness should not be necessary in the issue.
NODE-3: Fragmented WebSocket UTF-8 is decoded per chunk
Current behavior
WebSocketClientBasecallsEncoding.UTF8.GetCharsindependently for each receive chunk. UTF-8 permits a code point to span frame or receive-buffer boundaries, so valid text can become replacement characters before JSON parsing. Both operator and Windows node clients use this base.Current location
src/OpenClaw.Shared/WebSocketClientBase.cs:256-312Possible direction
Accumulate bounded raw bytes through
EndOfMessageand decode once, or maintain a per-messageDecoder. Add a test that splits a multibyte character across receives.NODE-4: Full command text enters persistent logs
Current behavior
V2 exec approval logs include the canonical full argv, and
system.run.preparelogs raw or fully formatted command text. Pattern sanitization cannot identify arbitrary positional secrets. Logs persist locally and may be included in an explicitly generated diagnostics bundle after another pass through the same sanitizer.Current locations
src/OpenClaw.Shared/ExecApprovals/ExecApprovalV2NormalizationStep.cs:42-44src/OpenClaw.Shared/ExecApprovals/ExecApprovalsCoordinator.cs:142-145,282-285,472-503src/OpenClaw.Shared/Capabilities/SystemCapability.cs:193-225src/OpenClaw.Tray.WinUI/Services/Logger.cs:23-59,90-158Possible direction
Persist executable identity, argument count, decision, outcome, duration, and correlation identifiers without argument values. Keep any full-command diagnostic channel explicit and nonpersistent.
NODE-5: Align WSL setup configuration with the safer script-delivery path
Current behavior and scope
One gateway-configuration step still uses the direct process-argument path rather than the repository's stdin-based WSL script-delivery mode.
Revalidation found no supported untrusted observer during clean setup. The managed distro is a single-purpose trusted appliance at this point: the gateway is not yet running, no operator/node is paired, no agent or MCP service is active, and supported setup creates no second untrusted executable principal. This is defense-in-depth, not a supported-boundary vulnerability.
Current area
Possible direction
Use the existing stdin-based script transport and, where practical, a downstream configuration interface that does not place configuration values in command arguments. Add regression tests using synthetic values.
CONN-1: Scope repository-only CLI identity state to the selected gateway
Current behavior and practical scope
The source-only gateway validation CLI combines endpoint overrides with profile-level identity state. Under narrow persisted-state conditions, inherited identity precedence can differ from the override behavior described by CLI help and output.
The CLI remains current source tooling but is not included in installers, portable ZIPs, or release assets. The repository validation script's CLI calls are stale, fail argument parsing, omit the now-required token, and normally use isolated profile state. Practical exposure therefore requires narrow manual contributor use.
Current area
OpenClaw.Cliendpoint, credential, and identity selectionPossible direction
Resolve known endpoints through
GatewayRegistryand use only the selected gateway's identity directory. Give unknown endpoints isolated identity state, make explicit overrides authoritative unless the user opts into stored identity, and repair or retire the stale validation script.CONN-2: Dual-token legacy migration loses the shared token
Current behavior
When both legacy
TokenandBootstrapTokenare present, migration stores bootstrap but drops the shared token. URL deduplication then prevents later backfill. This conflicts with the documented independent migration contract.Current locations
src/OpenClaw.Tray.WinUI/Services/SettingsManager.cs:361-370src/OpenClaw.Tray.WinUI/App.xaml.cs:2047-2075src/OpenClaw.Connection/GatewayRegistry.cs:332-410Possible direction
Persist both fields independently and add a migration test with both nonempty values.
CONN-3: Gateway registry recovery is unsafe
Current behavior
Malformed JSON produces an empty startup registry without a quarantine copy or explicit degraded state. The original file remains initially, but later migration or registry writes can replace it. Read-side I/O exceptions abort the remaining guarded startup sequence, leaving a partially initialized tray.
Current locations
src/OpenClaw.Connection/GatewayRegistry.cs:144-206,384-408src/OpenClaw.Tray.WinUI/App.xaml.cs:516-522,712-727,1691-1717src/OpenClaw.Shared/AsyncEventHandlerGuard.cs:19-37Possible direction
Preserve or quarantine unreadable input, return a typed load/degraded result, prevent overwrite until recovery is acknowledged, and allow unrelated startup services to continue safely.
CONN-4: Shared-token replacement reports success before authentication
Current behavior
Shared-token-only and new records skip pre-mutation handshake validation. The manager persists and activates the supplied token, disconnects the old client, starts connection asynchronously, and returns success before authentication. Later failure does not restore the prior record or connection.
The affected manager-backed capability is local-MCP-only and authenticated. This is transactional correctness, not an authorization bypass.
Current locations
src/OpenClaw.Connection/GatewayConnectionManager.cs:555-573,1125-1219,1363-1416src/OpenClaw.Tray.WinUI/App.CapabilityHandlers.cs:285-297src/OpenClaw.Shared/Capabilities/AppConnectionCapability.cs:92-103Related work
Open PR #1076 introduces terminal-state waiting and rollback for direct WinUI connection transactions, but the manager/MCP path remains success-shaped.
CONN-5: Runtime settings writes are non-atomic
Current behavior
SettingsManager.Save()directly overwritessettings.json. Interruption can leave empty or partial JSON, and load silently retains defaults with no last-known-good recovery. Active gateway credentials now live elsewhere, reducing the blast radius, but general settings and capability preferences can still be lost.Current locations
src/OpenClaw.Tray.WinUI/Services/SettingsManager.cs:198-223,434-462src/OpenClaw.Shared/SettingsData.cs:225-236Possible direction
Use a same-directory temporary file, flush and atomic replace, preserve a backup, and recover explicitly from invalid primary content.
CHAT-1: Image preview cache collides and grows indefinitely
Current behavior
A process-wide filename-keyed cache lets a later local image with the same basename replace the bytes shown by older timeline rows. Raw bytes and decoded bitmap resources remain retained without a capacity or lifecycle policy.
Current locations
src/OpenClaw.Tray.WinUI/Chat/OpenClawChatDataProvider.cs:80-88,362-385,2201-2237src/OpenClaw.Tray.WinUI/Chat/ReactorChatTimeline.cs:610-719,1026-1029Related work
Open PR #1119 adds opaque per-image keys and origin isolation, fixing collision and historical mutation. It does not add eviction or cleanup, so lifetime growth remains.
CHAT-2: Chat Stop can render a queued final frame
Current behavior
After a successful abort acknowledgement, the provider immediately clears thread suppression. Chat frames carry no run ID, so a later final frame can pass, render, complete the turn, and reach automatic TTS. This is a local cancellation and transcript-integrity race, not a server-side abort or command-approval bypass.
Current locations
src/OpenClaw.Tray.WinUI/Chat/OpenClawChatDataProvider.cs:403-420,911-1000,2574-3053src/OpenClaw.Shared/OpenClawGatewayClient.cs:426-438,3526-3727Possible direction
Keep thread suppression until the next user-turn boundary, or carry run identity through chat events and filter aborted runs.
UI-1: Channels linking and recovery copy bypasses localization
Current behavior
QR linking, gateway/provider recovery, progress and error states, QR decode messages, plugin installation guidance, and unlink dialogs are still built from English literals in code-behind despite existing runtime localization infrastructure.
Current location
src/OpenClaw.Tray.WinUI/Pages/ChannelsPage.xaml.cs:1650-2055,2098-2225Possible direction
Add format-capable
ChannelsPage_*resources, route runtime text throughLocalizationHelper, and update source contract tests to assert resource use rather than fixed English sentences.UI-2: Skills mutation failures and accessibility
Current behavior
The enable/disable UI treats a transport-oriented Boolean as gateway acceptance, optimistically changes its cached state, and provides no user-visible rollback for later rejection. The dynamic icon-only action has a tooltip but no explicit automation name.
Current locations
src/OpenClaw.Tray.WinUI/Pages/SkillsPage.xaml.cs:97-126,283-294src/OpenClaw.Shared/OpenClawGatewayClient.cs:1207-1210,1881-1909,2140-2145,2341-2348Possible direction
Add a response-aware mutation result and surface rejection without committing local state. Give the button a localized automation name and add deterministic dynamic-card accessibility coverage.
UI-3: Cron mutations discard failures
Current behavior
Create/edit closes and clears the form unconditionally. Remove and enable/disable update local UI without rollback. The existing
Task<bool>reports local send behavior, not gateway acceptance, so merely awaiting it would not handle server rejection.Current locations
src/OpenClaw.Tray.WinUI/Pages/CronPage.xaml.cs:129-168,266-290,378-512src/OpenClaw.Shared/OpenClawGatewayClient.cs:1168-1182,1881-1909,2140-2144,2290-2337Possible direction
Model add/update/remove responses the way detailed
cron.runis modeled, preserve the form on failure, and reconcile remove/toggle state only after acceptance.UI-4: Settings-only hotkey registration can survive Unregister
Current behavior
Registration state is stored only from the Voice hotkey result. If Voice registration fails while the Settings chord succeeds,
_registeredremains false and publicUnregister()returns before posting native unregister work.Current locations
src/OpenClaw.Tray.WinUI/Services/GlobalHotkeyService.cs:108-120,227-355src/OpenClaw.Tray.WinUI/App.xaml.cs:3469-3553,4321-4324Possible direction
Track each hotkey independently and test all partial-registration combinations.
TOOL-1: SetupEngine tests are omitted from the root solution
Current behavior
OpenClaw.SetupEngine.Testsremains absent fromopenclaw-windows-node.slnx, whiledocs/TEST_COVERAGE.mdsays rootdotnet testruns all local-development tests except E2E. CI explicitly builds and runs the suite, so this is developer test discovery and documentation correctness, not a release coverage gap.Current locations
openclaw-windows-node.slnx:31-45docs/TEST_COVERAGE.md:20-32,84-99.github/workflows/ci.yml:139-149,258-269TOOL-2: Installer validation searches obsolete artifact names
Current behavior
The Inno installer emits
OpenClawCompanion-Setup-*, while the legacy uninstall-ordering test auto-discovers onlyOpenClawTray-Setup-*. Default invocation explicitly skips with exit code 2. The script also describes obsolete[UninstallRun]behavior, while current cleanup runs through[Code]. CI does not invoke this runtime validator.Current locations
installer.iss:43-57tests/PackagingTests/Test-InnoUninstallOrdering.ps1:89-114,230-256,384-397tests/OpenClaw.Tray.Tests/InstallerIssAssertionTests.cs:43-52,69-122Possible direction
Either modernize the locator and assertions or retire the legacy script in favor of an installed-app smoke lane. Avoid treating the current skip as a silent pass or a security issue.
TOOL-3: GitVersion remains split between local/build and CI
Current behavior
The repository-local tool and
GitVersion.MsBuildare pinned to 6.8.2, while CI computes workflow outputs with 6.4.x. Documentation now records the split. Tag and assembly comparisons fail closed, so this is latent build/release reliability debt rather than silent artifact corruption.Current locations
.config/dotnet-tools.json:5-10src/Directory.Build.props:17-20.github/workflows/ci.yml:100-117,512-523,751-812docs/VERSIONING.md:18-24TOOL-4: OpenClaw.Cli lacks a dedicated CI lane
Current behavior
CI has no explicit
OpenClaw.Clistep, but Shared tests now reference and compile it and run two corrupt-identity process cases. Parser matrices, credential precedence, unknown URL behavior, and profile/per-gateway identity selection remain uncovered.Current locations
.github/workflows/ci.yml:123-199tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj:3-10tests/OpenClaw.Shared.Tests/DeviceIdentityFailClosedTests.cs:381-423,472-495Possible direction
Add a small dedicated test project/lane if the CLI remains supported, or retire the stale CLI and validation-script surface explicitly.
TOOL-5: Piper extraction can deadlock on redirected stderr
Current behavior
ExtractTarBz2redirects stderr, waits synchronously for process exit, and only then reads stderr. The normal pinned archive is quiet, but sufficiently verbose extraction failures can fill the pipe and block both processes. This was reproduced with a synthetic abnormal destination state.Current locations
src/OpenClaw.Shared/Audio/PiperVoiceManager.cs:161-238,338-371src/OpenClaw.Tray.WinUI/Pages/VoiceSettingsPage.xaml.cs:646-720Possible direction
Drain stderr concurrently before awaiting exit and add a regression child process that emits more than the pipe capacity. Keep reproduction isolated from real profile data.
Suggested maintainer handling
I deliberately did not open one issue per row. If any item is useful, please feel free to:
I am happy for this consolidated report itself to remain only as an audit record rather than an active roadmap checklist.