Skip to content

draft: add package-owned gateway isolation controls - #26

Closed
MythiliMur wants to merge 1 commit into
mainfrom
draft/gateway-isolation-controls
Closed

MythiliMur wants to merge 1 commit into
mainfrom
draft/gateway-isolation-controls

Conversation

@MythiliMur

Copy link
Copy Markdown
Collaborator

Summary

Adds a package-owned clawctl gateway-isolation control surface:

  • status reports the requested next-launch posture;
  • enable and disable atomically persist a package-local requested state;
  • output explicitly says changes apply on the next manual Gateway restart.

Deliberately draft / not merge-ready

This change does not pretend an environment marker is isolation. The launcher rejects an enabled isolation request until a real Windows isolation boundary exists. The follow-up must create and verify that boundary (for example, the planned dedicated isolated agent session), then use this state as its source of truth.

The paired OpenClaw core proposal should remain platform-neutral: an authenticated, external-supervisor control bridge so Control UI can modify a launcher-owned setting without core hard-coding Windows isolation semantics.

Validation

  • dotnet test .\OpenClaw.Gateway.MSIX.slnx --configuration Release --no-restore
    • 60 passed

@clawsweeper

clawsweeper Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

🦞👀
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.


public GatewayIsolationState Read()
{
if (!File.Exists(_path))
try
{
return JsonSerializer.Deserialize<GatewayIsolationState>(
File.ReadAllText(_path)) ??
{
string directory = Path.GetDirectoryName(_path) ??
throw new InvalidOperationException("The isolation state path has no directory.");
Directory.CreateDirectory(directory);
string temporary = Path.Combine(directory, $".{FileName}.{Guid.NewGuid():N}.tmp");
try
{
File.WriteAllText(temporary, JsonSerializer.Serialize(state));
}
finally
{
if (File.Exists(temporary))
{
if (File.Exists(temporary))
{
File.Delete(temporary);
@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. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 10, 2026
@clawsweeper

clawsweeper Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex review: blocked before merge. Reviewed September 10, 2026, 7:17 PM ET / 23:17 UTC.

ClawSweeper review

What this changes

Adds package-owned commands to save and display a requested Gateway isolation setting, plus a launch guard for explicitly supplied enabled state.

Merge readiness

⛔ Blocked before merge - 11 items remain

Keep open as a draft: current main does not provide these controls, and the contribution has distinct value, but two concrete defects prevent safe use. Collaborator-authored work also requires explicit maintainer handling.

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

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The preparatory work is focused, but the public controls fail in NativeAOT and do not enforce their saved setting.
Proof confidence 🌊 off-meta tidepool Not applicable: The ordinary external-contributor proof gate does not apply to this COLLABORATOR-authored PR. Its reported unit tests cover persistence and the guard separately; native command execution, saved-state enforcement, and package-upgrade behavior remain unvalidated merge requirements.
Patch quality 🦪 silver shellfish (2/6) Security review found an item that needs attention.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: The ordinary external-contributor proof gate does not apply to this COLLABORATOR-authored PR. Its reported unit tests cover persistence and the guard separately; native command execution, saved-state enforcement, and package-upgrade behavior remain unvalidated merge requirements.
Evidence reviewed 9 items Verified scope and repository: Origin matches the target repository. The host-verified introduced comparison covers nine files at cb2adfc; current-main differences were not attributed to this branch.
Saved preference bypasses production launch: RunAsync calls CreateStartInfo without isolation state, then starts the Node process through WindowsKillOnCloseJob. The new guard only observes an explicitly supplied argument; production startup never reads GatewayIsolationStore.
Reflection-based persistent state: The new store uses default JsonSerializer overloads for both reading and writing. No generated JSON context is supplied.
Findings 2 actionable findings [P1] Enforce the saved isolation request before starting Node
[P1] Use generated JSON metadata for the NativeAOT launcher
Security Needs attention Saved isolation request does not constrain process launch: Production startup ignores the new persisted preference and bypasses the rejection guard, allowing an ordinary interactive-session process despite a requested isolation posture.

How this fits together

The Windows package exposes clawctl for package management and openclaw for launching the bundled CLI through device-installed Node.js. This change stores an isolation preference beside launcher data, but the production process-launch path does not consume it.

flowchart TD
  A[clawctl isolation command] --> B[Saved isolation preference]
  B --> C[Requested status output]
  D[openclaw command] --> E[Production launcher]
  E --> F[Node process in interactive session]
  G[Explicit isolation argument] --> H[Unsupported isolation guard]
Loading

Decision needed

Question Recommendation
Should these public controls wait for the actual Windows isolation boundary, or may an explicitly unavailable preparation-only interface land first? Keep the controls in draft: Complete and verify the Windows boundary before exposing an enable command that promises isolation after restart.

Why: The body deliberately defers the security boundary, so deciding what users may safely be offered requires agreement on the staged product contract.

Before merge

  • Enforce the saved isolation request before starting Node (P1) - With a valid saved Enabled: true preference, GatewayLauncher.RunAsync still calls CreateStartInfo without the new argument and starts Node normally. No production startup path reads the store, so this guard never implements the rejection promised in the PR body. Connect the persisted request to the pre-launch decision and cover the real launch entrypoint; otherwise a manual restart silently runs without the requested isolation.
  • Use generated JSON metadata for the NativeAOT launcher (P1) - The packaged launcher publishes with NativeAOT, where reflection-based JSON serialization is disabled by default. JsonSerializer.Serialize(state) therefore throws for both enable and disable, and the matching default Deserialize overload fails when a state file exists. Ordinary JIT unit tests do not exercise this configuration. Supply source-generated metadata for both operations and validate the published native executable.
  • Resolve security concern: Saved isolation request does not constrain process launch - Production startup ignores the new persisted preference and bypasses the rejection guard, allowing an ordinary interactive-session process despite a requested isolation posture.
  • Resolve merge risk (P1) - The Windows isolation boundary remains deliberately unimplemented; the public command wording could cause users to expect protection after restarting.
  • Resolve merge risk (P1) - The new persisted preference lacks installed-MSIX evidence for fresh installation, retained settings across upgrade, and recovery from invalid state.
  • Resolve merge risk (P1) - GitHub reports merge conflicts, so integration with current main remains unverified.
  • Complete next step (P2) - Resolve the isolation landing contract, repair both findings, reconcile the branch with main, and validate native execution plus fresh-install and upgrade behavior before leaving draft.
  • Improve patch quality - Use source-generated JSON metadata and verify enable, disable, and status in the published NativeAOT package.
  • Improve patch quality - Connect persisted state to the production pre-launch decision and demonstrate that an unsupported enabled request prevents Node creation.
  • Improve patch quality - Establish the staged isolation contract and verify preference behavior on fresh installation and package upgrade.
  • Resolve maintainer decision - Resolve the maintainer decision shown above before merge.

Findings

  • [P1] Enforce the saved isolation request before starting Node — src/OpenClaw.Launcher/GatewayLauncher.cs:71-74
  • [P1] Use generated JSON metadata for the NativeAOT launcher — src/OpenClaw.Launcher/GatewayIsolationStore.cs:53
  • [high] Saved isolation request does not constrain process launch — src/OpenClaw.Launcher/GatewayLauncher.cs:71
Agent review details

Security

Needs attention: The requested isolation posture is not enforced at process creation; no additional supply-chain or reachable path-traversal defect was established.

Review metrics

Metric Value Why it matters
Production and test growth production +132/-4; tests +88/-0 Growth supports a new command and persistence surface, but the tests do not connect persisted state to production launch.

Merge-risk options

Maintainer options:

  1. Finish the isolation contract before landing (recommended)
    Keep the draft paused until production startup honors the setting and installed-package validation establishes the intended boundary and upgrade behavior.
  2. Land only explicitly unavailable preparation
    After maintainer agreement, narrow the interface, repair NativeAOT serialization, and verify saved-state compatibility without promising isolation.

Technical review

Best possible solution:

Keep isolation explicitly unavailable until a verified Windows boundary exists, with NativeAOT-safe preferences enforced before process creation and preserved across package upgrades.

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

Yes, source establishes both failure paths: startup ignores saved enabled state, and the new JSON overloads conflict with the package's NativeAOT contract. No runtime execution was performed.

Is this the best way to solve the issue?

Unclear as a landing strategy: package ownership is consistent with the existing launcher boundary, but shipping public enable controls before enforcement exists requires a narrower, explicit contract.

Full review comments:

  • [P1] Enforce the saved isolation request before starting Node — src/OpenClaw.Launcher/GatewayLauncher.cs:71-74
    With a valid saved Enabled: true preference, GatewayLauncher.RunAsync still calls CreateStartInfo without the new argument and starts Node normally. No production startup path reads the store, so this guard never implements the rejection promised in the PR body. Connect the persisted request to the pre-launch decision and cover the real launch entrypoint; otherwise a manual restart silently runs without the requested isolation.
    Confidence: 0.99
  • [P1] Use generated JSON metadata for the NativeAOT launcher — src/OpenClaw.Launcher/GatewayIsolationStore.cs:53
    The packaged launcher publishes with NativeAOT, where reflection-based JSON serialization is disabled by default. JsonSerializer.Serialize(state) therefore throws for both enable and disable, and the matching default Deserialize overload fails when a state file exists. Ordinary JIT unit tests do not exercise this configuration. Supply source-generated metadata for both operations and validate the published native executable.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.98

AGENTS.md: not found in the target repository.

Codex review notes: model internal, reasoning medium; reviewed against 51969c7b2022.

Labels

Label changes:

  • add P2: This is a bounded draft feature with important merge blockers, not evidence of an urgent regression affecting shipped users.
  • add merge-risk: 🚨 compatibility: The new persistent setting needs NativeAOT-compatible serialization and installed-package upgrade validation.
  • add merge-risk: 🚨 security-boundary: An enabled isolation preference is ignored by production startup despite output promising a change after restart.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🌊 off-meta tidepool and patch quality is 🦪 silver shellfish.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The ordinary external-contributor proof gate does not apply to this COLLABORATOR-authored PR. Its reported unit tests cover persistence and the guard separately; native command execution, saved-state enforcement, and package-upgrade behavior remain unvalidated merge requirements.

Label justifications:

  • P2: This is a bounded draft feature with important merge blockers, not evidence of an urgent regression affecting shipped users.
  • merge-risk: 🚨 security-boundary: An enabled isolation preference is ignored by production startup despite output promising a change after restart.
  • merge-risk: 🚨 compatibility: The new persistent setting needs NativeAOT-compatible serialization and installed-package upgrade validation.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🌊 off-meta tidepool and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The ordinary external-contributor proof gate does not apply to this COLLABORATOR-authored PR. Its reported unit tests cover persistence and the guard separately; native command execution, saved-state enforcement, and package-upgrade behavior remain unvalidated merge requirements.

Evidence

Security concerns:

  • [high] Saved isolation request does not constrain process launch — src/OpenClaw.Launcher/GatewayLauncher.cs:71
    Production startup ignores the new persisted preference and bypasses the rejection guard, allowing an ordinary interactive-session process despite a requested isolation posture.
    Confidence: 0.99

What I checked:

  • Verified scope and repository: Origin matches the target repository. The host-verified introduced comparison covers nine files at cb2adfc; current-main differences were not attributed to this branch. (cb2adfcc7d52)
  • Saved preference bypasses production launch: RunAsync calls CreateStartInfo without isolation state, then starts the Node process through WindowsKillOnCloseJob. The new guard only observes an explicitly supplied argument; production startup never reads GatewayIsolationStore. (src/OpenClaw.Launcher/GatewayLauncher.cs:14, cb2adfcc7d52)
  • Reflection-based persistent state: The new store uses default JsonSerializer overloads for both reading and writing. No generated JSON context is supplied. (src/OpenClaw.Launcher/GatewayIsolationStore.cs:53, cb2adfcc7d52)
  • NativeAOT production contract: The launcher enables PublishAot for runtime-specific builds; packaging scripts explicitly publish NativeAOT. Current CONTRIBUTING.md requires source-generated JSON metadata and NativeAOT validation for JSON changes. (src/OpenClaw.Launcher/OpenClaw.Launcher.csproj:16, cb2adfcc7d52)
  • System.Text.Json runtime contract: Microsoft documents that trimmed builds disable reflection-based serialization by default and that these calls then throw InvalidOperationException. Source-generated metadata is the supported alternative: System.Text.Json source generation. The dependency signal is the new store's direct System.Text.Json calls.
  • Current main does not implement isolation controls: Current main retains the transparent launch path and has no GatewayIsolationStore. README describes a dedicated isolated agent session as future work. No merged fixing PR or shipped implementation was established. (src/OpenClaw.Launcher/GatewayLauncher.cs:7, 51969c7b2022)

Likely related people:

  • anna-dingler: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • xlinush: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@MythiliMur

Copy link
Copy Markdown
Collaborator Author

This is being handled here - #28

@MythiliMur MythiliMur closed this Sep 11, 2026
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. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants