Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesstack72

Relationships

#2156 Windows: model runtime shell execution produces wrong output encoding and arg splitting

Opened by stack72 · 9/15/2026· Shipped 9/15/2026

Description

On Windows, the model runtime delegates shell commands to the system shell (PowerShell), which behaves differently from Unix sh in three ways:

  1. UTF-16LE output encoding: Model shell commands that write to files produce UTF-16LE encoded output (with BOM and null bytes interleaved) instead of UTF-8. This corrupts any downstream consumer reading the output as UTF-8.

  2. Argument splitting: PowerShell's echo (alias for Write-Output) outputs each argument on a separate line. echo scanning dev produces "scanning\ndev" instead of "scanning dev". This breaks any model or workflow that relies on echo producing space-separated output.

  3. Escape handling: \@ in key=value arguments is handled differently by PowerShell vs sh, causing literal @ to be misinterpreted.

Steps to Reproduce

  1. Create a model with run: "echo scanning dev"
  2. Execute the model on Windows
  3. Observe output contains scanning and dev on separate lines

Or for encoding:

  1. Create a model that writes vault-resolved secrets to a file via shell redirection
  2. Execute on Windows
  3. The output file contains UTF-16LE encoded text

Environment

  • Windows Server 2022 (GitHub Actions windows-latest)
  • swamp version: 20260915.001037.0-sha.c42457d4
  • Discovered via Windows UAT runner (swamp-uat#363)

Impact

12 UAT test failures across vault roundtrip (5), workflow vary_dimensions (5), dollar sign escaping (1), and \@ escaping (1).

Suggested Fix

Use cmd.exe /c with explicit UTF-8 codepage (chcp 65001) instead of PowerShell for shell command execution on Windows. Alternatively, use Deno's own file I/O (Deno.writeTextFile) instead of shell redirection for output capture.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 11 MOREREVIEW+ 9 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/15/2026, 8:27:31 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack729/15/2026, 6:56:02 PM
Editable. Press Enter to edit.

stack72 commented 9/15/2026, 7:10:30 PM

Investigation request

On a native Windows runner, can you run the failing UAT scenarios using cmd.exe /d /s /c "chcp 65001 >nul & <command>" and confirm whether they all pass?

Please include:

  1. Exact output/byte dumps for redirected non-ASCII text (e.g. p@ss!w0rd#%^&*() written to a file via shell redirection — show hex dump of the output file to confirm UTF-8 vs UTF-16LE)
  2. echo scanning dev output under cmd.exe /d /s /c — confirm it produces scanning dev\r\n on a single line rather than PowerShell's scanning\r\ndev\r\n
  3. \@ input handling — confirm cmd.exe passes \@ through literally in --input key=value\@thing arguments
  4. Identify any existing Windows UAT or supported models that rely on PowerShell-specific syntax (e.g. $env:VAR, Invoke-WebRequest, pipe semantics) — switching to cmd.exe would break those if they exist

This would confirm the suggested fix is viable before implementation.

stack72 commented 9/15/2026, 7:33:06 PM

Confirmed: cmd.exe vs PowerShell behavior verified on Windows

Tested on Windows Server 2022 (10.0.26100.33438):

cmd.exe

C:\>echo scanning dev
scanning dev

C:\>echo p@ss!w0rd#%^&*()
p@ss!w0rd#%&*()

C:\>echo value\@thing
value\@thing

All on single lines, \@ passed through literally. (^ consumed as cmd escape char — minor, not related to the main issue.)

PowerShell

PS C:\> echo scanning dev
scanning
dev

Each argument on a separate line — confirms the root cause.

Recommendation

Switching the model runtime shell from PowerShell to cmd.exe /d /s /c "chcp 65001 >nul & <command>" on Windows would fix the echo arg splitting and the UTF-8 encoding. The \@ passthrough also works correctly under cmd.exe.

One caveat: cmd.exe's ^ is an escape character, so echo p@ss!w0rd#%^&*() drops the ^. Model definitions using ^ in shell commands would need ^^ escaping under cmd.exe — but this is the standard cmd.exe behavior and matches what users on Windows already expect.

No existing Windows UAT models use PowerShell-specific syntax ($env:, Invoke-WebRequest, etc.) — all fixture models use POSIX-compatible echo and shell redirection.

stack72 commented 9/15/2026, 7:37:01 PM

Confirmed: cmd.exe + chcp 65001 produces clean UTF-8 file output

Tested on Windows 10.0.26100.33438, cmd.exe with chcp 65001:

C:\>chcp 65001
Active code page: 65001

C:\>echo café résumé naïve > out.txt
C:\>certutil -encodehex out.txt out.hex 4
C:\>type out.hex
63 61 66 c3 a9 20 72 c3  a9 73 75 6d c3 a9 20 6e
61 c3 af 76 65 20 0d 0a

Byte analysis:

  • c3 a9 = é (UTF-8, correct — appears 3x for café/résumé)
  • c3 af = ï (UTF-8, correct — naïve)
  • No ff fe BOM at start
  • No 00 null bytes between characters
  • 0d 0a = CRLF line ending (standard Windows)

This confirms that cmd.exe /d /s /c "chcp 65001 >nul & <command>" resolves all three issues: single-line echo output, UTF-8 file encoding, and literal \@ passthrough.

stack72 commented 9/15/2026, 7:52:02 PM

Injection test results: cmd.exe double quotes do NOT protect metacharacters. Tests with & | > < ^ all broke the echo command (values lost, not written to file). No actual file injection occurred (syntax errors prevented it), but secrets containing those chars are corrupted. Test 8 (UTF-8 non-ASCII) passed cleanly. Revised fix: use Deno.writeTextFile() for output capture instead of shell redirection.

stack72 commented 9/15/2026, 8:12:19 PM

Direction change: using PowerShell not cmd.exe. cmd.exe metachar handling is too fragile. PowerShell single-quotes are fully literal, UTF-8 works via OutputEncoding, and echo splitting is fixable with Write-Host or quoted strings.

Sign in to post a ripple.