Skip to content

fix: close the WinRM execution gaps from the 2026-08-20 windows-dev audit - #112

Merged
jonchun merged 6 commits into
mainfrom
fix/winrm-audit-gaps
Aug 21, 2026
Merged

jonchun merged 6 commits into
mainfrom
fix/winrm-audit-gaps

Conversation

@jonchun

@jonchun jonchun commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

A live capability audit against a real Windows Server 2025 host (via the new
env-gated e2e suite's methodology) found two cases where the command shellguard
executes over WinRM is not the pipeline the validator approved, plus stale
capability hints.

Fixes

  • Comma-list properties collapsed to one string: Select-Object -Property Name, Id, @{N='MB';E={...}} reconstructed as -Property 'Name,Id,@{...}' —
    a single string property name — returning a literal-named empty column with
    exit 0. Reconstruction now splits mixed comma-lists at top-level commas and
    quotes per element.
  • curl resolved to the Invoke-WebRequest alias: validated curl -k -m 10
    died at runtime on PS 5.1's alias (denied cmdlet, incompatible flags),
    leaving Windows hosts with no working HTTP-level check. Validated curl
    pipelines now execute as curl.exe, and a powershell-scoped
    curl.exe.yaml (GET-only, mirroring curl.yaml) admits the explicit
    spelling.
  • Hint inventory: winrmConnectHint now advertises Test-NetConnection
    and curl, and instructs agents to attempt tools and report "not
    recognized" as an installation gap instead of assuming policy blocks —
    the self-censorship failure mode behind both the 2026-08-05 and 2026-08-20
    incidents.
  • JVM tool scoping: jcmd/jmap/jstat were shell: bash while the hint
    advertised them on WinRM; their CLIs are identical on Windows, so they are
    now universal like jps/jstack.

Tests

  • Regression tests for both reconstruction bugs and curl.exe validation.
  • New TestLiveWinRM e2e suite (gated on SHELLGUARD_E2E_WINRM_*) running
    parse → validate → reconstruct → execute against a real host, with output
    assertions strong enough to catch exit-0 failures.

🤖 Generated with Claude Code

jonchun and others added 6 commits August 20, 2026 19:59
Two cases from the 2026-08-20 windows-dev live audit where the string we
execute was not the pipeline the validator approved:

- Comma-lists mixing identifiers with a hashtable (Select-Object -Property
  Name, Id, @{...}) were single-quoted as one token, so PowerShell received
  a single string property name and returned a literal-named empty column
  with exit 0. Split at top-level commas and quote per element.
- Bare curl resolves to PowerShell 5.1's Invoke-WebRequest alias, whose
  flags are incompatible with the validated curl manifest. Rewrite validated
  curl pipelines to curl.exe (in System32 since Server 2016 / Win10 1803).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sally

curl.exe mirrors curl.yaml's GET-only policy (with allows_flag_bundling,
since it is a native binary, not a cmdlet) so the explicit Windows spelling
validates alongside the alias-bypassed bare curl. jcmd/jmap/jstat lose their
shell: bash marking: the CLIs are identical on Windows and the WinRM hint
already advertised them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… WinRM hint

The 2026-08-05 and 2026-08-20 incidents were both hint-inventory lies:
agents treat omitted tools as unavailable and never attempt them. Name
Test-NetConnection and curl explicitly, and tell the agent that a
'not recognized' error is an installation gap to report, never a policy
block to assume.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every other test stops at string reconstruction, which is how both the
curl alias bug and the comma-list quoting bug shipped: exit-code-clean
failures that only a real Windows host exposes. Gated on
SHELLGUARD_E2E_WINRM_* so CI is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
govulncheck flags GO-2026-6218 (net/url), GO-2026-6090 (crypto/tls),
GO-2026-6088 (encoding/xml), and GO-2026-5972 (encoding/asn1) as reachable
from pre-existing code paths; all are fixed in go1.25.13.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonchun
jonchun merged commit 3bf5f7a into main Aug 21, 2026
2 checks passed
@jonchun
jonchun deleted the fix/winrm-audit-gaps branch August 21, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant