Skip to content

[Bug]: SecretRef file provider broken on Windows 11 26200 — icacls /sid unsupported, preflight validator ignores allowInsecurePath #89223

Description

@CameronWeller

Summary

secrets.providers.<name>.source: "file" is broken on Windows 11 (build 26200) in OpenClaw 2026.5.28. Two compounding bugs:

  1. icacls /sid is not a valid flag on modern Windows builds — icacls.exe returns exit 87 ("Invalid parameter"). inspectWindowsAcl treats this as failure (ok: false), so every file-source secret resolves to source: "unknown" and assertSecurePermissions throws ACL verification unavailable on Windows for <path>.
  2. The documented escape hatch allowInsecurePath: true is silently ignored by the runtime config-write preflight validator (preflightRuntimeSnapshotWriterefreshHandler.preflightmutate-DajLmhPa.js:166). It works for the static secrets audit resolver but not for config.patch, so any subsequent config write fails with active SecretRef resolution failed.

Together, this makes SecretRef file-source unusable on modern Windows for any non-trivial setup that ever needs to mutate config (e.g., toggling dreaming.enabled).

Related: #70640 (closed) introduced allowInsecurePath as the fix for the original ACL-verification failure. That fix is incomplete because (a) it doesn't address the underlying icacls regression and (b) it's not honored consistently across resolver entry points.

Environment

  • OpenClaw 2026.5.28
  • Windows 11 Pro, build 26200
  • Powershell 7.x

Reproduction

# 1. Create a locked secret file (owner-restricted ACL — the "correct" way per Windows conventions)
$f = "$env:USERPROFILE\.openclaw\secrets\test.txt"
'test' | Set-Content -NoNewline $f
icacls $f /inheritance:r /grant:r "${env:USERNAME}:R" "NT AUTHORITY\SYSTEM:(R)" | Out-Null

# 2. In openclaw.json, add:
#    "secrets": {
#      "providers": {
#        "testfile": { "source": "file", "path": "...\test.txt", "mode": "singleValue" }
#      }
#    }
#    And a consumer, e.g. "gateway.auth.token": { "source": "file", "provider": "testfile", "id": "value" }

# 3. Static audit fails:
openclaw secrets audit --check
# → [REF_UNRESOLVED] ... ACL verification unavailable on Windows for C:\Users\...\test.txt

# 4. Add the documented workaround:
#    "secrets.providers.testfile.allowInsecurePath": true
#  Static audit now passes. But runtime config writes still fail:
openclaw gateway call config.patch --params '{"path":"plugins.entries.memory-core.config.dreaming.enabled","value":true}' --token <gateway-token>
# → GatewayRequestError: invalid config: active SecretRef resolution failed
#   (secrets.providers.testfile.path ACL verification unavailable on Windows for ...)

Source-level diagnosis

Tracing the failure path through the bundled dist:

  • permissions-ya3cPkFH.js:340inspectWindowsAcl calls icacls.exe <path> /sid. The /sid switch does not exist in icacls on Windows 11 26200; the executable returns exit 87 and the inspector reports ok: false.
  • fs-safe-DYWmA8_q.js:837assertSecurePermissions throws "ACL verification unavailable on Windows for ..." whenever the inspector returns ok: false and allowInsecurePath is not honored at that call site.
  • resolve-BB3PkFpN.js:121-127 — the static resolver honors allowInsecurePath correctly (this is why secrets audit clears once the flag is set).
  • mutate-DajLmhPa.js:166 — the runtime config-write path raises active SecretRef resolution failed without consulting allowInsecurePath. This is the regression that makes the escape hatch incomplete.

Suggested fix

  1. Drop / repair the icacls /sid call. The plain icacls <path> output already includes the SIDs and ACE list in a parseable form. Either drop the unsupported flag, or detect exit 87 and fall back to plain icacls.
  2. Honor allowInsecurePath consistently across all resolver entry points, including preflightRuntimeSnapshotWrite / refreshHandler.preflight. Today it's only respected by the static audit path.
  3. (Optional, nicer default): if ACL inspection genuinely cannot succeed, downgrade source: "unknown" to a warning (not a hard fail) when the file is owned by the current user and has restrictive permissions per Windows owner-rights conventions. That removes the need for an opt-in flag in the common single-user case.

Impact

Effectively forces users on modern Windows to keep gateway tokens and provider API keys plaintext in openclaw.json — which is exactly what the SecretRef machinery exists to prevent — or accept that they can't ever issue a runtime config write. I had to revert two SecretRef migrations to plaintext in order to enable memory-core.dreaming.enabled.

🤖 Filed by Archimedes (Claude Code) on behalf of @CameronWeller

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions