feat: raise the WinRM post-sync command limit to 8192 characters - #358
Conversation
Send the script to the host over stdin rather than on the PowerShell command line. cmd.exe rejects a command line past ~8155 characters (measured against a live Server 2016 host) and -EncodedCommand inflates a script ~3.2x on the way there, so the usable ceiling was ~2555. A fixed bootstrap now takes the command line and reads the real script from stdin. The script crosses base64-encoded, so the host's console code page cannot alter it: the ASCII-only restriction is gone, and the pkcs12 password no longer appears in the host's process table. Serialize SOAP requests per client. NTLM message sealing is RC4 keyed by a sequence counter, and the library issues the stdin Send concurrently with the output Receive without locking, desynchronizing the keystream and failing with "checksum does not match". Commands that write stdin also use a shorter WSMan operation timeout so the output poll releases the lock promptly instead of long-polling for 60s. Also shortens noOutcomeMessage to fit the control plane's 120-character failure-detail cap, which previously cut it mid-quote and dropped the part telling the operator what to do instead.
|
💬 Discussion in Slack: #pr-review-cli-358-feat-raise-the-winrm-post-sync-command-limit-to-8192-character Posted by Review Police — reviews, comments, new commits, and CI failures will stream into this channel. |
|
| Filename | Overview |
|---|---|
| packages/gateway-v2/winrm/winrm.go | Implements stdin-based script delivery and serialized SOAP transport, but applies the polling timeout to setup and input operations as well. |
| packages/gateway-v2/winrm_handler.go | Raises the product limit to 8192 characters while retaining byte-based validation that rejects valid non-ASCII commands. |
| packages/gateway-v2/winrm/winrm_command_test.go | Adds useful encoding and limit coverage, but command-limit tests exercise only single-byte ASCII input. |
| packages/gateway-v2/winrm/winrm_transport_test.go | Verifies transport serialization and timeout configuration but not the effect of that timeout on non-polling operations. |
Reviews (1): Last reviewed commit: "feat: raise the WinRM post-sync command ..." | Re-trigger Greptile
The gateway measured the command with len(), a byte count, while the
control plane's limit counts characters. Now that a command may be
non-ASCII, 8192 accented characters is 16384 bytes, so the gateway
rejected a command the UI had already accepted, after the certificates
were delivered.
Also raises the gateway cap and reframes it as a backstop rather than a
second copy of the product limit. The command arrives with placeholders
substituted, and {{certificateFiles}} grows with the number of
certificates delivered, so it needs headroom over what an operator can
save.
The short timeout applied to every operation on the client, not just the output poll it was meant for. Shell creation, Command, Send, Signal and Delete inherited a two-second budget, and none of them retries on a w:TimedOut fault, so a host that was merely slow failed the sync outright. It existed only to break a standoff: the output poll held the transport lock waiting for output, and no output could arrive until stdin was written, which needed the same lock. The bootstrap now writes one byte before it blocks on stdin, so the poll returns as soon as PowerShell starts and releases the lock on its own. The timeout override is gone and newClient is untouched again. The sentinel is stripped with TrimPrefix, which removes a single occurrence, so a command that itself opens by printing that byte keeps it.
Writing stdin takes two messages, the payload and then a separate one marking EOF, and PowerShell stays blocked in ReadToEnd until the second arrives. The output poll took the transport lock between them and waited for output that could not exist until EOF was sent, which needed that same lock. The ready sentinel only freed the first poll, so the standoff came back on the next one. Receive requests now wait on a gate that the EOF send opens, which is deterministic rather than dependent on lock handoff timing. The gate opens even when that send fails, and its wait honours the context, so neither a transport error nor a stalled write can park the poll past the command deadline. The sentinel and its flush assumption are gone with it. Verified end to end against Windows Server / PowerShell 5.1: exit code 0 in 1975ms, output intact including a blank line, a comment, and non-ASCII with a surrogate pair.
…se-windows-post-command-character-limit-to-8192
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 30250094 | Triggered | Generic Password | 8f1be78 | e2e/pam/redis_test.go | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Description 📣
Sends the post-sync PowerShell script to the Windows host over stdin instead of on the command line, lifting the effective ~2555-character ceiling imposed by cmd.exe to the new 8192 product limit and removing the reason a command had to be ASCII.
Paired with Infisical/infisical#7620, which raises the matching schema cap. PKI-348.
Type ✨
Tests 🛠️
go build ./... go vet ./packages/gateway-v2/winrm/ go test -race ./packages/gateway-v2/...Unit coverage added for the UTF-16LE encoding (including surrogate pairs), the base64 payload round trip, and the transport serialization. The serialization test is paired with a control test asserting the same probe does observe overlap when unwrapped, so it cannot pass vacuously.
Live-host validation is still outstanding. The mechanism was developed against a Windows Server 2016 / PowerShell 5.1 host, but the NTLM serialization fix has not yet been exercised end to end by a real sync.