Skip to content

docs(gateway): add Windows no-Docker hardening fallback guide#38932

Open
fantasyengineercdream wants to merge 3 commits intoopenclaw:mainfrom
fantasyengineercdream:docs/windows-no-docker-hardening
Open

docs(gateway): add Windows no-Docker hardening fallback guide#38932
fantasyengineercdream wants to merge 3 commits intoopenclaw:mainfrom
fantasyengineercdream:docs/windows-no-docker-hardening

Conversation

@fantasyengineercdream
Copy link
Copy Markdown

Summary

  • Problem: native Windows users who cannot use WSL2 or Docker often end up running OpenClaw directly on the host with no meaningful boundary at all.
  • Why it matters: this creates a docs gap for a real user segment and pushes them toward less safe host setups instead of a clearly documented fallback.
  • What changed: adds a docs-only Windows hardening fallback based on a dedicated low-privilege user, dedicated workspace/state paths, NTFS ACL allowlists, and verify/rollback steps.
  • What did NOT change: no runtime behavior, no config defaults, no sandbox claims, no installer/UI/channel-specific workflow.

Change Type

  • Docs
  • Security hardening

Scope

  • Gateway / orchestration
  • UI / DX

Why this is worth taking

This PR is valuable even though it is docs-only:

  1. It closes a practical gap between the current recommendation and what some Windows users can actually run.
  2. It aligns with the repo's stated focus on UX, docs, and runtime hardening.
  3. It gives maintainers a safer fallback to point users to instead of informal Discord-only advice.
  4. It is low-risk because it is explicit about limitations and does not change product behavior.

Linked Issue/PR

  • Closes: None
  • Related: None

User-visible / Behavior Changes

  • New docs page for native Windows hardening without Docker/WSL.
  • New cross-links from existing Windows / sandboxing docs.
  • No product behavior change.

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • Risk + mitigation: this PR is docs-only. The page explicitly states that the approach is weaker than Docker sandboxing and must not be presented as an equivalent security boundary.

Repro + Verification

Environment

  • OS: Windows 11
  • Runtime/container: native PowerShell, no Docker/WSL for the tested flow
  • Model/provider: OpenClaw with existing model configuration
  • Integration/channel (if any): none required for this doc validation
  • Relevant config (redacted): dedicated workspace + dedicated state path

Steps

  1. Create a dedicated local user.
  2. Grant NTFS ACL access only to the workspace/state paths.
  3. Start OpenClaw under the constrained user with isolated OPENCLAW_STATE_DIR / OPENCLAW_CONFIG_PATH.
  4. Run smoke-test and forbidden-path test.
  5. Run rollback commands and confirm cleanup path.

Expected

  • Constrained user can operate inside the intended workspace/state paths.
  • Constrained user does not retain broad routine access to unrelated paths that were explicitly denied.
  • Rollback steps are clear and reversible.

Actual

  • Validated on the reference Windows implementation using dedicated user + ACL allowlist + rollback flow.

Evidence

  • Trace/log snippets
  • Screenshot/recording

Reference implementation and validation material:

Human Verification

  • Verified scenarios:
    • dedicated user creation
    • workspace/state ACL grant
    • hardening verification script
    • rollback flow
  • Edge cases checked:
    • existing user path
    • missing directory handling
    • explicit limitations if the gateway still runs under the normal user
  • What I did not verify:
    • every possible Windows edition / enterprise policy environment
    • container-equivalent isolation, which this PR does not claim

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery

  • How to disable/revert this change quickly: revert the docs page and link additions.
  • Files/config to restore: docs/gateway/sandboxing.md, docs/platforms/windows.md, and the new doc page.
  • Known bad symptoms reviewers should watch for:
    • wording that overstates this as sandbox-equivalent
    • wording that appears to replace WSL2/Docker as the primary recommendation

Risks and Mitigations

  • Risk: users may overestimate the security boundary.

  • Mitigation: the guide repeatedly states that this is a weaker host hardening fallback, not a container boundary.

  • Risk: reviewers may read this as a proposal to bless native Windows as the default path.

  • Mitigation: the PR keeps WSL2 and Docker as the primary recommendation and adds this only as a documented fallback.

AI-assisted transparency

  • AI-assisted: Yes
  • Testing level: Human-verified on a working Windows reference setup
  • I understand the change and can explain the threat model, limitations, and rollback flow.

@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation gateway Gateway runtime docker Docker and sandbox tooling size: XS labels Mar 7, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 7, 2026

Greptile Summary

This PR adds a docs-only Windows host hardening guide (docs/gateway/windows-no-docker-hardening.md) for users who cannot run Docker or WSL2, along with cross-links from docs/gateway/sandboxing.md and docs/platforms/windows.md. The guide is well-structured: it clearly positions the approach as a blast-radius-reduction fallback (not a container equivalent), documents the threat model, and includes a rollback flow. Two issues were found in the PowerShell code samples:

  • Step 5 launch command has a variable-expansion bug: the runas double-quoted string causes PowerShell to expand $env:OPENCLAW_STATE_DIR and $env:OPENCLAW_CONFIG_PATH in the outer session, producing malformed assignment syntax in the child openclaw_bot session. The inner $env: variable names need to be backtick-escaped.
  • Rollback block 2 references $Principal without defining it: if a reader runs only the second rollback snippet, $Principal is undefined and the icacls /remove:d call silently no-ops, leaving deny ACEs in place. The definition should be repeated at the top of that block.

Confidence Score: 3/5

  • Safe to merge after fixing the PowerShell variable-expansion bug in the step 5 runas command, which would cause the gateway launch to fail for users following the guide.
  • The PR is docs-only with no runtime behavior changes, and the overall structure and security framing are sound. However, the step 5 code block contains a real PowerShell expansion bug that would silently corrupt the environment-variable assignments passed to the child session, meaning the gateway would not start correctly with the isolated state path. This is a user-facing correctness issue in the primary workflow snippet and warrants a fix before the guide ships.
  • docs/gateway/windows-no-docker-hardening.md — specifically the runas command in step 5 (lines 131-136) and the second rollback code block (lines 183-190).

Last reviewed commit: 51d2bf1

Comment on lines +131 to +136
runas /user:$env:COMPUTERNAME\openclaw_bot "powershell -NoProfile -NoExit -Command `"`
$env:OPENCLAW_STATE_DIR='$State'; `
$env:OPENCLAW_CONFIG_PATH='$State\openclaw.json'; `
Set-Location -LiteralPath '$Workspace'; `
openclaw gateway`""
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

$env: variables expanded by calling session, breaking inner assignments

This runas command wraps the inner PowerShell command in a double-quoted string. PowerShell expands $env:OPENCLAW_STATE_DIR and $env:OPENCLAW_CONFIG_PATH in the outer session before passing the string to runas. Since those variables are almost certainly empty in the outer session, the resulting inner command becomes something like:

='D:\OpenClawWorkspace\.openclaw-state'; `
='D:\OpenClawWorkspace\.openclaw-state\openclaw.json'; `

which is invalid PowerShell syntax and will fail silently or with a parse error in the child session. The $State and $Workspace variables (plain PS variables, not $env:) are correctly expanded by the outer session and should remain as-is. Only the $env: variable names on the left-hand side of the assignments need to be escaped.

Fix by escaping the inner $env: names with a backtick so they are not expanded by the outer session:

Suggested change
runas /user:$env:COMPUTERNAME\openclaw_bot "powershell -NoProfile -NoExit -Command `"`
$env:OPENCLAW_STATE_DIR='$State'; `
$env:OPENCLAW_CONFIG_PATH='$State\openclaw.json'; `
Set-Location -LiteralPath '$Workspace'; `
openclaw gateway`""
```
runas /user:$env:COMPUTERNAME\openclaw_bot "powershell -NoProfile -NoExit -Command `"`
`$env:OPENCLAW_STATE_DIR='$State'; `
`$env:OPENCLAW_CONFIG_PATH='$State\openclaw.json'; `
Set-Location -LiteralPath '$Workspace'; `
openclaw gateway`""
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/gateway/windows-no-docker-hardening.md
Line: 131-136

Comment:
**`$env:` variables expanded by calling session, breaking inner assignments**

This `runas` command wraps the inner PowerShell command in a double-quoted string. PowerShell expands `$env:OPENCLAW_STATE_DIR` and `$env:OPENCLAW_CONFIG_PATH` **in the outer session** before passing the string to `runas`. Since those variables are almost certainly empty in the outer session, the resulting inner command becomes something like:

```
='D:\OpenClawWorkspace\.openclaw-state'; `
='D:\OpenClawWorkspace\.openclaw-state\openclaw.json'; `
```

which is invalid PowerShell syntax and will fail silently or with a parse error in the child session. The `$State` and `$Workspace` variables (plain PS variables, not `$env:`) are correctly expanded by the outer session and should remain as-is. Only the `$env:` variable names on the left-hand side of the assignments need to be escaped.

Fix by escaping the inner `$env:` names with a backtick so they are not expanded by the outer session:

```suggestion
runas /user:$env:COMPUTERNAME\openclaw_bot "powershell -NoProfile -NoExit -Command `"`
`$env:OPENCLAW_STATE_DIR='$State'; `
`$env:OPENCLAW_CONFIG_PATH='$State\openclaw.json'; `
Set-Location -LiteralPath '$Workspace'; `
openclaw gateway`""
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +183 to +190
```powershell
$Parent = "D:\"
Get-ChildItem -LiteralPath $Parent -Directory |
Where-Object { $_.FullName -ne "D:\OpenClawWorkspace" } |
ForEach-Object {
icacls $_.FullName /remove:d "$Principal" /T /C
}
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

$Principal undefined if code block is run in isolation

$Principal is defined in the first rollback code block (line 175), but this second rollback block references it without redefining it. If a reader copies and runs only this snippet (a common pattern when following step-by-step docs), $Principal will be an empty string in PowerShell, so icacls ... /remove:d "" will silently no-op or emit an unhelpful error, leaving the deny ACEs in place.

Repeating the definition at the top of this block makes it self-contained:

Suggested change
```powershell
$Parent = "D:\"
Get-ChildItem -LiteralPath $Parent -Directory |
Where-Object { $_.FullName -ne "D:\OpenClawWorkspace" } |
ForEach-Object {
icacls $_.FullName /remove:d "$Principal" /T /C
}
```
$Principal = "$env:COMPUTERNAME\openclaw_bot"
$Parent = "D:\"
Get-ChildItem -LiteralPath $Parent -Directory |
Where-Object { $_.FullName -ne "D:\OpenClawWorkspace" } |
ForEach-Object {
icacls $_.FullName /remove:d "$Principal" /T /C
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/gateway/windows-no-docker-hardening.md
Line: 183-190

Comment:
**`$Principal` undefined if code block is run in isolation**

`$Principal` is defined in the first rollback code block (line 175), but this second rollback block references it without redefining it. If a reader copies and runs only this snippet (a common pattern when following step-by-step docs), `$Principal` will be an empty string in PowerShell, so `icacls ... /remove:d ""` will silently no-op or emit an unhelpful error, leaving the deny ACEs in place.

Repeating the definition at the top of this block makes it self-contained:

```suggestion
$Principal = "$env:COMPUTERNAME\openclaw_bot"
$Parent = "D:\"
Get-ChildItem -LiteralPath $Parent -Directory |
  Where-Object { $_.FullName -ne "D:\OpenClawWorkspace" } |
  ForEach-Object {
    icacls $_.FullName /remove:d "$Principal" /T /C
  }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 51d2bf1e63

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +184 to +186
$Parent = "D:\"
Get-ChildItem -LiteralPath $Parent -Directory |
Where-Object { $_.FullName -ne "D:\OpenClawWorkspace" } |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use selected workspace parent in rollback ACL cleanup

The rollback instructions hardcode D:\ and D:\OpenClawWorkspace even though earlier steps present the workspace as configurable (for example, “such as D:\OpenClawWorkspace”). If a user chose a different workspace location, this cleanup loop will skip the directories where denies were actually added in step 4, leaving restrictive ACLs behind and making the rollback incomplete.

Useful? React with 👍 / 👎.

@fantasyengineercdream fantasyengineercdream force-pushed the docs/windows-no-docker-hardening branch from 9e6b341 to 3027dcf Compare March 8, 2026 03:45
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3027dcf5fe

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

intentionally blocked:

```powershell
runas /user:$env:COMPUTERNAME\openclaw_bot "powershell -NoProfile -Command `"Get-ChildItem -LiteralPath '$env:USERPROFILE'`""
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Verify denied access against a path this guide blocks

The forbidden-path check currently probes '$env:USERPROFILE', which is usually inaccessible to other non-admin users on Windows even without the sibling-deny ACLs from step 4, so this test can report a “pass” while your intended boundary is not actually enforced. In practice this gives false confidence: users can complete verification even if the deny loop was skipped or mis-targeted; the check should target one of the explicitly denied sibling directories (or a user-provided blocked path) to validate the hardening steps this page introduced.

Useful? React with 👍 / 👎.

@Takhoffman Takhoffman requested a review from a team as a code owner March 24, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker Docker and sandbox tooling docs Improvements or additions to documentation gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant